[prev in list] [next in list] [prev in thread] [next in thread] 

List:       git-commits-head
Subject:    perf probe: Do not rely on map__load() filter to find symbols
From:       "Linux Kernel Mailing List" <linux-kernel () vger ! kernel ! org>
Date:       2015-01-31 0:38:00
Message-ID: 20150131003800.69622660D97 () gitolite ! kernel ! org
[Download RAW message or body]

Gitweb:     http://git.kernel.org/linus/;a=commit;h=564c62a4d7f9a4b60920ee0b02cfe890471d87f4
Commit:     564c62a4d7f9a4b60920ee0b02cfe890471d87f4
Parent:     18bd726418f2a2e12f85104f0f4b5d5d077e1752
Refname:    refs/heads/master
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Wed Jan 14 20:18:07 2015 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed Jan 21 10:06:02 2015 -0300

    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>
---
 tools/perf/util/probe-event.c | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 94a717b..b24482e 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,
 	return ret;
 }
 
-static char *looking_function_name;
-static int num_matched_functions;
-
-static int probe_function_filter(struct map *map __maybe_unused,
-				      struct symbol *sym)
+static int find_probe_functions(struct map *map, char *name)
 {
-	if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
-	    strcmp(looking_function_name, sym->name) == 0) {
-		num_matched_functions++;
-		return 0;
+	int found = 0;
+	struct symbol *sym = map__find_symbol_by_name(map, name, NULL);
+
+	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)	\
@@ -2222,10 +2224,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
 	struct kmap *kmap = NULL;
 	struct ref_reloc_sym *reloc_sym = NULL;
 	struct symbol *sym;
-	struct rb_node *nd;
 	struct probe_trace_event *tev;
 	struct perf_probe_point *pp = &pev->point;
 	struct probe_trace_point *tp;
+	int num_matched_functions;
 	int ret, i;
 
 	/* Init maps of given executable or kernel */
@@ -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
 	 * same name but different addresses, this lists all the symbols.
 	 */
-	num_matched_functions = 0;
-	looking_function_name = pp->function;
-	ret = map__load(map, probe_function_filter);
-	if (ret || num_matched_functions == 0) {
+	num_matched_functions = find_probe_functions(map, pp->function);
+	if (num_matched_functions == 0) {
 		pr_err("Failed to find symbol %s in %s\n", pp->function,
 			target ? : "kernel");
 		ret = -ENOENT;
@@ -2275,7 +2275,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
 	}
 
 	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;
 		tp = &tev->point;
 		if (ret == num_matched_functions) {
@@ -2323,6 +2325,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
 					strdup_or_goto(pev->args[i].type,
 							nomem_out);
 		}
+
+		sym = symbol__next_by_name(sym);
+		if (sym == NULL || strcmp(sym->name, pp->function))
+			break;
 	}
 
 out:
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic