aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2011-05-30 15:08:23 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-06-02 12:31:01 -0400
commit7cec0922389e080d11ec43dd23aa778e136bd1e1 (patch)
tree0d772b32f38b4ef16e4256711e947b38baa2c2f9 /tools
parent610723f24eeb842025178a6722fa9108c4e157b6 (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.txt4
-rw-r--r--tools/perf/builtin-script.c84
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/session.c4
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
38struct output_option { 39struct 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
301static 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
312static 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
291static void process_event(union perf_event *event __unused, 358static 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);