aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2015-01-14 06:18:07 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-01-21 08:06:02 -0500
commit564c62a4d7f9a4b60920ee0b02cfe890471d87f4 (patch)
treeb19e154acf61fcd58bf509b689db587aa09d491d /tools/perf
parent18bd726418f2a2e12f85104f0f4b5d5d077e1752 (diff)
perf probe: Do not rely on map__load() filter to find symbols
The find_probe_trace_events_from_map() searches matching symbol from a map (so from a backing dso). For uprobes, it'll create a new map (and dso) and loads it using a filter. It's a little bit inefficient in that it'll read out the symbol table everytime but works well anyway. For kprobes however, it'll reuse existing kernel map which might be loaded before. In this case map__load() just returns with no result. It makes kprobes always failed to find symbol even if it exists in the map (dso). To fix it, use map__find_symbol_by_name() instead. It'll load a map with full symbols and sorts them by name. It needs to search sibing nodes since there can be multiple (local) symbols with same name. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Link: http://lkml.kernel.org/r/1421234288-22758-3-git-send-email-namhyung@kernel.org [ Use symbol__next_by_name ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/probe-event.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 94a717bf007d..b24482e54451 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2193,18 +2193,20 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2193 return ret; 2193 return ret;
2194} 2194}
2195 2195
2196static char *looking_function_name; 2196static int find_probe_functions(struct map *map, char *name)
2197static int num_matched_functions;
2198
2199static int probe_function_filter(struct map *map __maybe_unused,
2200 struct symbol *sym)
2201{ 2197{
2202 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && 2198 int found = 0;
2203 strcmp(looking_function_name, sym->name) == 0) { 2199 struct symbol *sym = map__find_symbol_by_name(map, name, NULL);
2204 num_matched_functions++; 2200
2205 return 0; 2201 while (sym != NULL) {
2202 if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL)
2203 found++;
2204 sym = symbol__next_by_name(sym);
2205 if (sym == NULL || strcmp(sym->name, name))
2206 break;
2206 } 2207 }
2207 return 1; 2208
2209 return found;
2208} 2210}
2209 2211
2210#define strdup_or_goto(str, label) \ 2212#define strdup_or_goto(str, label) \
@@ -2222,10 +2224,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2222 struct kmap *kmap = NULL; 2224 struct kmap *kmap = NULL;
2223 struct ref_reloc_sym *reloc_sym = NULL; 2225 struct ref_reloc_sym *reloc_sym = NULL;
2224 struct symbol *sym; 2226 struct symbol *sym;
2225 struct rb_node *nd;
2226 struct probe_trace_event *tev; 2227 struct probe_trace_event *tev;
2227 struct perf_probe_point *pp = &pev->point; 2228 struct perf_probe_point *pp = &pev->point;
2228 struct probe_trace_point *tp; 2229 struct probe_trace_point *tp;
2230 int num_matched_functions;
2229 int ret, i; 2231 int ret, i;
2230 2232
2231 /* Init maps of given executable or kernel */ 2233 /* Init maps of given executable or kernel */
@@ -2242,10 +2244,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2242 * Load matched symbols: Since the different local symbols may have 2244 * Load matched symbols: Since the different local symbols may have
2243 * same name but different addresses, this lists all the symbols. 2245 * same name but different addresses, this lists all the symbols.
2244 */ 2246 */
2245 num_matched_functions = 0; 2247 num_matched_functions = find_probe_functions(map, pp->function);
2246 looking_function_name = pp->function; 2248 if (num_matched_functions == 0) {
2247 ret = map__load(map, probe_function_filter);
2248 if (ret || num_matched_functions == 0) {
2249 pr_err("Failed to find symbol %s in %s\n", pp->function, 2249 pr_err("Failed to find symbol %s in %s\n", pp->function,
2250 target ? : "kernel"); 2250 target ? : "kernel");
2251 ret = -ENOENT; 2251 ret = -ENOENT;
@@ -2275,7 +2275,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2275 } 2275 }
2276 2276
2277 ret = 0; 2277 ret = 0;
2278 map__for_each_symbol(map, sym, nd) { 2278 sym = map__find_symbol_by_name(map, pp->function, NULL);
2279
2280 while (sym != NULL) {
2279 tev = (*tevs) + ret; 2281 tev = (*tevs) + ret;
2280 tp = &tev->point; 2282 tp = &tev->point;
2281 if (ret == num_matched_functions) { 2283 if (ret == num_matched_functions) {
@@ -2323,6 +2325,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2323 strdup_or_goto(pev->args[i].type, 2325 strdup_or_goto(pev->args[i].type,
2324 nomem_out); 2326 nomem_out);
2325 } 2327 }
2328
2329 sym = symbol__next_by_name(sym);
2330 if (sym == NULL || strcmp(sym->name, pp->function))
2331 break;
2326 } 2332 }
2327 2333
2328out: 2334out: