diff options
author | Akihiro Nagai <akihiro.nagai.hw@hitachi.com> | 2012-01-29 23:43:15 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-01-30 15:09:21 -0500 |
commit | a978f2ab4166a84c77d0f846f59690f2a892d058 (patch) | |
tree | 015a35d71132a28a53b729be99ab469ebb641a66 /tools/perf | |
parent | 9558259697b827106b464648e850e568e0b0c931 (diff) |
perf script: Add the offset field specifier
Add the offset field specifier 'symoff' to show the offset from
the symbols in the output of perf-script. We can get the more
detailed address information.
Output sample:
ffffffff81467612 irq_return+0x0 => 301ec016b0 _start+0x0
ffffffff81467612 irq_return+0x0 => 301ec016b0 _start+0x0
301ec016b3 _start+0x3 => 301ec04b70 _dl_start+0x0
ffffffff81467612 irq_return+0x0 => 301ec04b70 _dl_start+0x0
ffffffff81467612 irq_return+0x0 => 301ec04b96 _dl_start+0x26
ffffffff81467612 irq_return+0x0 => 301ec04b9d _dl_start+0x2d
301ec04beb _dl_start+0x7b => 301ec04c0d _dl_start+0x9d
301ec04c11 _dl_start+0xa1 => 301ec04bf0 _dl_start+0x80
[snip]
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: yrl.pp-manager.tt@hitachi.com
Link: http://lkml.kernel.org/r/20120130044314.2384.67094.stgit@linux3
Signed-off-by: Akihiro Nagai <akihiro.nagai.hw@hitachi.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/Documentation/perf-script.txt | 2 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 23 | ||||
-rw-r--r-- | tools/perf/util/session.c | 8 | ||||
-rw-r--r-- | tools/perf/util/session.h | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 24 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 2 |
6 files changed, 46 insertions, 15 deletions
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 2f6cef43da25..228c7bb0f0dd 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt | |||
@@ -115,7 +115,7 @@ OPTIONS | |||
115 | -f:: | 115 | -f:: |
116 | --fields:: | 116 | --fields:: |
117 | Comma separated list of fields to print. Options are: | 117 | Comma separated list of fields to print. Options are: |
118 | comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr. | 118 | comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff. |
119 | Field list can be prepended with the type, trace, sw or hw, | 119 | Field list can be prepended with the type, trace, sw or hw, |
120 | to indicate to which event type the field list applies. | 120 | to indicate to which event type the field list applies. |
121 | e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace | 121 | e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 414d49ad83de..752d4018d06d 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -40,6 +40,7 @@ enum perf_output_field { | |||
40 | PERF_OUTPUT_SYM = 1U << 8, | 40 | PERF_OUTPUT_SYM = 1U << 8, |
41 | PERF_OUTPUT_DSO = 1U << 9, | 41 | PERF_OUTPUT_DSO = 1U << 9, |
42 | PERF_OUTPUT_ADDR = 1U << 10, | 42 | PERF_OUTPUT_ADDR = 1U << 10, |
43 | PERF_OUTPUT_SYMOFFSET = 1U << 11, | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | struct output_option { | 46 | struct output_option { |
@@ -57,6 +58,7 @@ struct output_option { | |||
57 | {.str = "sym", .field = PERF_OUTPUT_SYM}, | 58 | {.str = "sym", .field = PERF_OUTPUT_SYM}, |
58 | {.str = "dso", .field = PERF_OUTPUT_DSO}, | 59 | {.str = "dso", .field = PERF_OUTPUT_DSO}, |
59 | {.str = "addr", .field = PERF_OUTPUT_ADDR}, | 60 | {.str = "addr", .field = PERF_OUTPUT_ADDR}, |
61 | {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, | ||
60 | }; | 62 | }; |
61 | 63 | ||
62 | /* default set to maintain compatibility with current format */ | 64 | /* default set to maintain compatibility with current format */ |
@@ -193,6 +195,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, | |||
193 | "to symbols.\n"); | 195 | "to symbols.\n"); |
194 | return -EINVAL; | 196 | return -EINVAL; |
195 | } | 197 | } |
198 | if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) { | ||
199 | pr_err("Display of offsets requested but symbol is not" | ||
200 | "selected.\n"); | ||
201 | return -EINVAL; | ||
202 | } | ||
196 | if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { | 203 | if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { |
197 | pr_err("Display of DSO requested but neither sample IP nor " | 204 | pr_err("Display of DSO requested but neither sample IP nor " |
198 | "sample address\nis selected. Hence, no addresses to convert " | 205 | "sample address\nis selected. Hence, no addresses to convert " |
@@ -353,7 +360,10 @@ static void print_sample_addr(union perf_event *event, | |||
353 | 360 | ||
354 | if (PRINT_FIELD(SYM)) { | 361 | if (PRINT_FIELD(SYM)) { |
355 | printf(" "); | 362 | printf(" "); |
356 | symbol__fprintf_symname(al.sym, stdout); | 363 | if (PRINT_FIELD(SYMOFFSET)) |
364 | symbol__fprintf_symname_offs(al.sym, &al, stdout); | ||
365 | else | ||
366 | symbol__fprintf_symname(al.sym, stdout); | ||
357 | } | 367 | } |
358 | 368 | ||
359 | if (PRINT_FIELD(DSO)) { | 369 | if (PRINT_FIELD(DSO)) { |
@@ -378,7 +388,8 @@ static void print_sample_bts(union perf_event *event, | |||
378 | else | 388 | else |
379 | printf("\n"); | 389 | printf("\n"); |
380 | perf_event__print_ip(event, sample, machine, evsel, | 390 | perf_event__print_ip(event, sample, machine, evsel, |
381 | PRINT_FIELD(SYM), PRINT_FIELD(DSO)); | 391 | PRINT_FIELD(SYM), PRINT_FIELD(DSO), |
392 | PRINT_FIELD(SYMOFFSET)); | ||
382 | } | 393 | } |
383 | 394 | ||
384 | printf(" => "); | 395 | printf(" => "); |
@@ -421,7 +432,8 @@ static void process_event(union perf_event *event __unused, | |||
421 | else | 432 | else |
422 | printf("\n"); | 433 | printf("\n"); |
423 | perf_event__print_ip(event, sample, machine, evsel, | 434 | perf_event__print_ip(event, sample, machine, evsel, |
424 | PRINT_FIELD(SYM), PRINT_FIELD(DSO)); | 435 | PRINT_FIELD(SYM), PRINT_FIELD(DSO), |
436 | PRINT_FIELD(SYMOFFSET)); | ||
425 | } | 437 | } |
426 | 438 | ||
427 | printf("\n"); | 439 | printf("\n"); |
@@ -1131,7 +1143,10 @@ static const struct option options[] = { | |||
1131 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 1143 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", |
1132 | "Look for files with symbols relative to this directory"), | 1144 | "Look for files with symbols relative to this directory"), |
1133 | OPT_CALLBACK('f', "fields", NULL, "str", | 1145 | OPT_CALLBACK('f', "fields", NULL, "str", |
1134 | "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr", | 1146 | "comma separated output fields prepend with 'type:'. " |
1147 | "Valid types: hw,sw,trace,raw. " | ||
1148 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," | ||
1149 | "addr,symoff", | ||
1135 | parse_output_fields), | 1150 | parse_output_fields), |
1136 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 1151 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
1137 | "system-wide collection from all CPUs"), | 1152 | "system-wide collection from all CPUs"), |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index e5334a976536..552c1c50eea1 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -1293,7 +1293,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | |||
1293 | 1293 | ||
1294 | void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | 1294 | void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, |
1295 | struct machine *machine, struct perf_evsel *evsel, | 1295 | struct machine *machine, struct perf_evsel *evsel, |
1296 | int print_sym, int print_dso) | 1296 | int print_sym, int print_dso, int print_symoffset) |
1297 | { | 1297 | { |
1298 | struct addr_location al; | 1298 | struct addr_location al; |
1299 | struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; | 1299 | struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; |
@@ -1340,7 +1340,11 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
1340 | printf("%16" PRIx64, sample->ip); | 1340 | printf("%16" PRIx64, sample->ip); |
1341 | if (print_sym) { | 1341 | if (print_sym) { |
1342 | printf(" "); | 1342 | printf(" "); |
1343 | symbol__fprintf_symname(al.sym, stdout); | 1343 | if (print_symoffset) |
1344 | symbol__fprintf_symname_offs(al.sym, &al, | ||
1345 | stdout); | ||
1346 | else | ||
1347 | symbol__fprintf_symname(al.sym, stdout); | ||
1344 | } | 1348 | } |
1345 | 1349 | ||
1346 | if (print_dso) { | 1350 | if (print_dso) { |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 37bc38381fb6..c8d90178e7de 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -147,7 +147,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | |||
147 | 147 | ||
148 | void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | 148 | void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, |
149 | struct machine *machine, struct perf_evsel *evsel, | 149 | struct machine *machine, struct perf_evsel *evsel, |
150 | int print_sym, int print_dso); | 150 | int print_sym, int print_dso, int print_symoffset); |
151 | 151 | ||
152 | int perf_session__cpu_bitmap(struct perf_session *session, | 152 | int perf_session__cpu_bitmap(struct perf_session *session, |
153 | const char *cpu_list, unsigned long *cpu_bitmap); | 153 | const char *cpu_list, unsigned long *cpu_bitmap); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index b580fa82911a..fc6e12fe4b44 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -263,16 +263,26 @@ static size_t symbol__fprintf(struct symbol *sym, FILE *fp) | |||
263 | sym->name); | 263 | sym->name); |
264 | } | 264 | } |
265 | 265 | ||
266 | size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp) | 266 | size_t symbol__fprintf_symname_offs(const struct symbol *sym, |
267 | const struct addr_location *al, FILE *fp) | ||
267 | { | 268 | { |
268 | const char *symname; | 269 | unsigned long offset; |
270 | size_t length; | ||
269 | 271 | ||
270 | if (sym && sym->name) | 272 | if (sym && sym->name) { |
271 | symname = sym->name; | 273 | length = fprintf(fp, "%s", sym->name); |
272 | else | 274 | if (al) { |
273 | symname = "[unknown]"; | 275 | offset = al->addr - sym->start; |
276 | length += fprintf(fp, "+0x%lx", offset); | ||
277 | } | ||
278 | return length; | ||
279 | } else | ||
280 | return fprintf(fp, "[unknown]"); | ||
281 | } | ||
274 | 282 | ||
275 | return fprintf(fp, "%s", symname); | 283 | size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp) |
284 | { | ||
285 | return symbol__fprintf_symname_offs(sym, NULL, fp); | ||
276 | } | 286 | } |
277 | 287 | ||
278 | void dso__set_long_name(struct dso *dso, char *name) | 288 | void dso__set_long_name(struct dso *dso, char *name) |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index d349c7a00b04..ba909c9970e2 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -241,6 +241,8 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines); | |||
241 | 241 | ||
242 | int symbol__init(void); | 242 | int symbol__init(void); |
243 | void symbol__exit(void); | 243 | void symbol__exit(void); |
244 | size_t symbol__fprintf_symname_offs(const struct symbol *sym, | ||
245 | const struct addr_location *al, FILE *fp); | ||
244 | size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); | 246 | size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); |
245 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); | 247 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); |
246 | 248 | ||