diff options
author | Masami Hiramatsu <mhiramat@kernel.org> | 2017-12-08 11:28:12 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-12-27 10:15:54 -0500 |
commit | 4b3a2716dd785fabb9f6ac80c1d53cb29a88169d (patch) | |
tree | 82c60e830f99a86a779031834e68ff2e915f6b61 | |
parent | e63c625a1e417edbe513b75b347a7238e9e7fea0 (diff) |
perf probe: Find versioned symbols from map
Commit d80406453ad4 ("perf symbols: Allow user probes on versioned
symbols") allows user to find default versioned symbols (with "@@") in
map. However, it did not enable normal versioned symbol (with "@") for
perf-probe. E.g.
=====
# ./perf probe -x /lib64/libc-2.25.so malloc_get_state
Failed to find symbol malloc_get_state in /usr/lib64/libc-2.25.so
Error: Failed to add events.
=====
This solves above issue by improving perf-probe symbol search function,
as below.
=====
# ./perf probe -x /lib64/libc-2.25.so malloc_get_state
Added new event:
probe_libc:malloc_get_state (on malloc_get_state in /usr/lib64/libc-2.25.so)
You can now use it in all perf tools, such as:
perf record -e probe_libc:malloc_get_state -aR sleep 1
# ./perf probe -l
probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so)
=====
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Acked-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Clarke <pc@us.ibm.com>
Cc: bhargavb <bhargavaramudu@gmail.com>
Cc: linux-rt-users@vger.kernel.org
Link: http://lkml.kernel.org/r/151275049269.24652.1639103455496216255.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/arch/powerpc/util/sym-handling.c | 8 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 20 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 5 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 |
4 files changed, 32 insertions, 2 deletions
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c index 9c4e23d8c8ce..53d83d7e6a09 100644 --- a/tools/perf/arch/powerpc/util/sym-handling.c +++ b/tools/perf/arch/powerpc/util/sym-handling.c | |||
@@ -64,6 +64,14 @@ int arch__compare_symbol_names_n(const char *namea, const char *nameb, | |||
64 | 64 | ||
65 | return strncmp(namea, nameb, n); | 65 | return strncmp(namea, nameb, n); |
66 | } | 66 | } |
67 | |||
68 | const char *arch__normalize_symbol_name(const char *name) | ||
69 | { | ||
70 | /* Skip over initial dot */ | ||
71 | if (name && *name == '.') | ||
72 | name++; | ||
73 | return name; | ||
74 | } | ||
67 | #endif | 75 | #endif |
68 | 76 | ||
69 | #if defined(_CALL_ELF) && _CALL_ELF == 2 | 77 | #if defined(_CALL_ELF) && _CALL_ELF == 2 |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index a68141d360b0..0d6c66d51939 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -2801,16 +2801,32 @@ static int find_probe_functions(struct map *map, char *name, | |||
2801 | int found = 0; | 2801 | int found = 0; |
2802 | struct symbol *sym; | 2802 | struct symbol *sym; |
2803 | struct rb_node *tmp; | 2803 | struct rb_node *tmp; |
2804 | const char *norm, *ver; | ||
2805 | char *buf = NULL; | ||
2804 | 2806 | ||
2805 | if (map__load(map) < 0) | 2807 | if (map__load(map) < 0) |
2806 | return 0; | 2808 | return 0; |
2807 | 2809 | ||
2808 | map__for_each_symbol(map, sym, tmp) { | 2810 | map__for_each_symbol(map, sym, tmp) { |
2809 | if (strglobmatch(sym->name, name)) { | 2811 | norm = arch__normalize_symbol_name(sym->name); |
2812 | if (!norm) | ||
2813 | continue; | ||
2814 | |||
2815 | /* We don't care about default symbol or not */ | ||
2816 | ver = strchr(norm, '@'); | ||
2817 | if (ver) { | ||
2818 | buf = strndup(norm, ver - norm); | ||
2819 | if (!buf) | ||
2820 | return -ENOMEM; | ||
2821 | norm = buf; | ||
2822 | } | ||
2823 | if (strglobmatch(norm, name)) { | ||
2810 | found++; | 2824 | found++; |
2811 | if (syms && found < probe_conf.max_probes) | 2825 | if (syms && found < probe_conf.max_probes) |
2812 | syms[found - 1] = sym; | 2826 | syms[found - 1] = sym; |
2813 | } | 2827 | } |
2828 | if (buf) | ||
2829 | zfree(&buf); | ||
2814 | } | 2830 | } |
2815 | 2831 | ||
2816 | return found; | 2832 | return found; |
@@ -2856,7 +2872,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
2856 | * same name but different addresses, this lists all the symbols. | 2872 | * same name but different addresses, this lists all the symbols. |
2857 | */ | 2873 | */ |
2858 | num_matched_functions = find_probe_functions(map, pp->function, syms); | 2874 | num_matched_functions = find_probe_functions(map, pp->function, syms); |
2859 | if (num_matched_functions == 0) { | 2875 | if (num_matched_functions <= 0) { |
2860 | pr_err("Failed to find symbol %s in %s\n", pp->function, | 2876 | pr_err("Failed to find symbol %s in %s\n", pp->function, |
2861 | pev->target ? : "kernel"); | 2877 | pev->target ? : "kernel"); |
2862 | ret = -ENOENT; | 2878 | ret = -ENOENT; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 1b67a8639dfe..cc065d4bfafc 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -94,6 +94,11 @@ static int prefix_underscores_count(const char *str) | |||
94 | return tail - str; | 94 | return tail - str; |
95 | } | 95 | } |
96 | 96 | ||
97 | const char * __weak arch__normalize_symbol_name(const char *name) | ||
98 | { | ||
99 | return name; | ||
100 | } | ||
101 | |||
97 | int __weak arch__compare_symbol_names(const char *namea, const char *nameb) | 102 | int __weak arch__compare_symbol_names(const char *namea, const char *nameb) |
98 | { | 103 | { |
99 | return strcmp(namea, nameb); | 104 | return strcmp(namea, nameb); |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index a4f0075b4e5c..0563f33c1eb3 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -349,6 +349,7 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr); | |||
349 | void arch__sym_update(struct symbol *s, GElf_Sym *sym); | 349 | void arch__sym_update(struct symbol *s, GElf_Sym *sym); |
350 | #endif | 350 | #endif |
351 | 351 | ||
352 | const char *arch__normalize_symbol_name(const char *name); | ||
352 | #define SYMBOL_A 0 | 353 | #define SYMBOL_A 0 |
353 | #define SYMBOL_B 1 | 354 | #define SYMBOL_B 1 |
354 | 355 | ||