Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf callchain: Add order support for libunwind DWARF unwinder

As reported by Milian, currently for DWARF unwind (both libdw and
libunwind) we display callchain in callee order only.

Adding the support to follow callchain order setup to libunwind DWARF
unwinder, so we could get following output for report:

$ perf record --call-graph dwarf ls
...
$ perf report --no-children --stdio

39.26% ls libc-2.21.so [.] __strcoll_l
|
---__strcoll_l
mpsort_with_tmp
mpsort_with_tmp
sort_files
main
__libc_start_main
_start
0

$ perf report -g caller --no-children --stdio
...
39.26% ls libc-2.21.so [.] __strcoll_l
|
---0
_start
__libc_start_main
main
sort_files
mpsort_with_tmp
mpsort_with_tmp
__strcoll_l

Based-on-patch-by: Milian Wolff <milian.wolff@kdab.com>
Reported-and-Tested-by: Milian Wolff <milian.wolff@kdab.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Wang Nan <wangnan0@huawei.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/20151118075247.GA5416@krava.brq.redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
cb1dc22d b26b218a

+29 -16
+29 -16
tools/perf/util/unwind-libunwind.c
··· 615 615 void *arg, int max_stack) 616 616 { 617 617 u64 val; 618 + unw_word_t ips[max_stack]; 618 619 unw_addr_space_t addr_space; 619 620 unw_cursor_t c; 620 - int ret; 621 + int ret, i = 0; 621 622 622 623 ret = perf_reg_value(&val, &ui->sample->user_regs, PERF_REG_IP); 623 624 if (ret) 624 625 return ret; 625 626 626 - ret = entry(val, ui->thread, cb, arg); 627 - if (ret) 628 - return -ENOMEM; 627 + ips[i++] = (unw_word_t) val; 629 628 630 - if (--max_stack == 0) 631 - return 0; 629 + /* 630 + * If we need more than one entry, do the DWARF 631 + * unwind itself. 632 + */ 633 + if (max_stack - 1 > 0) { 634 + addr_space = thread__priv(ui->thread); 635 + if (addr_space == NULL) 636 + return -1; 632 637 633 - addr_space = thread__priv(ui->thread); 634 - if (addr_space == NULL) 635 - return -1; 638 + ret = unw_init_remote(&c, addr_space, ui); 639 + if (ret) 640 + display_error(ret); 636 641 637 - ret = unw_init_remote(&c, addr_space, ui); 638 - if (ret) 639 - display_error(ret); 642 + while (!ret && (unw_step(&c) > 0) && i < max_stack) { 643 + unw_get_reg(&c, UNW_REG_IP, &ips[i]); 644 + ++i; 645 + } 640 646 641 - while (!ret && (unw_step(&c) > 0) && max_stack--) { 642 - unw_word_t ip; 647 + max_stack = i; 648 + } 643 649 644 - unw_get_reg(&c, UNW_REG_IP, &ip); 645 - ret = ip ? entry(ip, ui->thread, cb, arg) : 0; 650 + /* 651 + * Display what we got based on the order setup. 652 + */ 653 + for (i = 0; i < max_stack && !ret; i++) { 654 + int j = i; 655 + 656 + if (callchain_param.order == ORDER_CALLER) 657 + j = max_stack - i - 1; 658 + ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0; 646 659 } 647 660 648 661 return ret;