diff options
author | David Ahern <dsahern@gmail.com> | 2011-05-30 15:08:23 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-06-02 12:31:01 -0400 |
commit | 7cec0922389e080d11ec43dd23aa778e136bd1e1 (patch) | |
tree | 0d772b32f38b4ef16e4256711e947b38baa2c2f9 /tools | |
parent | 610723f24eeb842025178a6722fa9108c4e157b6 (diff) |
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>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Documentation/perf-script.txt | 4 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 84 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 1 | ||||
-rw-r--r-- | tools/perf/util/session.c | 4 |
4 files changed, 82 insertions, 11 deletions
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 1e744c2391dc..c6068cb43f57 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt | |||
@@ -115,8 +115,8 @@ 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. Field | 118 | comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr. |
119 | 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 |
122 | 122 | ||
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a8bd00f2e557..3056b45b3dd6 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -33,6 +33,7 @@ enum perf_output_field { | |||
33 | PERF_OUTPUT_IP = 1U << 7, | 33 | PERF_OUTPUT_IP = 1U << 7, |
34 | PERF_OUTPUT_SYM = 1U << 8, | 34 | PERF_OUTPUT_SYM = 1U << 8, |
35 | PERF_OUTPUT_DSO = 1U << 9, | 35 | PERF_OUTPUT_DSO = 1U << 9, |
36 | PERF_OUTPUT_ADDR = 1U << 10, | ||
36 | }; | 37 | }; |
37 | 38 | ||
38 | struct output_option { | 39 | struct output_option { |
@@ -49,6 +50,7 @@ struct output_option { | |||
49 | {.str = "ip", .field = PERF_OUTPUT_IP}, | 50 | {.str = "ip", .field = PERF_OUTPUT_IP}, |
50 | {.str = "sym", .field = PERF_OUTPUT_SYM}, | 51 | {.str = "sym", .field = PERF_OUTPUT_SYM}, |
51 | {.str = "dso", .field = PERF_OUTPUT_DSO}, | 52 | {.str = "dso", .field = PERF_OUTPUT_DSO}, |
53 | {.str = "addr", .field = PERF_OUTPUT_ADDR}, | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | /* default set to maintain compatibility with current format */ | 56 | /* default set to maintain compatibility with current format */ |
@@ -173,14 +175,22 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, | |||
173 | !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) | 175 | !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) |
174 | symbol_conf.use_callchain = false; | 176 | symbol_conf.use_callchain = false; |
175 | } | 177 | } |
176 | if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP)) { | 178 | |
177 | pr_err("Display of symbols requested but IP is not selected.\n" | 179 | if (PRINT_FIELD(ADDR) && |
178 | "No addresses to convert to symbols.\n"); | 180 | perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR", |
181 | PERF_OUTPUT_ADDR)) | ||
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"); | ||
179 | return -EINVAL; | 188 | return -EINVAL; |
180 | } | 189 | } |
181 | if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP)) { | 190 | if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { |
182 | pr_err("Display of DSO requested but IP is not selected.\n" | 191 | pr_err("Display of DSO requested but neither sample IP nor " |
183 | "No addresses to convert to dso.\n"); | 192 | "sample address\nis selected. Hence, no addresses to convert " |
193 | "to DSO.\n"); | ||
184 | return -EINVAL; | 194 | return -EINVAL; |
185 | } | 195 | } |
186 | 196 | ||
@@ -288,6 +298,63 @@ static void print_sample_start(struct perf_sample *sample, | |||
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 | static void process_event(union perf_event *event __unused, | 358 | static void process_event(union perf_event *event __unused, |
292 | struct perf_sample *sample, | 359 | struct perf_sample *sample, |
293 | struct perf_evsel *evsel, | 360 | struct perf_evsel *evsel, |
@@ -305,6 +372,9 @@ static void process_event(union perf_event *event __unused, | |||
305 | print_trace_event(sample->cpu, sample->raw_data, | 372 | print_trace_event(sample->cpu, sample->raw_data, |
306 | sample->raw_size); | 373 | sample->raw_size); |
307 | 374 | ||
375 | if (PRINT_FIELD(ADDR)) | ||
376 | print_sample_addr(event, sample, session, thread, attr); | ||
377 | |||
308 | if (PRINT_FIELD(IP)) { | 378 | if (PRINT_FIELD(IP)) { |
309 | if (!symbol_conf.use_callchain) | 379 | if (!symbol_conf.use_callchain) |
310 | printf(" "); | 380 | printf(" "); |
@@ -1003,7 +1073,7 @@ static const struct option options[] = { | |||
1003 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 1073 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", |
1004 | "Look for files with symbols relative to this directory"), | 1074 | "Look for files with symbols relative to this directory"), |
1005 | OPT_CALLBACK('f', "fields", NULL, "str", | 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 | parse_output_fields), | 1077 | parse_output_fields), |
1008 | 1078 | ||
1009 | OPT_END() | 1079 | OPT_END() |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0239eb87b232..a03a36b7908a 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -377,6 +377,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, | |||
377 | array++; | 377 | array++; |
378 | } | 378 | } |
379 | 379 | ||
380 | data->addr = 0; | ||
380 | if (type & PERF_SAMPLE_ADDR) { | 381 | if (type & PERF_SAMPLE_ADDR) { |
381 | data->addr = *array; | 382 | data->addr = *array; |
382 | array++; | 383 | array++; |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0dd418299261..b723f211881c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -708,9 +708,9 @@ static void dump_sample(struct perf_session *session, union perf_event *event, | |||
708 | if (!dump_trace) | 708 | if (!dump_trace) |
709 | return; | 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 | event->header.misc, sample->pid, sample->tid, sample->ip, | 712 | event->header.misc, sample->pid, sample->tid, sample->ip, |
713 | sample->period); | 713 | sample->period, sample->addr); |
714 | 714 | ||
715 | if (session->sample_type & PERF_SAMPLE_CALLCHAIN) | 715 | if (session->sample_type & PERF_SAMPLE_CALLCHAIN) |
716 | callchain__printf(sample); | 716 | callchain__printf(sample); |