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

perf probe ppc64le: Prefer symbol table lookup over DWARF

Use symbol table lookups by default if DWARF is not necessary, since
powerpc ABIv2 encodes local entry points in the symbol table and the
function entry address in DWARF may not be appropriate for kprobes, as
described here:

https://sourceware.org/bugzilla/show_bug.cgi?id=17638

"The DWARF address ranges deliberately include the *whole* function,
both global and local entry points."
...
"If you want to set probes on a local entry point, you should look up
the symbol in the main symbol table (not DWARF), and check the st_other
bits; they will indicate whether the function has a local entry point,
and what its offset from the global entry point is. Note that GDB does
the same when setting a breakpoint on a function entry."

Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Reviewed-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Link: http://lkml.kernel.org/r/88a10e22f4aaba2aef812824ca4b10d7beeea012.1430217967.git.naveen.n.rao@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Naveen N. Rao and committed by
Arnaldo Carvalho de Melo
d5c2e2c1 c50fc0a4

+17
+8
tools/perf/arch/powerpc/util/sym-handling.c
··· 9 9 #include "debug.h" 10 10 #include "symbol.h" 11 11 #include "map.h" 12 + #include "probe-event.h" 12 13 13 14 #ifdef HAVE_LIBELF_SUPPORT 14 15 bool elf__needs_adjust_symbols(GElf_Ehdr ehdr) ··· 56 55 nameb++; 57 56 58 57 return strcmp(namea, nameb); 58 + } 59 + #endif 60 + 61 + #if defined(_CALL_ELF) && _CALL_ELF == 2 62 + bool arch__prefers_symtab(void) 63 + { 64 + return true; 59 65 } 60 66 #endif
+8
tools/perf/util/probe-event.c
··· 2567 2567 goto out; 2568 2568 } 2569 2569 2570 + bool __weak arch__prefers_symtab(void) { return false; } 2571 + 2570 2572 static int convert_to_probe_trace_events(struct perf_probe_event *pev, 2571 2573 struct probe_trace_event **tevs, 2572 2574 int max_tevs, const char *target) ··· 2582 2580 pr_warning("Failed to make a group name.\n"); 2583 2581 return ret; 2584 2582 } 2583 + } 2584 + 2585 + if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { 2586 + ret = find_probe_trace_events_from_map(pev, tevs, max_tevs, target); 2587 + if (ret > 0) 2588 + return ret; /* Found in symbol table */ 2585 2589 } 2586 2590 2587 2591 /* Convert perf_probe_event with debuginfo */
+1
tools/perf/util/probe-event.h
··· 135 135 struct strfilter *filter, bool externs); 136 136 extern int show_available_funcs(const char *module, struct strfilter *filter, 137 137 bool user); 138 + bool arch__prefers_symtab(void); 138 139 139 140 /* Maximum index number of event-name postfix */ 140 141 #define MAX_EVENT_INDEX 1024