Commit 7cec0922389e080d11ec43dd23aa778e136bd1e1
Committed by
Arnaldo Carvalho de Melo
1 parent
610723f24e
perf script: Add printing of sample address
Resolve to a function or variable if possible and if the sym option is enabled. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1306782503-22002-1-git-send-email-dsahern@gmail.com Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Showing 4 changed files with 82 additions and 11 deletions Side-by-side Diff
tools/perf/Documentation/perf-script.txt
... | ... | @@ -115,8 +115,8 @@ |
115 | 115 | -f:: |
116 | 116 | --fields:: |
117 | 117 | Comma separated list of fields to print. Options are: |
118 | - comm, tid, pid, time, cpu, event, trace, ip, sym, dso. Field | |
119 | - list can be prepended with the type, trace, sw or hw, | |
118 | + comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr. | |
119 | + Field list can be prepended with the type, trace, sw or hw, | |
120 | 120 | to indicate to which event type the field list applies. |
121 | 121 | e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace |
122 | 122 |
tools/perf/builtin-script.c
... | ... | @@ -33,6 +33,7 @@ |
33 | 33 | PERF_OUTPUT_IP = 1U << 7, |
34 | 34 | PERF_OUTPUT_SYM = 1U << 8, |
35 | 35 | PERF_OUTPUT_DSO = 1U << 9, |
36 | + PERF_OUTPUT_ADDR = 1U << 10, | |
36 | 37 | }; |
37 | 38 | |
38 | 39 | struct output_option { |
... | ... | @@ -49,6 +50,7 @@ |
49 | 50 | {.str = "ip", .field = PERF_OUTPUT_IP}, |
50 | 51 | {.str = "sym", .field = PERF_OUTPUT_SYM}, |
51 | 52 | {.str = "dso", .field = PERF_OUTPUT_DSO}, |
53 | + {.str = "addr", .field = PERF_OUTPUT_ADDR}, | |
52 | 54 | }; |
53 | 55 | |
54 | 56 | /* default set to maintain compatibility with current format */ |
55 | 57 | |
56 | 58 | |
... | ... | @@ -173,14 +175,22 @@ |
173 | 175 | !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) |
174 | 176 | symbol_conf.use_callchain = false; |
175 | 177 | } |
176 | - if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP)) { | |
177 | - pr_err("Display of symbols requested but IP is not selected.\n" | |
178 | - "No addresses to convert to symbols.\n"); | |
178 | + | |
179 | + if (PRINT_FIELD(ADDR) && | |
180 | + perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR", | |
181 | + PERF_OUTPUT_ADDR)) | |
179 | 182 | return -EINVAL; |
183 | + | |
184 | + if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { | |
185 | + pr_err("Display of symbols requested but neither sample IP nor " | |
186 | + "sample address\nis selected. Hence, no addresses to convert " | |
187 | + "to symbols.\n"); | |
188 | + return -EINVAL; | |
180 | 189 | } |
181 | - if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP)) { | |
182 | - pr_err("Display of DSO requested but IP is not selected.\n" | |
183 | - "No addresses to convert to dso.\n"); | |
190 | + if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { | |
191 | + pr_err("Display of DSO requested but neither sample IP nor " | |
192 | + "sample address\nis selected. Hence, no addresses to convert " | |
193 | + "to DSO.\n"); | |
184 | 194 | return -EINVAL; |
185 | 195 | } |
186 | 196 | |
... | ... | @@ -288,6 +298,63 @@ |
288 | 298 | } |
289 | 299 | } |
290 | 300 | |
301 | +static bool sample_addr_correlates_sym(struct perf_event_attr *attr) | |
302 | +{ | |
303 | + if ((attr->type == PERF_TYPE_SOFTWARE) && | |
304 | + ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) || | |
305 | + (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) || | |
306 | + (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))) | |
307 | + return true; | |
308 | + | |
309 | + return false; | |
310 | +} | |
311 | + | |
312 | +static void print_sample_addr(union perf_event *event, | |
313 | + struct perf_sample *sample, | |
314 | + struct perf_session *session, | |
315 | + struct thread *thread, | |
316 | + struct perf_event_attr *attr) | |
317 | +{ | |
318 | + struct addr_location al; | |
319 | + u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | |
320 | + const char *symname, *dsoname; | |
321 | + | |
322 | + printf("%16" PRIx64, sample->addr); | |
323 | + | |
324 | + if (!sample_addr_correlates_sym(attr)) | |
325 | + return; | |
326 | + | |
327 | + thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, | |
328 | + event->ip.pid, sample->addr, &al); | |
329 | + if (!al.map) | |
330 | + thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE, | |
331 | + event->ip.pid, sample->addr, &al); | |
332 | + | |
333 | + al.cpu = sample->cpu; | |
334 | + al.sym = NULL; | |
335 | + | |
336 | + if (al.map) | |
337 | + al.sym = map__find_symbol(al.map, al.addr, NULL); | |
338 | + | |
339 | + if (PRINT_FIELD(SYM)) { | |
340 | + if (al.sym && al.sym->name) | |
341 | + symname = al.sym->name; | |
342 | + else | |
343 | + symname = ""; | |
344 | + | |
345 | + printf(" %16s", symname); | |
346 | + } | |
347 | + | |
348 | + if (PRINT_FIELD(DSO)) { | |
349 | + if (al.map && al.map->dso && al.map->dso->name) | |
350 | + dsoname = al.map->dso->name; | |
351 | + else | |
352 | + dsoname = ""; | |
353 | + | |
354 | + printf(" (%s)", dsoname); | |
355 | + } | |
356 | +} | |
357 | + | |
291 | 358 | static void process_event(union perf_event *event __unused, |
292 | 359 | struct perf_sample *sample, |
293 | 360 | struct perf_evsel *evsel, |
... | ... | @@ -305,6 +372,9 @@ |
305 | 372 | print_trace_event(sample->cpu, sample->raw_data, |
306 | 373 | sample->raw_size); |
307 | 374 | |
375 | + if (PRINT_FIELD(ADDR)) | |
376 | + print_sample_addr(event, sample, session, thread, attr); | |
377 | + | |
308 | 378 | if (PRINT_FIELD(IP)) { |
309 | 379 | if (!symbol_conf.use_callchain) |
310 | 380 | printf(" "); |
... | ... | @@ -1003,7 +1073,7 @@ |
1003 | 1073 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", |
1004 | 1074 | "Look for files with symbols relative to this directory"), |
1005 | 1075 | OPT_CALLBACK('f', "fields", NULL, "str", |
1006 | - "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso", | |
1076 | + "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", | |
1007 | 1077 | parse_output_fields), |
1008 | 1078 | |
1009 | 1079 | OPT_END() |
tools/perf/util/evsel.c
tools/perf/util/session.c
... | ... | @@ -708,9 +708,9 @@ |
708 | 708 | if (!dump_trace) |
709 | 709 | return; |
710 | 710 | |
711 | - printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n", | |
711 | + printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n", | |
712 | 712 | event->header.misc, sample->pid, sample->tid, sample->ip, |
713 | - sample->period); | |
713 | + sample->period, sample->addr); | |
714 | 714 | |
715 | 715 | if (session->sample_type & PERF_SAMPLE_CALLCHAIN) |
716 | 716 | callchain__printf(sample); |