aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNaveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>2016-04-12 05:10:50 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-05-05 20:04:03 -0400
commit0b3c2264ae30ed692fd1ffd2b84c5fbdf737cb0d (patch)
treef26cae86be020c92c2a78880da9af369427f3456
parent239aeba764092b29dd7cab177cd47f472390622e (diff)
perf symbols: Fix kallsyms perf test on ppc64le
ppc64le functions have a Global Entry Point (GEP) and a Local Entry Point (LEP). While placing a probe, we always prefer the LEP since it catches function calls through both the GEP and the LEP. In order to do this, we fixup the function entry points during elf symbol table lookup to point to the LEPs. This works, but breaks 'perf test kallsyms' since the symbols loaded from the symbol table (pointing to the LEP) do not match the symbols in kallsyms. To fix this, we do not adjust all the symbols during symbol table load. Instead, we note down st_other in a newly introduced arch-specific member of perf symbol structure, and later use this to adjust the probe trace point. Reported-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Acked-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Acked-by: Balbir Singh <bsingharora@gmail.com> Cc: Mark Wielaard <mjw@redhat.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/6be7c2b17e370100c2f79dd444509df7929bdd3e.1460451721.git.naveen.n.rao@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c28
-rw-r--r--tools/perf/util/probe-event.c5
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/symbol-elf.c7
-rw-r--r--tools/perf/util/symbol.h3
5 files changed, 31 insertions, 15 deletions
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index 6974ba0fa065..c6d0f91731a1 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -19,12 +19,6 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
19 ehdr.e_type == ET_DYN; 19 ehdr.e_type == ET_DYN;
20} 20}
21 21
22#if defined(_CALL_ELF) && _CALL_ELF == 2
23void arch__elf_sym_adjust(GElf_Sym *sym)
24{
25 sym->st_value += PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
26}
27#endif
28#endif 22#endif
29 23
30#if !defined(_CALL_ELF) || _CALL_ELF != 2 24#if !defined(_CALL_ELF) || _CALL_ELF != 2
@@ -65,11 +59,21 @@ bool arch__prefers_symtab(void)
65 return true; 59 return true;
66} 60}
67 61
62#ifdef HAVE_LIBELF_SUPPORT
63void arch__sym_update(struct symbol *s, GElf_Sym *sym)
64{
65 s->arch_sym = sym->st_other;
66}
67#endif
68
68#define PPC64LE_LEP_OFFSET 8 69#define PPC64LE_LEP_OFFSET 8
69 70
70void arch__fix_tev_from_maps(struct perf_probe_event *pev, 71void arch__fix_tev_from_maps(struct perf_probe_event *pev,
71 struct probe_trace_event *tev, struct map *map) 72 struct probe_trace_event *tev, struct map *map,
73 struct symbol *sym)
72{ 74{
75 int lep_offset;
76
73 /* 77 /*
74 * When probing at a function entry point, we normally always want the 78 * When probing at a function entry point, we normally always want the
75 * LEP since that catches calls to the function through both the GEP and 79 * LEP since that catches calls to the function through both the GEP and
@@ -82,10 +86,18 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
82 * 86 *
83 * In addition, we shouldn't specify an offset for kretprobes. 87 * In addition, we shouldn't specify an offset for kretprobes.
84 */ 88 */
85 if (pev->point.offset || pev->point.retprobe || !map) 89 if (pev->point.offset || pev->point.retprobe || !map || !sym)
86 return; 90 return;
87 91
92 lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym);
93
88 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) 94 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS)
89 tev->point.offset += PPC64LE_LEP_OFFSET; 95 tev->point.offset += PPC64LE_LEP_OFFSET;
96 else if (lep_offset) {
97 if (pev->uprobes)
98 tev->point.address += lep_offset;
99 else
100 tev->point.offset += lep_offset;
101 }
90} 102}
91#endif 103#endif
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 85d82f4dc5e9..c82c625395ab 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2477,7 +2477,8 @@ static int find_probe_functions(struct map *map, char *name,
2477 2477
2478void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused, 2478void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
2479 struct probe_trace_event *tev __maybe_unused, 2479 struct probe_trace_event *tev __maybe_unused,
2480 struct map *map __maybe_unused) { } 2480 struct map *map __maybe_unused,
2481 struct symbol *sym __maybe_unused) { }
2481 2482
2482/* 2483/*
2483 * Find probe function addresses from map. 2484 * Find probe function addresses from map.
@@ -2614,7 +2615,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2614 strdup_or_goto(pev->args[i].type, 2615 strdup_or_goto(pev->args[i].type,
2615 nomem_out); 2616 nomem_out);
2616 } 2617 }
2617 arch__fix_tev_from_maps(pev, tev, map); 2618 arch__fix_tev_from_maps(pev, tev, map, sym);
2618 } 2619 }
2619 if (ret == skipped) { 2620 if (ret == skipped) {
2620 ret = -ENOENT; 2621 ret = -ENOENT;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e2209623f981..5a27eb4fad05 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -154,7 +154,8 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
154int show_available_funcs(const char *module, struct strfilter *filter, bool user); 154int show_available_funcs(const char *module, struct strfilter *filter, bool user);
155bool arch__prefers_symtab(void); 155bool arch__prefers_symtab(void);
156void arch__fix_tev_from_maps(struct perf_probe_event *pev, 156void arch__fix_tev_from_maps(struct perf_probe_event *pev,
157 struct probe_trace_event *tev, struct map *map); 157 struct probe_trace_event *tev, struct map *map,
158 struct symbol *sym);
158 159
159/* If there is no space to write, returns -E2BIG. */ 160/* If there is no space to write, returns -E2BIG. */
160int e_snprintf(char *str, size_t size, const char *format, ...) 161int e_snprintf(char *str, size_t size, const char *format, ...)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 3f9d6798bd18..87a297dd8901 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -770,7 +770,8 @@ static bool want_demangle(bool is_kernel_sym)
770 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle; 770 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
771} 771}
772 772
773void __weak arch__elf_sym_adjust(GElf_Sym *sym __maybe_unused) { } 773void __weak arch__sym_update(struct symbol *s __maybe_unused,
774 GElf_Sym *sym __maybe_unused) { }
774 775
775int dso__load_sym(struct dso *dso, struct map *map, 776int dso__load_sym(struct dso *dso, struct map *map,
776 struct symsrc *syms_ss, struct symsrc *runtime_ss, 777 struct symsrc *syms_ss, struct symsrc *runtime_ss,
@@ -947,8 +948,6 @@ int dso__load_sym(struct dso *dso, struct map *map,
947 (sym.st_value & 1)) 948 (sym.st_value & 1))
948 --sym.st_value; 949 --sym.st_value;
949 950
950 arch__elf_sym_adjust(&sym);
951
952 if (dso->kernel || kmodule) { 951 if (dso->kernel || kmodule) {
953 char dso_name[PATH_MAX]; 952 char dso_name[PATH_MAX];
954 953
@@ -1082,6 +1081,8 @@ new_symbol:
1082 if (!f) 1081 if (!f)
1083 goto out_elf_end; 1082 goto out_elf_end;
1084 1083
1084 arch__sym_update(f, &sym);
1085
1085 if (filter && filter(curr_map, f)) 1086 if (filter && filter(curr_map, f))
1086 symbol__delete(f); 1087 symbol__delete(f);
1087 else { 1088 else {
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index c8e43979ed5c..07211c2f8456 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -55,6 +55,7 @@ struct symbol {
55 u16 namelen; 55 u16 namelen;
56 u8 binding; 56 u8 binding;
57 bool ignore; 57 bool ignore;
58 u8 arch_sym;
58 char name[0]; 59 char name[0];
59}; 60};
60 61
@@ -323,7 +324,7 @@ int setup_intlist(struct intlist **list, const char *list_str,
323 324
324#ifdef HAVE_LIBELF_SUPPORT 325#ifdef HAVE_LIBELF_SUPPORT
325bool elf__needs_adjust_symbols(GElf_Ehdr ehdr); 326bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
326void arch__elf_sym_adjust(GElf_Sym *sym); 327void arch__sym_update(struct symbol *s, GElf_Sym *sym);
327#endif 328#endif
328 329
329#define SYMBOL_A 0 330#define SYMBOL_A 0