aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
authorMark Santaniello <marksan@fb.com>2017-06-19 12:38:24 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-06-19 21:05:40 -0400
commit55b9b50811ca459e4688543b688b7b2b85ec5ea8 (patch)
treebe78e60a1421fadb188a80309d31cb18f3387858 /tools/perf/builtin-script.c
parent9b57fb7e35957c6838f89f4ed7e3f8433a4bbfc5 (diff)
perf script: Support -F brstack,dso and brstacksym,dso
Perf script can report the dso for "addr" and "ip" fields. This adds the same support for the "brstack" and "brstacksym" fields. This can be helpful for AutoFDO: we can ignore LBR entries unless the source and target address are both in the target module we are about to build. I built a small test akin to "while(1) { do_nothing(); }" where the do_nothing function is loaded from a dso: $ cat burncpu.cpp #include <dlfcn.h> int main() { void* handle = dlopen("./dso.so", RTLD_LAZY); if (!handle) return -1; typedef void (*fp)(); fp do_nothing = (fp) dlsym(handle, "do_nothing"); while(1) { do_nothing(); } } $ cat dso.cpp extern "C" void do_nothing() {} $ cat build.sh #!/bin/bash g++ -shared dso.cpp -o dso.so g++ burncpu.cpp -o burncpu -ldl I sampled the execution with perf record -b. Using the new perf script functionality I can easily find cases where there was a transition from one dso to another: $ perf record -a -b -- sleep 5 [ perf record: Woken up 55 times to write data ] [ perf record: Captured and wrote 18.815 MB perf.data (43593 samples) ] $ perf script -F brstack,dso | sed 's/\/0 /\/0\n/g' | grep burncpu | grep dso.so | head -n 1 0x7f967139b6aa(/tmp/burncpu/dso.so)/0x4006b1(/tmp/burncpu/exe)/P/-/-/0 $ perf script -F brstacksym,dso | sed 's/\/0 /\/0\n/g' | grep burncpu | grep dso.so | head -n 1 do_nothing+0x5(/tmp/burncpu/dso.so)/main+0x44(/tmp/burncpu/exe)/P/-/-/0 Signed-off-by: Mark Santaniello <marksan@fb.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20170619163825.2012979-1-marksan@fb.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c61
1 files changed, 49 insertions, 12 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index afa84debc5c4..3c21089f5273 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -298,10 +298,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
298 "selected.\n"); 298 "selected.\n");
299 return -EINVAL; 299 return -EINVAL;
300 } 300 }
301 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 301 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) &&
302 pr_err("Display of DSO requested but neither sample IP nor " 302 !PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM)) {
303 "sample address\nis selected. Hence, no addresses to convert " 303 pr_err("Display of DSO requested but none of sample IP, sample address, "
304 "to DSO.\n"); 304 "brstack\nor brstacksym are selected. Hence, no addresses to "
305 "convert to DSO.\n");
305 return -EINVAL; 306 return -EINVAL;
306 } 307 }
307 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { 308 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
@@ -514,18 +515,43 @@ mispred_str(struct branch_entry *br)
514 return br->flags.predicted ? 'P' : 'M'; 515 return br->flags.predicted ? 'P' : 'M';
515} 516}
516 517
517static void print_sample_brstack(struct perf_sample *sample) 518static void print_sample_brstack(struct perf_sample *sample,
519 struct thread *thread,
520 struct perf_event_attr *attr)
518{ 521{
519 struct branch_stack *br = sample->branch_stack; 522 struct branch_stack *br = sample->branch_stack;
520 u64 i; 523 struct addr_location alf, alt;
524 u64 i, from, to;
521 525
522 if (!(br && br->nr)) 526 if (!(br && br->nr))
523 return; 527 return;
524 528
525 for (i = 0; i < br->nr; i++) { 529 for (i = 0; i < br->nr; i++) {
526 printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ", 530 from = br->entries[i].from;
527 br->entries[i].from, 531 to = br->entries[i].to;
528 br->entries[i].to, 532
533 if (PRINT_FIELD(DSO)) {
534 memset(&alf, 0, sizeof(alf));
535 memset(&alt, 0, sizeof(alt));
536 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf);
537 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
538 }
539
540 printf("0x%"PRIx64, from);
541 if (PRINT_FIELD(DSO)) {
542 printf("(");
543 map__fprintf_dsoname(alf.map, stdout);
544 printf(")");
545 }
546
547 printf("/0x%"PRIx64, to);
548 if (PRINT_FIELD(DSO)) {
549 printf("(");
550 map__fprintf_dsoname(alt.map, stdout);
551 printf(")");
552 }
553
554 printf("/%c/%c/%c/%d ",
529 mispred_str( br->entries + i), 555 mispred_str( br->entries + i),
530 br->entries[i].flags.in_tx? 'X' : '-', 556 br->entries[i].flags.in_tx? 'X' : '-',
531 br->entries[i].flags.abort? 'A' : '-', 557 br->entries[i].flags.abort? 'A' : '-',
@@ -534,7 +560,8 @@ static void print_sample_brstack(struct perf_sample *sample)
534} 560}
535 561
536static void print_sample_brstacksym(struct perf_sample *sample, 562static void print_sample_brstacksym(struct perf_sample *sample,
537 struct thread *thread) 563 struct thread *thread,
564 struct perf_event_attr *attr)
538{ 565{
539 struct branch_stack *br = sample->branch_stack; 566 struct branch_stack *br = sample->branch_stack;
540 struct addr_location alf, alt; 567 struct addr_location alf, alt;
@@ -559,8 +586,18 @@ static void print_sample_brstacksym(struct perf_sample *sample,
559 alt.sym = map__find_symbol(alt.map, alt.addr); 586 alt.sym = map__find_symbol(alt.map, alt.addr);
560 587
561 symbol__fprintf_symname_offs(alf.sym, &alf, stdout); 588 symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
589 if (PRINT_FIELD(DSO)) {
590 printf("(");
591 map__fprintf_dsoname(alf.map, stdout);
592 printf(")");
593 }
562 putchar('/'); 594 putchar('/');
563 symbol__fprintf_symname_offs(alt.sym, &alt, stdout); 595 symbol__fprintf_symname_offs(alt.sym, &alt, stdout);
596 if (PRINT_FIELD(DSO)) {
597 printf("(");
598 map__fprintf_dsoname(alt.map, stdout);
599 printf(")");
600 }
564 printf("/%c/%c/%c/%d ", 601 printf("/%c/%c/%c/%d ",
565 mispred_str( br->entries + i), 602 mispred_str( br->entries + i),
566 br->entries[i].flags.in_tx? 'X' : '-', 603 br->entries[i].flags.in_tx? 'X' : '-',
@@ -1187,9 +1224,9 @@ static void process_event(struct perf_script *script,
1187 print_sample_iregs(sample, attr); 1224 print_sample_iregs(sample, attr);
1188 1225
1189 if (PRINT_FIELD(BRSTACK)) 1226 if (PRINT_FIELD(BRSTACK))
1190 print_sample_brstack(sample); 1227 print_sample_brstack(sample, thread, attr);
1191 else if (PRINT_FIELD(BRSTACKSYM)) 1228 else if (PRINT_FIELD(BRSTACKSYM))
1192 print_sample_brstacksym(sample, thread); 1229 print_sample_brstacksym(sample, thread, attr);
1193 1230
1194 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) 1231 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
1195 print_sample_bpf_output(sample); 1232 print_sample_bpf_output(sample);