Commit 7cec0922389e080d11ec43dd23aa778e136bd1e1

Authored by David Ahern
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
... ... @@ -377,6 +377,7 @@
377 377 array++;
378 378 }
379 379  
  380 + data->addr = 0;
380 381 if (type & PERF_SAMPLE_ADDR) {
381 382 data->addr = *array;
382 383 array++;
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);