perf tools powerpc: Adjust callchain based on DWARF debug info
When saving the callchain on Power, the kernel conservatively saves excess entries in the callchain. A few of these entries are needed in some cases but not others. We should use the DWARF debug information to determine when the entries are needed. Eg: the value in the link register (LR) is needed only when it holds the return address of a function. At other times it must be ignored. If the unnecessary entries are not ignored, we end up with duplicate arcs in the call-graphs. Use the DWARF debug information to determine if any callchain entries should be ignored when building call-graphs. Callgraph before the patch: 14.67% 2234 sprintft libc-2.18.so [.] __random | --- __random | |--61.12%-- __random | | | |--97.15%-- rand | | do_my_sprintf | | main | | generic_start_main.isra.0 | | __libc_start_main | | 0x0 | | | --2.85%-- do_my_sprintf | main | generic_start_main.isra.0 | __libc_start_main | 0x0 | --38.88%-- rand | |--94.01%-- rand | do_my_sprintf | main | generic_start_main.isra.0 | __libc_start_main | 0x0 | --5.99%-- do_my_sprintf main generic_start_main.isra.0 __libc_start_main 0x0 Callgraph after the patch: 14.67% 2234 sprintft libc-2.18.so [.] __random | --- __random | |--95.93%-- rand | do_my_sprintf | main | generic_start_main.isra.0 | __libc_start_main | 0x0 | --4.07%-- do_my_sprintf main generic_start_main.isra.0 __libc_start_main 0x0 TODO: For split-debug info objects like glibc, we can only determine the call-frame-address only when both .eh_frame and .debug_info sections are available. We should be able to determin the CFA even without the .eh_frame section. Fix suggested by Anton Blanchard. Thanks to valuable input on DWARF debug information from Ulrich Weigand. Reported-by: Maynard Johnson <maynard@us.ibm.com> Tested-by: Maynard Johnson <maynard@us.ibm.com> Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Link: http://lkml.kernel.org/r/20140625154903.GA29607@us.ibm.com Signed-off-by: Jiri Olsa <jolsa@kernel.org>
This commit is contained in:

committed by
Jiri Olsa

parent
21da83fb6c
commit
a60335ba32
@@ -1281,7 +1281,9 @@ static int machine__resolve_callchain_sample(struct machine *machine,
|
||||
u8 cpumode = PERF_RECORD_MISC_USER;
|
||||
int chain_nr = min(max_stack, (int)chain->nr);
|
||||
int i;
|
||||
int j;
|
||||
int err;
|
||||
int skip_idx __maybe_unused;
|
||||
|
||||
callchain_cursor_reset(&callchain_cursor);
|
||||
|
||||
@@ -1290,14 +1292,26 @@ static int machine__resolve_callchain_sample(struct machine *machine,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Based on DWARF debug information, some architectures skip
|
||||
* a callchain entry saved by the kernel.
|
||||
*/
|
||||
skip_idx = arch_skip_callchain_idx(machine, thread, chain);
|
||||
|
||||
for (i = 0; i < chain_nr; i++) {
|
||||
u64 ip;
|
||||
struct addr_location al;
|
||||
|
||||
if (callchain_param.order == ORDER_CALLEE)
|
||||
ip = chain->ips[i];
|
||||
j = i;
|
||||
else
|
||||
ip = chain->ips[chain->nr - i - 1];
|
||||
j = chain->nr - i - 1;
|
||||
|
||||
#ifdef HAVE_SKIP_CALLCHAIN_IDX
|
||||
if (j == skip_idx)
|
||||
continue;
|
||||
#endif
|
||||
ip = chain->ips[j];
|
||||
|
||||
if (ip >= PERF_CONTEXT_MAX) {
|
||||
switch (ip) {
|
||||
|
Reference in New Issue
Block a user