hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/tools/perf/util/annotate.c
....@@ -1,34 +1,48 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
34 *
45 * Parts came from builtin-annotate.c, see those files for further
56 * copyright notes.
6
- *
7
- * Released under the GPL v2. (and only v2, not any later version)
87 */
98
109 #include <errno.h>
1110 #include <inttypes.h>
12
-#include "util.h"
11
+#include <libgen.h>
12
+#include <stdlib.h>
13
+#include <bpf/bpf.h>
14
+#include <bpf/btf.h>
15
+#include <bpf/libbpf.h>
16
+#include <linux/btf.h>
17
+#include "util.h" // hex_width()
1318 #include "ui/ui.h"
1419 #include "sort.h"
1520 #include "build-id.h"
1621 #include "color.h"
1722 #include "config.h"
18
-#include "cache.h"
23
+#include "dso.h"
24
+#include "env.h"
25
+#include "map.h"
26
+#include "maps.h"
1927 #include "symbol.h"
28
+#include "srcline.h"
2029 #include "units.h"
2130 #include "debug.h"
2231 #include "annotate.h"
2332 #include "evsel.h"
2433 #include "evlist.h"
34
+#include "bpf-event.h"
2535 #include "block-range.h"
2636 #include "string2.h"
37
+#include "util/event.h"
2738 #include "arch/common.h"
2839 #include <regex.h>
2940 #include <pthread.h>
3041 #include <linux/bitops.h>
3142 #include <linux/kernel.h>
43
+#include <linux/string.h>
44
+#include <subcmd/parse-options.h>
45
+#include <subcmd/run-command.h>
3246
3347 /* FIXME: For the HE_COLORSET */
3448 #include "ui/browser.h"
....@@ -42,7 +56,7 @@
4256 #define DARROW_CHAR ((unsigned char)'.')
4357 #define UARROW_CHAR ((unsigned char)'-')
4458
45
-#include "sane_ctype.h"
59
+#include <linux/ctype.h>
4660
4761 struct annotation_options annotation__default_options = {
4862 .use_offset = true,
....@@ -134,13 +148,20 @@
134148 return 0;
135149 }
136150
151
+#include "arch/arc/annotate/instructions.c"
137152 #include "arch/arm/annotate/instructions.c"
138153 #include "arch/arm64/annotate/instructions.c"
154
+#include "arch/csky/annotate/instructions.c"
139155 #include "arch/x86/annotate/instructions.c"
140156 #include "arch/powerpc/annotate/instructions.c"
141157 #include "arch/s390/annotate/instructions.c"
158
+#include "arch/sparc/annotate/instructions.c"
142159
143160 static struct arch architectures[] = {
161
+ {
162
+ .name = "arc",
163
+ .init = arc__annotate_init,
164
+ },
144165 {
145166 .name = "arm",
146167 .init = arm__annotate_init,
....@@ -148,6 +169,10 @@
148169 {
149170 .name = "arm64",
150171 .init = arm64__annotate_init,
172
+ },
173
+ {
174
+ .name = "csky",
175
+ .init = csky__annotate_init,
151176 },
152177 {
153178 .name = "x86",
....@@ -170,6 +195,13 @@
170195 .comment_char = '#',
171196 },
172197 },
198
+ {
199
+ .name = "sparc",
200
+ .init = sparc__annotate_init,
201
+ .objdump = {
202
+ .comment_char = '#',
203
+ },
204
+ },
173205 };
174206
175207 static void ins__delete(struct ins_operands *ops)
....@@ -183,18 +215,18 @@
183215 }
184216
185217 static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
186
- struct ins_operands *ops)
218
+ struct ins_operands *ops, int max_ins_name)
187219 {
188
- return scnprintf(bf, size, "%-6s %s", ins->name, ops->raw);
220
+ return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw);
189221 }
190222
191223 int ins__scnprintf(struct ins *ins, char *bf, size_t size,
192
- struct ins_operands *ops)
224
+ struct ins_operands *ops, int max_ins_name)
193225 {
194226 if (ins->ops->scnprintf)
195
- return ins->ops->scnprintf(ins, bf, size, ops);
227
+ return ins->ops->scnprintf(ins, bf, size, ops, max_ins_name);
196228
197
- return ins__raw_scnprintf(ins, bf, size, ops);
229
+ return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
198230 }
199231
200232 bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
....@@ -210,7 +242,7 @@
210242 char *endptr, *tok, *name;
211243 struct map *map = ms->map;
212244 struct addr_map_symbol target = {
213
- .map = map,
245
+ .ms = { .map = map, },
214246 };
215247
216248 ops->target.addr = strtoull(ops->raw, &endptr, 16);
....@@ -238,9 +270,9 @@
238270 find_target:
239271 target.addr = map__objdump_2mem(map, ops->target.addr);
240272
241
- if (map_groups__find_ams(&target) == 0 &&
242
- map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
243
- ops->target.sym = target.sym;
273
+ if (maps__find_ams(ms->maps, &target) == 0 &&
274
+ map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
275
+ ops->target.sym = target.ms.sym;
244276
245277 return 0;
246278
....@@ -258,18 +290,18 @@
258290 }
259291
260292 static int call__scnprintf(struct ins *ins, char *bf, size_t size,
261
- struct ins_operands *ops)
293
+ struct ins_operands *ops, int max_ins_name)
262294 {
263295 if (ops->target.sym)
264
- return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
296
+ return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
265297
266298 if (ops->target.addr == 0)
267
- return ins__raw_scnprintf(ins, bf, size, ops);
299
+ return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
268300
269301 if (ops->target.name)
270
- return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name);
302
+ return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.name);
271303
272
- return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr);
304
+ return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr);
273305 }
274306
275307 static struct ins_ops call_ops = {
....@@ -285,10 +317,16 @@
285317 /*
286318 * Prevents from matching commas in the comment section, e.g.:
287319 * ffff200008446e70: b.cs ffff2000084470f4 <generic_exec_single+0x314> // b.hs, b.nlast
320
+ *
321
+ * and skip comma as part of function arguments, e.g.:
322
+ * 1d8b4ac <linemap_lookup(line_maps const*, unsigned int)+0xcc>
288323 */
289324 static inline const char *validate_comma(const char *c, struct ins_operands *ops)
290325 {
291326 if (ops->raw_comment && c > ops->raw_comment)
327
+ return NULL;
328
+
329
+ if (ops->raw_func_start && c > ops->raw_func_start)
292330 return NULL;
293331
294332 return c;
....@@ -299,12 +337,14 @@
299337 struct map *map = ms->map;
300338 struct symbol *sym = ms->sym;
301339 struct addr_map_symbol target = {
302
- .map = map,
340
+ .ms = { .map = map, },
303341 };
304342 const char *c = strchr(ops->raw, ',');
305343 u64 start, end;
306344
307345 ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char);
346
+ ops->raw_func_start = strchr(ops->raw, '<');
347
+
308348 c = validate_comma(c, ops);
309349
310350 /*
....@@ -358,9 +398,9 @@
358398 * Actual navigation will come next, with further understanding of how
359399 * the symbol searching and disassembly should be done.
360400 */
361
- if (map_groups__find_ams(&target) == 0 &&
362
- map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
363
- ops->target.sym = target.sym;
401
+ if (maps__find_ams(ms->maps, &target) == 0 &&
402
+ map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
403
+ ops->target.sym = target.ms.sym;
364404
365405 if (!ops->target.outside) {
366406 ops->target.offset = target.addr - start;
....@@ -373,15 +413,15 @@
373413 }
374414
375415 static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
376
- struct ins_operands *ops)
416
+ struct ins_operands *ops, int max_ins_name)
377417 {
378418 const char *c;
379419
380420 if (!ops->target.addr || ops->target.offset < 0)
381
- return ins__raw_scnprintf(ins, bf, size, ops);
421
+ return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
382422
383423 if (ops->target.outside && ops->target.sym != NULL)
384
- return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
424
+ return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
385425
386426 c = strchr(ops->raw, ',');
387427 c = validate_comma(c, ops);
....@@ -400,7 +440,7 @@
400440 c++;
401441 }
402442
403
- return scnprintf(bf, size, "%-6s %.*s%" PRIx64,
443
+ return scnprintf(bf, size, "%-*s %.*s%" PRIx64, max_ins_name,
404444 ins->name, c ? c - ops->raw : 0, ops->raw,
405445 ops->target.offset);
406446 }
....@@ -468,16 +508,16 @@
468508 }
469509
470510 static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
471
- struct ins_operands *ops)
511
+ struct ins_operands *ops, int max_ins_name)
472512 {
473513 int printed;
474514
475515 if (ops->locked.ins.ops == NULL)
476
- return ins__raw_scnprintf(ins, bf, size, ops);
516
+ return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
477517
478
- printed = scnprintf(bf, size, "%-6s ", ins->name);
518
+ printed = scnprintf(bf, size, "%-*s ", max_ins_name, ins->name);
479519 return printed + ins__scnprintf(&ops->locked.ins, bf + printed,
480
- size - printed, ops->locked.ops);
520
+ size - printed, ops->locked.ops, max_ins_name);
481521 }
482522
483523 static void lock__delete(struct ins_operands *ops)
....@@ -537,7 +577,7 @@
537577 if (comment == NULL)
538578 return 0;
539579
540
- comment = ltrim(comment);
580
+ comment = skip_spaces(comment);
541581 comment__symbol(ops->source.raw, comment + 1, &ops->source.addr, &ops->source.name);
542582 comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
543583
....@@ -549,9 +589,9 @@
549589 }
550590
551591 static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
552
- struct ins_operands *ops)
592
+ struct ins_operands *ops, int max_ins_name)
553593 {
554
- return scnprintf(bf, size, "%-6s %s,%s", ins->name,
594
+ return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
555595 ops->source.name ?: ops->source.raw,
556596 ops->target.name ?: ops->target.raw);
557597 }
....@@ -582,16 +622,16 @@
582622 if (comment == NULL)
583623 return 0;
584624
585
- comment = ltrim(comment);
625
+ comment = skip_spaces(comment);
586626 comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
587627
588628 return 0;
589629 }
590630
591631 static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
592
- struct ins_operands *ops)
632
+ struct ins_operands *ops, int max_ins_name)
593633 {
594
- return scnprintf(bf, size, "%-6s %s", ins->name,
634
+ return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
595635 ops->target.name ?: ops->target.raw);
596636 }
597637
....@@ -601,9 +641,9 @@
601641 };
602642
603643 static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
604
- struct ins_operands *ops __maybe_unused)
644
+ struct ins_operands *ops __maybe_unused, int max_ins_name)
605645 {
606
- return scnprintf(bf, size, "%-6s", "nop");
646
+ return scnprintf(bf, size, "%-*s", max_ins_name, "nop");
607647 }
608648
609649 static struct ins_ops nop_ops = {
....@@ -821,6 +861,10 @@
821861 ch[offset].start < start)
822862 return 0;
823863 }
864
+
865
+ if (ch[offset].num < NUM_SPARKS)
866
+ ch[offset].cycles_spark[ch[offset].num] = cycles;
867
+
824868 ch[offset].have_start = have_start;
825869 ch[offset].start = start;
826870 ch[offset].cycles += cycles;
....@@ -828,14 +872,15 @@
828872 return 0;
829873 }
830874
831
-static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
875
+static int __symbol__inc_addr_samples(struct map_symbol *ms,
832876 struct annotated_source *src, int evidx, u64 addr,
833877 struct perf_sample *sample)
834878 {
879
+ struct symbol *sym = ms->sym;
835880 unsigned offset;
836881 struct sym_hist *h;
837882
838
- pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
883
+ pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, ms->map->unmap_ip(ms->map, addr));
839884
840885 if ((addr < sym->start || addr >= sym->end) &&
841886 (addr != sym->end || sym->start != sym->end)) {
....@@ -902,17 +947,17 @@
902947 return notes->src;
903948 }
904949
905
-static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
906
- struct perf_evsel *evsel, u64 addr,
950
+static int symbol__inc_addr_samples(struct map_symbol *ms,
951
+ struct evsel *evsel, u64 addr,
907952 struct perf_sample *sample)
908953 {
954
+ struct symbol *sym = ms->sym;
909955 struct annotated_source *src;
910956
911957 if (sym == NULL)
912958 return 0;
913
- src = symbol__hists(sym, evsel->evlist->nr_entries);
914
- return (src) ? __symbol__inc_addr_samples(sym, map, src, evsel->idx,
915
- addr, sample) : 0;
959
+ src = symbol__hists(sym, evsel->evlist->core.nr_entries);
960
+ return src ? __symbol__inc_addr_samples(ms, src, evsel->idx, addr, sample) : 0;
916961 }
917962
918963 static int symbol__account_cycles(u64 addr, u64 start,
....@@ -960,17 +1005,17 @@
9601005 * it starts on the function start.
9611006 */
9621007 if (start &&
963
- (start->sym == ams->sym ||
964
- (ams->sym &&
965
- start->addr == ams->sym->start + ams->map->start)))
1008
+ (start->ms.sym == ams->ms.sym ||
1009
+ (ams->ms.sym &&
1010
+ start->addr == ams->ms.sym->start + ams->ms.map->start)))
9661011 saddr = start->al_addr;
9671012 if (saddr == 0)
9681013 pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
9691014 ams->addr,
9701015 start ? start->addr : 0,
971
- ams->sym ? ams->sym->start + ams->map->start : 0,
1016
+ ams->ms.sym ? ams->ms.sym->start + ams->ms.map->start : 0,
9721017 saddr);
973
- err = symbol__account_cycles(ams->al_addr, saddr, ams->sym, cycles);
1018
+ err = symbol__account_cycles(ams->al_addr, saddr, ams->ms.sym, cycles);
9741019 if (err)
9751020 pr_debug2("account_cycles failed %d\n", err);
9761021 return err;
....@@ -991,6 +1036,7 @@
9911036 static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch)
9921037 {
9931038 unsigned n_insn;
1039
+ unsigned int cover_insn = 0;
9941040 u64 offset;
9951041
9961042 n_insn = annotation__count_insn(notes, start, end);
....@@ -998,27 +1044,40 @@
9981044 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
9991045
10001046 /* Hide data when there are too many overlaps. */
1001
- if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
1047
+ if (ch->reset >= 0x7fff)
10021048 return;
10031049
10041050 for (offset = start; offset <= end; offset++) {
10051051 struct annotation_line *al = notes->offsets[offset];
10061052
1007
- if (al)
1053
+ if (al && al->ipc == 0.0) {
10081054 al->ipc = ipc;
1055
+ cover_insn++;
1056
+ }
1057
+ }
1058
+
1059
+ if (cover_insn) {
1060
+ notes->hit_cycles += ch->cycles;
1061
+ notes->hit_insn += n_insn * ch->num;
1062
+ notes->cover_insn += cover_insn;
10091063 }
10101064 }
10111065 }
10121066
10131067 void annotation__compute_ipc(struct annotation *notes, size_t size)
10141068 {
1015
- u64 offset;
1069
+ s64 offset;
10161070
10171071 if (!notes->src || !notes->src->cycles_hist)
10181072 return;
10191073
1074
+ notes->total_insn = annotation__count_insn(notes, 0, size - 1);
1075
+ notes->hit_cycles = 0;
1076
+ notes->hit_insn = 0;
1077
+ notes->cover_insn = 0;
1078
+
10201079 pthread_mutex_lock(&notes->lock);
1021
- for (offset = 0; offset < size; ++offset) {
1080
+ for (offset = size - 1; offset >= 0; --offset) {
10221081 struct cyc_hist *ch;
10231082
10241083 ch = &notes->src->cycles_hist[offset];
....@@ -1040,15 +1099,15 @@
10401099 }
10411100
10421101 int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
1043
- struct perf_evsel *evsel)
1102
+ struct evsel *evsel)
10441103 {
1045
- return symbol__inc_addr_samples(ams->sym, ams->map, evsel, ams->al_addr, sample);
1104
+ return symbol__inc_addr_samples(&ams->ms, evsel, ams->al_addr, sample);
10461105 }
10471106
10481107 int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
1049
- struct perf_evsel *evsel, u64 ip)
1108
+ struct evsel *evsel, u64 ip)
10501109 {
1051
- return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evsel, ip, sample);
1110
+ return symbol__inc_addr_samples(&he->ms, evsel, ip, sample);
10521111 }
10531112
10541113 static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
....@@ -1064,7 +1123,7 @@
10641123
10651124 static int disasm_line__parse(char *line, const char **namep, char **rawp)
10661125 {
1067
- char tmp, *name = ltrim(line);
1126
+ char tmp, *name = skip_spaces(line);
10681127
10691128 if (name[0] == '\0')
10701129 return -1;
....@@ -1082,7 +1141,7 @@
10821141 goto out;
10831142
10841143 (*rawp)[0] = tmp;
1085
- *rawp = ltrim(*rawp);
1144
+ *rawp = strim(*rawp);
10861145
10871146 return 0;
10881147
....@@ -1091,93 +1150,70 @@
10911150 }
10921151
10931152 struct annotate_args {
1094
- size_t privsize;
1095
- struct arch *arch;
1096
- struct map_symbol ms;
1097
- struct perf_evsel *evsel;
1153
+ struct arch *arch;
1154
+ struct map_symbol ms;
1155
+ struct evsel *evsel;
10981156 struct annotation_options *options;
1099
- s64 offset;
1100
- char *line;
1101
- int line_nr;
1157
+ s64 offset;
1158
+ char *line;
1159
+ int line_nr;
11021160 };
11031161
1104
-static void annotation_line__delete(struct annotation_line *al)
1162
+static void annotation_line__init(struct annotation_line *al,
1163
+ struct annotate_args *args,
1164
+ int nr)
11051165 {
1106
- void *ptr = (void *) al - al->privsize;
1107
-
1108
- free_srcline(al->path);
1109
- zfree(&al->line);
1110
- free(ptr);
1166
+ al->offset = args->offset;
1167
+ al->line = strdup(args->line);
1168
+ al->line_nr = args->line_nr;
1169
+ al->data_nr = nr;
11111170 }
11121171
1113
-/*
1114
- * Allocating the annotation line data with following
1115
- * structure:
1116
- *
1117
- * --------------------------------------
1118
- * private space | struct annotation_line
1119
- * --------------------------------------
1120
- *
1121
- * Size of the private space is stored in 'struct annotation_line'.
1122
- *
1123
- */
1124
-static struct annotation_line *
1125
-annotation_line__new(struct annotate_args *args, size_t privsize)
1172
+static void annotation_line__exit(struct annotation_line *al)
1173
+{
1174
+ free_srcline(al->path);
1175
+ zfree(&al->line);
1176
+}
1177
+
1178
+static size_t disasm_line_size(int nr)
11261179 {
11271180 struct annotation_line *al;
1128
- struct perf_evsel *evsel = args->evsel;
1129
- size_t size = privsize + sizeof(*al);
1130
- int nr = 1;
11311181
1132
- if (perf_evsel__is_group_event(evsel))
1133
- nr = evsel->nr_members;
1134
-
1135
- size += sizeof(al->data[0]) * nr;
1136
-
1137
- al = zalloc(size);
1138
- if (al) {
1139
- al = (void *) al + privsize;
1140
- al->privsize = privsize;
1141
- al->offset = args->offset;
1142
- al->line = strdup(args->line);
1143
- al->line_nr = args->line_nr;
1144
- al->data_nr = nr;
1145
- }
1146
-
1147
- return al;
1182
+ return (sizeof(struct disasm_line) + (sizeof(al->data[0]) * nr));
11481183 }
11491184
11501185 /*
11511186 * Allocating the disasm annotation line data with
11521187 * following structure:
11531188 *
1154
- * ------------------------------------------------------------
1155
- * privsize space | struct disasm_line | struct annotation_line
1156
- * ------------------------------------------------------------
1189
+ * -------------------------------------------
1190
+ * struct disasm_line | struct annotation_line
1191
+ * -------------------------------------------
11571192 *
11581193 * We have 'struct annotation_line' member as last member
11591194 * of 'struct disasm_line' to have an easy access.
1160
- *
11611195 */
11621196 static struct disasm_line *disasm_line__new(struct annotate_args *args)
11631197 {
11641198 struct disasm_line *dl = NULL;
1165
- struct annotation_line *al;
1166
- size_t privsize = args->privsize + offsetof(struct disasm_line, al);
1199
+ int nr = 1;
11671200
1168
- al = annotation_line__new(args, privsize);
1169
- if (al != NULL) {
1170
- dl = disasm_line(al);
1201
+ if (evsel__is_group_event(args->evsel))
1202
+ nr = args->evsel->core.nr_members;
11711203
1172
- if (dl->al.line == NULL)
1173
- goto out_delete;
1204
+ dl = zalloc(disasm_line_size(nr));
1205
+ if (!dl)
1206
+ return NULL;
11741207
1175
- if (args->offset != -1) {
1176
- if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
1177
- goto out_free_line;
1208
+ annotation_line__init(&dl->al, args, nr);
1209
+ if (dl->al.line == NULL)
1210
+ goto out_delete;
11781211
1179
- disasm_line__init_ins(dl, args->arch, &args->ms);
1180
- }
1212
+ if (args->offset != -1) {
1213
+ if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
1214
+ goto out_free_line;
1215
+
1216
+ disasm_line__init_ins(dl, args->arch, &args->ms);
11811217 }
11821218
11831219 return dl;
....@@ -1195,17 +1231,17 @@
11951231 dl->ins.ops->free(&dl->ops);
11961232 else
11971233 ins__delete(&dl->ops);
1198
- free((void *)dl->ins.name);
1199
- dl->ins.name = NULL;
1200
- annotation_line__delete(&dl->al);
1234
+ zfree(&dl->ins.name);
1235
+ annotation_line__exit(&dl->al);
1236
+ free(dl);
12011237 }
12021238
1203
-int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
1239
+int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name)
12041240 {
12051241 if (raw || !dl->ins.ops)
1206
- return scnprintf(bf, size, "%-6s %s", dl->ins.name, dl->ops.raw);
1242
+ return scnprintf(bf, size, "%-*s %s", max_ins_name, dl->ins.name, dl->ops.raw);
12071243
1208
- return ins__scnprintf(&dl->ins, bf, size, &dl->ops);
1244
+ return ins__scnprintf(&dl->ins, bf, size, &dl->ops, max_ins_name);
12091245 }
12101246
12111247 static void annotation_line__add(struct annotation_line *al, struct list_head *head)
....@@ -1320,7 +1356,7 @@
13201356
13211357 static int
13221358 annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
1323
- struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
1359
+ struct evsel *evsel, u64 len, int min_pcnt, int printed,
13241360 int max_lines, struct annotation_line *queue, int addr_fmt_width,
13251361 int percent_type)
13261362 {
....@@ -1408,8 +1444,8 @@
14081444 if (queue)
14091445 return -1;
14101446
1411
- if (perf_evsel__is_group_event(evsel))
1412
- width *= evsel->nr_members;
1447
+ if (evsel__is_group_event(evsel))
1448
+ width *= evsel->core.nr_members;
14131449
14141450 if (!*al->line)
14151451 printf(" %*s:\n", width, " ");
....@@ -1440,26 +1476,16 @@
14401476 * means that it's not a disassembly line so should be treated differently.
14411477 * The ops.raw part will be parsed further according to type of the instruction.
14421478 */
1443
-static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1479
+static int symbol__parse_objdump_line(struct symbol *sym,
14441480 struct annotate_args *args,
1445
- int *line_nr)
1481
+ char *parsed_line, int *line_nr)
14461482 {
14471483 struct map *map = args->ms.map;
14481484 struct annotation *notes = symbol__annotation(sym);
14491485 struct disasm_line *dl;
1450
- char *line = NULL, *parsed_line, *tmp, *tmp2;
1451
- size_t line_len;
1486
+ char *tmp;
14521487 s64 line_ip, offset = -1;
14531488 regmatch_t match[2];
1454
-
1455
- if (getline(&line, &line_len, file) < 0)
1456
- return -1;
1457
-
1458
- if (!line)
1459
- return -1;
1460
-
1461
- line_ip = -1;
1462
- parsed_line = rtrim(line);
14631489
14641490 /* /filename:linenr ? Save line number and ignore. */
14651491 if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) {
....@@ -1467,17 +1493,9 @@
14671493 return 0;
14681494 }
14691495
1470
- tmp = ltrim(parsed_line);
1471
- if (*tmp) {
1472
- /*
1473
- * Parse hexa addresses followed by ':'
1474
- */
1475
- line_ip = strtoull(tmp, &tmp2, 16);
1476
- if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
1477
- line_ip = -1;
1478
- }
1479
-
1480
- if (line_ip != -1) {
1496
+ /* Process hex address followed by ':'. */
1497
+ line_ip = strtoull(parsed_line, &tmp, 16);
1498
+ if (parsed_line != tmp && tmp[0] == ':' && tmp[1] != '\0') {
14811499 u64 start = map__rip_2objdump(map, sym->start),
14821500 end = map__rip_2objdump(map, sym->end);
14831501
....@@ -1485,7 +1503,7 @@
14851503 if ((u64)line_ip < start || (u64)line_ip >= end)
14861504 offset = -1;
14871505 else
1488
- parsed_line = tmp2 + 1;
1506
+ parsed_line = tmp + 1;
14891507 }
14901508
14911509 args->offset = offset;
....@@ -1494,7 +1512,6 @@
14941512 args->ms.sym = sym;
14951513
14961514 dl = disasm_line__new(args);
1497
- free(line);
14981515 (*line_nr)++;
14991516
15001517 if (dl == NULL)
....@@ -1509,13 +1526,13 @@
15091526 /* kcore has no symbols, so add the call target symbol */
15101527 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
15111528 struct addr_map_symbol target = {
1512
- .map = map,
15131529 .addr = dl->ops.target.addr,
1530
+ .ms = { .map = map, },
15141531 };
15151532
1516
- if (!map_groups__find_ams(&target) &&
1517
- target.sym->start == target.al_addr)
1518
- dl->ops.target.sym = target.sym;
1533
+ if (!maps__find_ams(args->ms.maps, &target) &&
1534
+ target.ms.sym->start == target.al_addr)
1535
+ dl->ops.target.sym = target.ms.sym;
15191536 }
15201537
15211538 annotation_line__add(&dl->al, &notes->src->source);
....@@ -1547,15 +1564,14 @@
15471564 return;
15481565 }
15491566
1550
- list_del(&dl->al.node);
1567
+ list_del_init(&dl->al.node);
15511568 disasm_line__free(dl);
15521569 }
15531570 }
15541571
1555
-int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
1556
- int errnum, char *buf, size_t buflen)
1572
+int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen)
15571573 {
1558
- struct dso *dso = map->dso;
1574
+ struct dso *dso = ms->map->dso;
15591575
15601576 BUG_ON(buflen == 0);
15611577
....@@ -1570,8 +1586,7 @@
15701586 char *build_id_msg = NULL;
15711587
15721588 if (dso->has_build_id) {
1573
- build_id__sprintf(dso->build_id,
1574
- sizeof(dso->build_id), bf + 15);
1589
+ build_id__sprintf(&dso->bid, bf + 15);
15751590 build_id_msg = bf;
15761591 }
15771592 scnprintf(buf, buflen,
....@@ -1582,6 +1597,22 @@
15821597 "or:\n\n"
15831598 " --vmlinux vmlinux\n", build_id_msg ?: "");
15841599 }
1600
+ break;
1601
+ case SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF:
1602
+ scnprintf(buf, buflen, "Please link with binutils's libopcode to enable BPF annotation");
1603
+ break;
1604
+ case SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP:
1605
+ scnprintf(buf, buflen, "Problems with arch specific instruction name regular expressions.");
1606
+ break;
1607
+ case SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING:
1608
+ scnprintf(buf, buflen, "Problems while parsing the CPUID in the arch specific initialization.");
1609
+ break;
1610
+ case SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE:
1611
+ scnprintf(buf, buflen, "Invalid BPF file: %s.", dso->long_name);
1612
+ break;
1613
+ case SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF:
1614
+ scnprintf(buf, buflen, "The %s BPF file has no BTF section, compile with -g or use pahole -J.",
1615
+ dso->long_name);
15851616 break;
15861617 default:
15871618 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
....@@ -1597,6 +1628,7 @@
15971628 char *build_id_filename;
15981629 char *build_id_path = NULL;
15991630 char *pos;
1631
+ int len;
16001632
16011633 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
16021634 !dso__is_kcore(dso))
....@@ -1625,10 +1657,16 @@
16251657 if (pos && strlen(pos) < SBUILD_ID_SIZE - 2)
16261658 dirname(build_id_path);
16271659
1628
- if (dso__is_kcore(dso) ||
1629
- readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
1630
- strstr(linkname, DSO__NAME_KALLSYMS) ||
1631
- access(filename, R_OK)) {
1660
+ if (dso__is_kcore(dso))
1661
+ goto fallback;
1662
+
1663
+ len = readlink(build_id_path, linkname, sizeof(linkname) - 1);
1664
+ if (len < 0)
1665
+ goto fallback;
1666
+
1667
+ linkname[len] = '\0';
1668
+ if (strstr(linkname, DSO__NAME_KALLSYMS) ||
1669
+ access(filename, R_OK)) {
16321670 fallback:
16331671 /*
16341672 * If we don't have build-ids or the build-id file isn't in the
....@@ -1642,6 +1680,243 @@
16421680 return 0;
16431681 }
16441682
1683
+#if defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1684
+#define PACKAGE "perf"
1685
+#include <bfd.h>
1686
+#include <dis-asm.h>
1687
+
1688
+static int symbol__disassemble_bpf(struct symbol *sym,
1689
+ struct annotate_args *args)
1690
+{
1691
+ struct annotation *notes = symbol__annotation(sym);
1692
+ struct annotation_options *opts = args->options;
1693
+ struct bpf_prog_info_linear *info_linear;
1694
+ struct bpf_prog_linfo *prog_linfo = NULL;
1695
+ struct bpf_prog_info_node *info_node;
1696
+ int len = sym->end - sym->start;
1697
+ disassembler_ftype disassemble;
1698
+ struct map *map = args->ms.map;
1699
+ struct disassemble_info info;
1700
+ struct dso *dso = map->dso;
1701
+ int pc = 0, count, sub_id;
1702
+ struct btf *btf = NULL;
1703
+ char tpath[PATH_MAX];
1704
+ size_t buf_size;
1705
+ int nr_skip = 0;
1706
+ char *buf;
1707
+ bfd *bfdf;
1708
+ int ret;
1709
+ FILE *s;
1710
+
1711
+ if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
1712
+ return SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE;
1713
+
1714
+ pr_debug("%s: handling sym %s addr %" PRIx64 " len %" PRIx64 "\n", __func__,
1715
+ sym->name, sym->start, sym->end - sym->start);
1716
+
1717
+ memset(tpath, 0, sizeof(tpath));
1718
+ perf_exe(tpath, sizeof(tpath));
1719
+
1720
+ bfdf = bfd_openr(tpath, NULL);
1721
+ if (bfdf == NULL)
1722
+ abort();
1723
+
1724
+ if (!bfd_check_format(bfdf, bfd_object))
1725
+ abort();
1726
+
1727
+ s = open_memstream(&buf, &buf_size);
1728
+ if (!s) {
1729
+ ret = errno;
1730
+ goto out;
1731
+ }
1732
+ init_disassemble_info(&info, s,
1733
+ (fprintf_ftype) fprintf);
1734
+
1735
+ info.arch = bfd_get_arch(bfdf);
1736
+ info.mach = bfd_get_mach(bfdf);
1737
+
1738
+ info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
1739
+ dso->bpf_prog.id);
1740
+ if (!info_node) {
1741
+ ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
1742
+ goto out;
1743
+ }
1744
+ info_linear = info_node->info_linear;
1745
+ sub_id = dso->bpf_prog.sub_id;
1746
+
1747
+ info.buffer = (void *)(uintptr_t)(info_linear->info.jited_prog_insns);
1748
+ info.buffer_length = info_linear->info.jited_prog_len;
1749
+
1750
+ if (info_linear->info.nr_line_info)
1751
+ prog_linfo = bpf_prog_linfo__new(&info_linear->info);
1752
+
1753
+ if (info_linear->info.btf_id) {
1754
+ struct btf_node *node;
1755
+
1756
+ node = perf_env__find_btf(dso->bpf_prog.env,
1757
+ info_linear->info.btf_id);
1758
+ if (node)
1759
+ btf = btf__new((__u8 *)(node->data),
1760
+ node->data_size);
1761
+ }
1762
+
1763
+ disassemble_init_for_target(&info);
1764
+
1765
+#ifdef DISASM_FOUR_ARGS_SIGNATURE
1766
+ disassemble = disassembler(info.arch,
1767
+ bfd_big_endian(bfdf),
1768
+ info.mach,
1769
+ bfdf);
1770
+#else
1771
+ disassemble = disassembler(bfdf);
1772
+#endif
1773
+ if (disassemble == NULL)
1774
+ abort();
1775
+
1776
+ fflush(s);
1777
+ do {
1778
+ const struct bpf_line_info *linfo = NULL;
1779
+ struct disasm_line *dl;
1780
+ size_t prev_buf_size;
1781
+ const char *srcline;
1782
+ u64 addr;
1783
+
1784
+ addr = pc + ((u64 *)(uintptr_t)(info_linear->info.jited_ksyms))[sub_id];
1785
+ count = disassemble(pc, &info);
1786
+
1787
+ if (prog_linfo)
1788
+ linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
1789
+ addr, sub_id,
1790
+ nr_skip);
1791
+
1792
+ if (linfo && btf) {
1793
+ srcline = btf__name_by_offset(btf, linfo->line_off);
1794
+ nr_skip++;
1795
+ } else
1796
+ srcline = NULL;
1797
+
1798
+ fprintf(s, "\n");
1799
+ prev_buf_size = buf_size;
1800
+ fflush(s);
1801
+
1802
+ if (!opts->hide_src_code && srcline) {
1803
+ args->offset = -1;
1804
+ args->line = strdup(srcline);
1805
+ args->line_nr = 0;
1806
+ args->ms.sym = sym;
1807
+ dl = disasm_line__new(args);
1808
+ if (dl) {
1809
+ annotation_line__add(&dl->al,
1810
+ &notes->src->source);
1811
+ }
1812
+ }
1813
+
1814
+ args->offset = pc;
1815
+ args->line = buf + prev_buf_size;
1816
+ args->line_nr = 0;
1817
+ args->ms.sym = sym;
1818
+ dl = disasm_line__new(args);
1819
+ if (dl)
1820
+ annotation_line__add(&dl->al, &notes->src->source);
1821
+
1822
+ pc += count;
1823
+ } while (count > 0 && pc < len);
1824
+
1825
+ ret = 0;
1826
+out:
1827
+ free(prog_linfo);
1828
+ free(btf);
1829
+ fclose(s);
1830
+ bfd_close(bfdf);
1831
+ return ret;
1832
+}
1833
+#else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1834
+static int symbol__disassemble_bpf(struct symbol *sym __maybe_unused,
1835
+ struct annotate_args *args __maybe_unused)
1836
+{
1837
+ return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
1838
+}
1839
+#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1840
+
1841
+static int
1842
+symbol__disassemble_bpf_image(struct symbol *sym,
1843
+ struct annotate_args *args)
1844
+{
1845
+ struct annotation *notes = symbol__annotation(sym);
1846
+ struct disasm_line *dl;
1847
+
1848
+ args->offset = -1;
1849
+ args->line = strdup("to be implemented");
1850
+ args->line_nr = 0;
1851
+ dl = disasm_line__new(args);
1852
+ if (dl)
1853
+ annotation_line__add(&dl->al, &notes->src->source);
1854
+
1855
+ free(args->line);
1856
+ return 0;
1857
+}
1858
+
1859
+/*
1860
+ * Possibly create a new version of line with tabs expanded. Returns the
1861
+ * existing or new line, storage is updated if a new line is allocated. If
1862
+ * allocation fails then NULL is returned.
1863
+ */
1864
+static char *expand_tabs(char *line, char **storage, size_t *storage_len)
1865
+{
1866
+ size_t i, src, dst, len, new_storage_len, num_tabs;
1867
+ char *new_line;
1868
+ size_t line_len = strlen(line);
1869
+
1870
+ for (num_tabs = 0, i = 0; i < line_len; i++)
1871
+ if (line[i] == '\t')
1872
+ num_tabs++;
1873
+
1874
+ if (num_tabs == 0)
1875
+ return line;
1876
+
1877
+ /*
1878
+ * Space for the line and '\0', less the leading and trailing
1879
+ * spaces. Each tab may introduce 7 additional spaces.
1880
+ */
1881
+ new_storage_len = line_len + 1 + (num_tabs * 7);
1882
+
1883
+ new_line = malloc(new_storage_len);
1884
+ if (new_line == NULL) {
1885
+ pr_err("Failure allocating memory for tab expansion\n");
1886
+ return NULL;
1887
+ }
1888
+
1889
+ /*
1890
+ * Copy regions starting at src and expand tabs. If there are two
1891
+ * adjacent tabs then 'src == i', the memcpy is of size 0 and the spaces
1892
+ * are inserted.
1893
+ */
1894
+ for (i = 0, src = 0, dst = 0; i < line_len && num_tabs; i++) {
1895
+ if (line[i] == '\t') {
1896
+ len = i - src;
1897
+ memcpy(&new_line[dst], &line[src], len);
1898
+ dst += len;
1899
+ new_line[dst++] = ' ';
1900
+ while (dst % 8 != 0)
1901
+ new_line[dst++] = ' ';
1902
+ src = i + 1;
1903
+ num_tabs--;
1904
+ }
1905
+ }
1906
+
1907
+ /* Expand the last region. */
1908
+ len = line_len - src;
1909
+ memcpy(&new_line[dst], &line[src], len);
1910
+ dst += len;
1911
+ new_line[dst] = '\0';
1912
+
1913
+ free(*storage);
1914
+ *storage = new_line;
1915
+ *storage_len = new_storage_len;
1916
+ return new_line;
1917
+
1918
+}
1919
+
16451920 static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
16461921 {
16471922 struct annotation_options *opts = args->options;
....@@ -1653,10 +1928,19 @@
16531928 struct kcore_extract kce;
16541929 bool delete_extract = false;
16551930 bool decomp = false;
1656
- int stdout_fd[2];
16571931 int lineno = 0;
16581932 int nline;
1659
- pid_t pid;
1933
+ char *line;
1934
+ size_t line_len;
1935
+ const char *objdump_argv[] = {
1936
+ "/bin/sh",
1937
+ "-c",
1938
+ NULL, /* Will be the objdump command to run. */
1939
+ "--",
1940
+ NULL, /* Will be the symfs path. */
1941
+ NULL,
1942
+ };
1943
+ struct child_process objdump_process;
16601944 int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
16611945
16621946 if (err)
....@@ -1669,7 +1953,11 @@
16691953 pr_debug("annotating [%p] %30s : [%p] %30s\n",
16701954 dso, dso->long_name, sym, sym->name);
16711955
1672
- if (dso__is_kcore(dso)) {
1956
+ if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
1957
+ return symbol__disassemble_bpf(sym, args);
1958
+ } else if (dso->binary_type == DSO_BINARY_TYPE__BPF_IMAGE) {
1959
+ return symbol__disassemble_bpf_image(sym, args);
1960
+ } else if (dso__is_kcore(dso)) {
16731961 kce.kcore_filename = symfs_filename;
16741962 kce.addr = map__rip_2objdump(map, sym->start);
16751963 kce.offs = sym->start;
....@@ -1684,7 +1972,7 @@
16841972
16851973 if (dso__decompress_kmodule_path(dso, symfs_filename,
16861974 tmp, sizeof(tmp)) < 0)
1687
- goto out;
1975
+ return -1;
16881976
16891977 decomp = true;
16901978 strcpy(symfs_filename, tmp);
....@@ -1693,15 +1981,20 @@
16931981 err = asprintf(&command,
16941982 "%s %s%s --start-address=0x%016" PRIx64
16951983 " --stop-address=0x%016" PRIx64
1696
- " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
1984
+ " -l -d %s %s %s %c%s%c %s%s -C \"$1\"",
16971985 opts->objdump_path ?: "objdump",
16981986 opts->disassembler_style ? "-M " : "",
16991987 opts->disassembler_style ?: "",
17001988 map__rip_2objdump(map, sym->start),
17011989 map__rip_2objdump(map, sym->end),
1702
- opts->show_asm_raw ? "" : "--no-show-raw",
1990
+ opts->show_asm_raw ? "" : "--no-show-raw-insn",
17031991 opts->annotate_src ? "-S" : "",
1704
- symfs_filename, symfs_filename);
1992
+ opts->prefix ? "--prefix " : "",
1993
+ opts->prefix ? '"' : ' ',
1994
+ opts->prefix ?: "",
1995
+ opts->prefix ? '"' : ' ',
1996
+ opts->prefix_strip ? "--prefix-strip=" : "",
1997
+ opts->prefix_strip ?: "");
17051998
17061999 if (err < 0) {
17072000 pr_err("Failure allocating memory for the command to run\n");
....@@ -1710,54 +2003,73 @@
17102003
17112004 pr_debug("Executing: %s\n", command);
17122005
1713
- err = -1;
1714
- if (pipe(stdout_fd) < 0) {
1715
- pr_err("Failure creating the pipe to run %s\n", command);
2006
+ objdump_argv[2] = command;
2007
+ objdump_argv[4] = symfs_filename;
2008
+
2009
+ /* Create a pipe to read from for stdout */
2010
+ memset(&objdump_process, 0, sizeof(objdump_process));
2011
+ objdump_process.argv = objdump_argv;
2012
+ objdump_process.out = -1;
2013
+ if (start_command(&objdump_process)) {
2014
+ pr_err("Failure starting to run %s\n", command);
2015
+ err = -1;
17162016 goto out_free_command;
17172017 }
17182018
1719
- pid = fork();
1720
- if (pid < 0) {
1721
- pr_err("Failure forking to run %s\n", command);
1722
- goto out_close_stdout;
1723
- }
1724
-
1725
- if (pid == 0) {
1726
- close(stdout_fd[0]);
1727
- dup2(stdout_fd[1], 1);
1728
- close(stdout_fd[1]);
1729
- execl("/bin/sh", "sh", "-c", command, NULL);
1730
- perror(command);
1731
- exit(-1);
1732
- }
1733
-
1734
- close(stdout_fd[1]);
1735
-
1736
- file = fdopen(stdout_fd[0], "r");
2019
+ file = fdopen(objdump_process.out, "r");
17372020 if (!file) {
17382021 pr_err("Failure creating FILE stream for %s\n", command);
17392022 /*
17402023 * If we were using debug info should retry with
17412024 * original binary.
17422025 */
1743
- goto out_free_command;
2026
+ err = -1;
2027
+ goto out_close_stdout;
17442028 }
2029
+
2030
+ /* Storage for getline. */
2031
+ line = NULL;
2032
+ line_len = 0;
17452033
17462034 nline = 0;
17472035 while (!feof(file)) {
2036
+ const char *match;
2037
+ char *expanded_line;
2038
+
2039
+ if (getline(&line, &line_len, file) < 0 || !line)
2040
+ break;
2041
+
2042
+ /* Skip lines containing "filename:" */
2043
+ match = strstr(line, symfs_filename);
2044
+ if (match && match[strlen(symfs_filename)] == ':')
2045
+ continue;
2046
+
2047
+ expanded_line = strim(line);
2048
+ expanded_line = expand_tabs(expanded_line, &line, &line_len);
2049
+ if (!expanded_line)
2050
+ break;
2051
+
17482052 /*
17492053 * The source code line number (lineno) needs to be kept in
1750
- * accross calls to symbol__parse_objdump_line(), so that it
2054
+ * across calls to symbol__parse_objdump_line(), so that it
17512055 * can associate it with the instructions till the next one.
17522056 * See disasm_line__new() and struct disasm_line::line_nr.
17532057 */
1754
- if (symbol__parse_objdump_line(sym, file, args, &lineno) < 0)
2058
+ if (symbol__parse_objdump_line(sym, args, expanded_line,
2059
+ &lineno) < 0)
17552060 break;
17562061 nline++;
17572062 }
2063
+ free(line);
17582064
1759
- if (nline == 0)
2065
+ err = finish_command(&objdump_process);
2066
+ if (err)
2067
+ pr_err("Error running %s\n", command);
2068
+
2069
+ if (nline == 0) {
2070
+ err = -1;
17602071 pr_err("No output from %s\n", command);
2072
+ }
17612073
17622074 /*
17632075 * kallsyms does not have symbol sizes so there may a nop at the end.
....@@ -1767,23 +2079,21 @@
17672079 delete_last_nop(sym);
17682080
17692081 fclose(file);
1770
- err = 0;
2082
+
2083
+out_close_stdout:
2084
+ close(objdump_process.out);
2085
+
17712086 out_free_command:
17722087 free(command);
1773
-out_remove_tmp:
1774
- close(stdout_fd[0]);
17752088
2089
+out_remove_tmp:
17762090 if (decomp)
17772091 unlink(symfs_filename);
17782092
17792093 if (delete_extract)
17802094 kcore_extract__delete(&kce);
1781
-out:
1782
- return err;
17832095
1784
-out_close_stdout:
1785
- close(stdout_fd[1]);
1786
- goto out_free_command;
2096
+ return err;
17872097 }
17882098
17892099 static void calc_percent(struct sym_hist *sym_hist,
....@@ -1817,10 +2127,10 @@
18172127 }
18182128
18192129 static void annotation__calc_percent(struct annotation *notes,
1820
- struct perf_evsel *leader, s64 len)
2130
+ struct evsel *leader, s64 len)
18212131 {
18222132 struct annotation_line *al, *next;
1823
- struct perf_evsel *evsel;
2133
+ struct evsel *evsel;
18242134
18252135 list_for_each_entry(al, &notes->src->source, node) {
18262136 s64 end;
....@@ -1847,25 +2157,23 @@
18472157 }
18482158 }
18492159
1850
-void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel)
2160
+void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
18512161 {
18522162 struct annotation *notes = symbol__annotation(sym);
18532163
18542164 annotation__calc_percent(notes, evsel, symbol__size(sym));
18552165 }
18562166
1857
-int symbol__annotate(struct symbol *sym, struct map *map,
1858
- struct perf_evsel *evsel, size_t privsize,
1859
- struct annotation_options *options,
1860
- struct arch **parch)
2167
+int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
2168
+ struct annotation_options *options, struct arch **parch)
18612169 {
2170
+ struct symbol *sym = ms->sym;
18622171 struct annotation *notes = symbol__annotation(sym);
18632172 struct annotate_args args = {
1864
- .privsize = privsize,
18652173 .evsel = evsel,
18662174 .options = options,
18672175 };
1868
- struct perf_env *env = perf_evsel__env(evsel);
2176
+ struct perf_env *env = evsel__env(evsel);
18692177 const char *arch_name = perf_env__arch(env);
18702178 struct arch *arch;
18712179 int err;
....@@ -1888,9 +2196,8 @@
18882196 }
18892197 }
18902198
1891
- args.ms.map = map;
1892
- args.ms.sym = sym;
1893
- notes->start = map__rip_2objdump(map, sym->start);
2199
+ args.ms = *ms;
2200
+ notes->start = map__rip_2objdump(ms->map, sym->start);
18942201
18952202 return symbol__disassemble(sym, &args);
18962203 }
....@@ -2020,7 +2327,7 @@
20202327 }
20212328 }
20222329
2023
-static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
2330
+static void symbol__annotate_hits(struct symbol *sym, struct evsel *evsel)
20242331 {
20252332 struct annotation *notes = symbol__annotation(sym);
20262333 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
....@@ -2046,14 +2353,15 @@
20462353 return 0;
20472354 }
20482355
2049
-int symbol__annotate_printf(struct symbol *sym, struct map *map,
2050
- struct perf_evsel *evsel,
2356
+int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
20512357 struct annotation_options *opts)
20522358 {
2359
+ struct map *map = ms->map;
2360
+ struct symbol *sym = ms->sym;
20532361 struct dso *dso = map->dso;
20542362 char *filename;
20552363 const char *d_filename;
2056
- const char *evsel_name = perf_evsel__name(evsel);
2364
+ const char *evsel_name = evsel__name(evsel);
20572365 struct annotation *notes = symbol__annotation(sym);
20582366 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
20592367 struct annotation_line *pos, *queue = NULL;
....@@ -2077,9 +2385,9 @@
20772385
20782386 len = symbol__size(sym);
20792387
2080
- if (perf_evsel__is_group_event(evsel)) {
2081
- width *= evsel->nr_members;
2082
- perf_evsel__group_desc(evsel, buf, sizeof(buf));
2388
+ if (evsel__is_group_event(evsel)) {
2389
+ width *= evsel->core.nr_members;
2390
+ evsel__group_desc(evsel, buf, sizeof(buf));
20832391 evsel_name = buf;
20842392 }
20852393
....@@ -2211,10 +2519,10 @@
22112519 return 0;
22122520 }
22132521
2214
-int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
2522
+int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
22152523 struct annotation_options *opts)
22162524 {
2217
- const char *ev_name = perf_evsel__name(evsel);
2525
+ const char *ev_name = evsel__name(evsel);
22182526 char buf[1024];
22192527 char *filename;
22202528 int err = -1;
....@@ -2227,8 +2535,8 @@
22272535 if (fp == NULL)
22282536 goto out_free_filename;
22292537
2230
- if (perf_evsel__is_group_event(evsel)) {
2231
- perf_evsel__group_desc(evsel, buf, sizeof(buf));
2538
+ if (evsel__is_group_event(evsel)) {
2539
+ evsel__group_desc(evsel, buf, sizeof(buf));
22322540 ev_name = buf;
22332541 }
22342542
....@@ -2269,7 +2577,7 @@
22692577 struct annotation_line *al, *n;
22702578
22712579 list_for_each_entry_safe(al, n, &as->source, node) {
2272
- list_del(&al->node);
2580
+ list_del_init(&al->node);
22732581 disasm_line__free(disasm_line(al));
22742582 }
22752583 }
....@@ -2340,8 +2648,6 @@
23402648
23412649 if (++al->jump_sources > notes->max_jump_sources)
23422650 notes->max_jump_sources = al->jump_sources;
2343
-
2344
- ++notes->nr_jumps;
23452651 }
23462652 }
23472653
....@@ -2350,6 +2656,8 @@
23502656 struct annotation_line *al;
23512657
23522658 notes->max_line_len = 0;
2659
+ notes->nr_entries = 0;
2660
+ notes->nr_asm_entries = 0;
23532661
23542662 list_for_each_entry(al, &notes->src->source, node) {
23552663 size_t line_len = strlen(al->line);
....@@ -2382,12 +2690,30 @@
23822690 return 1;
23832691 }
23842692
2693
+static int annotation__max_ins_name(struct annotation *notes)
2694
+{
2695
+ int max_name = 0, len;
2696
+ struct annotation_line *al;
2697
+
2698
+ list_for_each_entry(al, &notes->src->source, node) {
2699
+ if (al->offset == -1)
2700
+ continue;
2701
+
2702
+ len = strlen(disasm_line(al)->ins.name);
2703
+ if (max_name < len)
2704
+ max_name = len;
2705
+ }
2706
+
2707
+ return max_name;
2708
+}
2709
+
23852710 void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
23862711 {
23872712 notes->widths.addr = notes->widths.target =
23882713 notes->widths.min_addr = hex_width(symbol__size(sym));
23892714 notes->widths.max_addr = hex_width(sym->end);
23902715 notes->widths.jumps = width_jumps(notes->max_jump_sources);
2716
+ notes->widths.max_ins_name = annotation__max_ins_name(notes);
23912717 }
23922718
23932719 void annotation__update_column_widths(struct annotation *notes)
....@@ -2435,30 +2761,29 @@
24352761 resort_source_line(root, &tmp_root);
24362762 }
24372763
2438
-static void symbol__calc_lines(struct symbol *sym, struct map *map,
2439
- struct rb_root *root,
2764
+static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root,
24402765 struct annotation_options *opts)
24412766 {
2442
- struct annotation *notes = symbol__annotation(sym);
2767
+ struct annotation *notes = symbol__annotation(ms->sym);
24432768
2444
- annotation__calc_lines(notes, map, root, opts);
2769
+ annotation__calc_lines(notes, ms->map, root, opts);
24452770 }
24462771
2447
-int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2448
- struct perf_evsel *evsel,
2772
+int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel,
24492773 struct annotation_options *opts)
24502774 {
2451
- struct dso *dso = map->dso;
2775
+ struct dso *dso = ms->map->dso;
2776
+ struct symbol *sym = ms->sym;
24522777 struct rb_root source_line = RB_ROOT;
24532778 struct hists *hists = evsel__hists(evsel);
24542779 char buf[1024];
24552780
2456
- if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
2781
+ if (symbol__annotate2(ms, evsel, opts, NULL) < 0)
24572782 return -1;
24582783
24592784 if (opts->print_lines) {
24602785 srcline_full_filename = opts->full_path;
2461
- symbol__calc_lines(sym, map, &source_line, opts);
2786
+ symbol__calc_lines(ms, &source_line, opts);
24622787 print_summary(&source_line, dso->long_name);
24632788 }
24642789
....@@ -2472,25 +2797,25 @@
24722797 return 0;
24732798 }
24742799
2475
-int symbol__tty_annotate(struct symbol *sym, struct map *map,
2476
- struct perf_evsel *evsel,
2800
+int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
24772801 struct annotation_options *opts)
24782802 {
2479
- struct dso *dso = map->dso;
2803
+ struct dso *dso = ms->map->dso;
2804
+ struct symbol *sym = ms->sym;
24802805 struct rb_root source_line = RB_ROOT;
24812806
2482
- if (symbol__annotate(sym, map, evsel, 0, opts, NULL) < 0)
2807
+ if (symbol__annotate(ms, evsel, opts, NULL) < 0)
24832808 return -1;
24842809
24852810 symbol__calc_percent(sym, evsel);
24862811
24872812 if (opts->print_lines) {
24882813 srcline_full_filename = opts->full_path;
2489
- symbol__calc_lines(sym, map, &source_line, opts);
2814
+ symbol__calc_lines(ms, &source_line, opts);
24902815 print_summary(&source_line, dso->long_name);
24912816 }
24922817
2493
- symbol__annotate_printf(sym, map, evsel, opts);
2818
+ symbol__annotate_printf(ms, evsel, opts);
24942819
24952820 annotated_source__purge(symbol__annotation(sym)->src);
24962821
....@@ -2551,7 +2876,23 @@
25512876 obj__printf(obj, " ");
25522877 }
25532878
2554
- disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
2879
+ disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset, notes->widths.max_ins_name);
2880
+}
2881
+
2882
+static void ipc_coverage_string(char *bf, int size, struct annotation *notes)
2883
+{
2884
+ double ipc = 0.0, coverage = 0.0;
2885
+
2886
+ if (notes->hit_cycles)
2887
+ ipc = notes->hit_insn / ((double)notes->hit_cycles);
2888
+
2889
+ if (notes->total_insn) {
2890
+ coverage = notes->cover_insn * 100.0 /
2891
+ ((double)notes->total_insn);
2892
+ }
2893
+
2894
+ scnprintf(bf, size, "(Average IPC: %.2f, IPC Coverage: %.1f%%)",
2895
+ ipc, coverage);
25552896 }
25562897
25572898 static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
....@@ -2588,9 +2929,9 @@
25882929 percent = annotation_data__percent(&al->data[i], percent_type);
25892930
25902931 obj__set_percent_color(obj, percent, current_entry);
2591
- if (notes->options->show_total_period) {
2932
+ if (symbol_conf.show_total_period) {
25922933 obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
2593
- } else if (notes->options->show_nr_samples) {
2934
+ } else if (symbol_conf.show_nr_samples) {
25942935 obj__printf(obj, "%6" PRIu64 " ",
25952936 al->data[i].he.nr_samples);
25962937 } else {
....@@ -2604,8 +2945,8 @@
26042945 obj__printf(obj, "%-*s", pcnt_width, " ");
26052946 else {
26062947 obj__printf(obj, "%-*s", pcnt_width,
2607
- notes->options->show_total_period ? "Period" :
2608
- notes->options->show_nr_samples ? "Samples" : "Percent");
2948
+ symbol_conf.show_total_period ? "Period" :
2949
+ symbol_conf.show_nr_samples ? "Samples" : "Percent");
26092950 }
26102951 }
26112952
....@@ -2648,6 +2989,11 @@
26482989 obj__printf(obj, "%*s ",
26492990 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
26502991 "Cycle(min/max)");
2992
+ }
2993
+
2994
+ if (show_title && !*al->line) {
2995
+ ipc_coverage_string(bf, sizeof(bf), notes);
2996
+ obj__printf(obj, "%*s", ANNOTATION__AVG_IPC_WIDTH, bf);
26512997 }
26522998 }
26532999
....@@ -2723,9 +3069,10 @@
27233069 wops->write_graph);
27243070 }
27253071
2726
-int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
3072
+int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
27273073 struct annotation_options *options, struct arch **parch)
27283074 {
3075
+ struct symbol *sym = ms->sym;
27293076 struct annotation *notes = symbol__annotation(sym);
27303077 size_t size = symbol__size(sym);
27313078 int nr_pcnt = 1, err;
....@@ -2734,10 +3081,10 @@
27343081 if (notes->offsets == NULL)
27353082 return ENOMEM;
27363083
2737
- if (perf_evsel__is_group_event(evsel))
2738
- nr_pcnt = evsel->nr_members;
3084
+ if (evsel__is_group_event(evsel))
3085
+ nr_pcnt = evsel->core.nr_members;
27393086
2740
- err = symbol__annotate(sym, map, evsel, 0, options, parch);
3087
+ err = symbol__annotate(ms, evsel, options, parch);
27413088 if (err)
27423089 goto out_free_offsets;
27433090
....@@ -2752,6 +3099,7 @@
27523099 notes->nr_events = nr_pcnt;
27533100
27543101 annotation__update_column_widths(notes);
3102
+ sym->annotate2 = true;
27553103
27563104 return 0;
27573105
....@@ -2760,69 +3108,48 @@
27603108 return err;
27613109 }
27623110
2763
-#define ANNOTATION__CFG(n) \
2764
- { .name = #n, .value = &annotation__default_options.n, }
2765
-
2766
-/*
2767
- * Keep the entries sorted, they are bsearch'ed
2768
- */
2769
-static struct annotation_config {
2770
- const char *name;
2771
- void *value;
2772
-} annotation__configs[] = {
2773
- ANNOTATION__CFG(hide_src_code),
2774
- ANNOTATION__CFG(jump_arrows),
2775
- ANNOTATION__CFG(offset_level),
2776
- ANNOTATION__CFG(show_linenr),
2777
- ANNOTATION__CFG(show_nr_jumps),
2778
- ANNOTATION__CFG(show_nr_samples),
2779
- ANNOTATION__CFG(show_total_period),
2780
- ANNOTATION__CFG(use_offset),
2781
-};
2782
-
2783
-#undef ANNOTATION__CFG
2784
-
2785
-static int annotation_config__cmp(const void *name, const void *cfgp)
3111
+static int annotation__config(const char *var, const char *value, void *data)
27863112 {
2787
- const struct annotation_config *cfg = cfgp;
2788
-
2789
- return strcmp(name, cfg->name);
2790
-}
2791
-
2792
-static int annotation__config(const char *var, const char *value,
2793
- void *data __maybe_unused)
2794
-{
2795
- struct annotation_config *cfg;
2796
- const char *name;
3113
+ struct annotation_options *opt = data;
27973114
27983115 if (!strstarts(var, "annotate."))
27993116 return 0;
28003117
2801
- name = var + 9;
2802
- cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs),
2803
- sizeof(struct annotation_config), annotation_config__cmp);
3118
+ if (!strcmp(var, "annotate.offset_level")) {
3119
+ perf_config_u8(&opt->offset_level, "offset_level", value);
28043120
2805
- if (cfg == NULL)
2806
- pr_debug("%s variable unknown, ignoring...", var);
2807
- else if (strcmp(var, "annotate.offset_level") == 0) {
2808
- perf_config_int(cfg->value, name, value);
2809
-
2810
- if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL)
2811
- *(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL;
2812
- else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL)
2813
- *(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL;
3121
+ if (opt->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
3122
+ opt->offset_level = ANNOTATION__MAX_OFFSET_LEVEL;
3123
+ else if (opt->offset_level < ANNOTATION__MIN_OFFSET_LEVEL)
3124
+ opt->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
3125
+ } else if (!strcmp(var, "annotate.hide_src_code")) {
3126
+ opt->hide_src_code = perf_config_bool("hide_src_code", value);
3127
+ } else if (!strcmp(var, "annotate.jump_arrows")) {
3128
+ opt->jump_arrows = perf_config_bool("jump_arrows", value);
3129
+ } else if (!strcmp(var, "annotate.show_linenr")) {
3130
+ opt->show_linenr = perf_config_bool("show_linenr", value);
3131
+ } else if (!strcmp(var, "annotate.show_nr_jumps")) {
3132
+ opt->show_nr_jumps = perf_config_bool("show_nr_jumps", value);
3133
+ } else if (!strcmp(var, "annotate.show_nr_samples")) {
3134
+ symbol_conf.show_nr_samples = perf_config_bool("show_nr_samples",
3135
+ value);
3136
+ } else if (!strcmp(var, "annotate.show_total_period")) {
3137
+ symbol_conf.show_total_period = perf_config_bool("show_total_period",
3138
+ value);
3139
+ } else if (!strcmp(var, "annotate.use_offset")) {
3140
+ opt->use_offset = perf_config_bool("use_offset", value);
3141
+ } else if (!strcmp(var, "annotate.disassembler_style")) {
3142
+ opt->disassembler_style = value;
28143143 } else {
2815
- *(bool *)cfg->value = perf_config_bool(name, value);
3144
+ pr_debug("%s variable unknown, ignoring...", var);
28163145 }
3146
+
28173147 return 0;
28183148 }
28193149
2820
-void annotation_config__init(void)
3150
+void annotation_config__init(struct annotation_options *opt)
28213151 {
2822
- perf_config(annotation__config, NULL);
2823
-
2824
- annotation__default_options.show_total_period = symbol_conf.show_total_period;
2825
- annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
3152
+ perf_config(annotation__config, opt);
28263153 }
28273154
28283155 static unsigned int parse_percent_type(char *str1, char *str2)
....@@ -2876,3 +3203,12 @@
28763203 free(str1);
28773204 return err;
28783205 }
3206
+
3207
+int annotate_check_args(struct annotation_options *args)
3208
+{
3209
+ if (args->prefix_strip && !args->prefix) {
3210
+ pr_err("--prefix-strip requires --prefix\n");
3211
+ return -1;
3212
+ }
3213
+ return 0;
3214
+}