Commit 564c62a4 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

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: default avatarNamhyung 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 18bd7264
...@@ -2193,18 +2193,20 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, ...@@ -2193,18 +2193,20 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
return ret; return ret;
} }
static char *looking_function_name; static int find_probe_functions(struct map *map, char *name)
static int num_matched_functions;
static int probe_function_filter(struct map *map __maybe_unused,
struct symbol *sym)
{ {
if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && int found = 0;
strcmp(looking_function_name, sym->name) == 0) { struct symbol *sym = map__find_symbol_by_name(map, name, NULL);
num_matched_functions++;
return 0; while (sym != NULL) {
if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL)
found++;
sym = symbol__next_by_name(sym);
if (sym == NULL || strcmp(sym->name, name))
break;
} }
return 1;
return found;
} }
#define strdup_or_goto(str, label) \ #define strdup_or_goto(str, label) \
...@@ -2222,10 +2224,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, ...@@ -2222,10 +2224,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
struct kmap *kmap = NULL; struct kmap *kmap = NULL;
struct ref_reloc_sym *reloc_sym = NULL; struct ref_reloc_sym *reloc_sym = NULL;
struct symbol *sym; struct symbol *sym;
struct rb_node *nd;
struct probe_trace_event *tev; struct probe_trace_event *tev;
struct perf_probe_point *pp = &pev->point; struct perf_probe_point *pp = &pev->point;
struct probe_trace_point *tp; struct probe_trace_point *tp;
int num_matched_functions;
int ret, i; int ret, i;
/* Init maps of given executable or kernel */ /* 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,10 +2244,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
* Load matched symbols: Since the different local symbols may have * Load matched symbols: Since the different local symbols may have
* same name but different addresses, this lists all the symbols. * same name but different addresses, this lists all the symbols.
*/ */
num_matched_functions = 0; num_matched_functions = find_probe_functions(map, pp->function);
looking_function_name = pp->function; if (num_matched_functions == 0) {
ret = map__load(map, probe_function_filter);
if (ret || num_matched_functions == 0) {
pr_err("Failed to find symbol %s in %s\n", pp->function, pr_err("Failed to find symbol %s in %s\n", pp->function,
target ? : "kernel"); target ? : "kernel");
ret = -ENOENT; ret = -ENOENT;
...@@ -2275,7 +2275,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, ...@@ -2275,7 +2275,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
} }
ret = 0; ret = 0;
map__for_each_symbol(map, sym, nd) { sym = map__find_symbol_by_name(map, pp->function, NULL);
while (sym != NULL) {
tev = (*tevs) + ret; tev = (*tevs) + ret;
tp = &tev->point; tp = &tev->point;
if (ret == num_matched_functions) { if (ret == num_matched_functions) {
...@@ -2323,6 +2325,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, ...@@ -2323,6 +2325,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
strdup_or_goto(pev->args[i].type, strdup_or_goto(pev->args[i].type,
nomem_out); nomem_out);
} }
sym = symbol__next_by_name(sym);
if (sym == NULL || strcmp(sym->name, pp->function))
break;
} }
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment