diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-12-15 10:32:33 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-15 14:22:04 -0500 |
commit | a128168d1e79e537d6666655e7771d973e9230e3 (patch) | |
tree | 73f8581954751bd9927182e3ac984d925faefade /tools | |
parent | d761b08bff0a9b653f6bd248cea50322e7eccb14 (diff) |
perf probe: Check build-id of vmlinux
Check build-id of vmlinux by using functions in symbol.c.
This also exposes map__load() for getting vmlinux path,
and removes vmlinux path list in builtin-probe.c,
because symbol.c already has that. Checking build-id
prevents users to open old or different debuginfo from
current running kernel.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: K.Prasad <prasad@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: systemtap <systemtap@sources.redhat.com>
Cc: DLE <dle-develop@lists.sourceforge.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20091215153232.17436.45539.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-probe.c | 72 | ||||
-rw-r--r-- | tools/perf/util/event.h | 2 | ||||
-rw-r--r-- | tools/perf/util/map.c | 14 |
3 files changed, 41 insertions, 47 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 8b4fdaeefa29..0584b7a0ed36 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -38,33 +38,27 @@ | |||
38 | #include "util/strlist.h" | 38 | #include "util/strlist.h" |
39 | #include "util/event.h" | 39 | #include "util/event.h" |
40 | #include "util/debug.h" | 40 | #include "util/debug.h" |
41 | #include "util/symbol.h" | ||
42 | #include "util/thread.h" | ||
43 | #include "util/session.h" | ||
41 | #include "util/parse-options.h" | 44 | #include "util/parse-options.h" |
42 | #include "util/parse-events.h" /* For debugfs_path */ | 45 | #include "util/parse-events.h" /* For debugfs_path */ |
43 | #include "util/probe-finder.h" | 46 | #include "util/probe-finder.h" |
44 | #include "util/probe-event.h" | 47 | #include "util/probe-event.h" |
45 | 48 | ||
46 | /* Default vmlinux search paths */ | ||
47 | #define NR_SEARCH_PATH 4 | ||
48 | const char *default_search_path[NR_SEARCH_PATH] = { | ||
49 | "/lib/modules/%s/build/vmlinux", /* Custom build kernel */ | ||
50 | "/usr/lib/debug/lib/modules/%s/vmlinux", /* Red Hat debuginfo */ | ||
51 | "/boot/vmlinux-debug-%s", /* Ubuntu */ | ||
52 | "./vmlinux", /* CWD */ | ||
53 | }; | ||
54 | |||
55 | #define MAX_PATH_LEN 256 | 49 | #define MAX_PATH_LEN 256 |
56 | #define MAX_PROBES 128 | 50 | #define MAX_PROBES 128 |
57 | 51 | ||
58 | /* Session management structure */ | 52 | /* Session management structure */ |
59 | static struct { | 53 | static struct { |
60 | char *vmlinux; | ||
61 | char *release; | ||
62 | bool need_dwarf; | 54 | bool need_dwarf; |
63 | bool list_events; | 55 | bool list_events; |
64 | bool force_add; | 56 | bool force_add; |
65 | int nr_probe; | 57 | int nr_probe; |
66 | struct probe_point probes[MAX_PROBES]; | 58 | struct probe_point probes[MAX_PROBES]; |
67 | struct strlist *dellist; | 59 | struct strlist *dellist; |
60 | struct symbol_conf conf; | ||
61 | struct perf_session *psession; | ||
68 | } session; | 62 | } session; |
69 | 63 | ||
70 | 64 | ||
@@ -122,33 +116,21 @@ static int opt_del_probe_event(const struct option *opt __used, | |||
122 | } | 116 | } |
123 | 117 | ||
124 | #ifndef NO_LIBDWARF | 118 | #ifndef NO_LIBDWARF |
125 | static int open_default_vmlinux(void) | 119 | static int open_vmlinux(void) |
126 | { | 120 | { |
127 | struct utsname uts; | 121 | struct map *kmap; |
128 | char fname[MAX_PATH_LEN]; | 122 | kmap = map_groups__find_by_name(&session.psession->kmaps, |
129 | int fd, ret, i; | 123 | MAP__FUNCTION, "[kernel.kallsyms]"); |
130 | 124 | if (!kmap) { | |
131 | ret = uname(&uts); | 125 | pr_debug("Could not find kernel map.\n"); |
132 | if (ret) { | 126 | return -ENOENT; |
133 | pr_debug("uname() failed.\n"); | ||
134 | return -errno; | ||
135 | } | 127 | } |
136 | session.release = uts.release; | 128 | if (map__load(kmap, session.psession, NULL) < 0) { |
137 | for (i = 0; i < NR_SEARCH_PATH; i++) { | 129 | pr_debug("Failed to load kernel map.\n"); |
138 | ret = snprintf(fname, MAX_PATH_LEN, | 130 | return -EINVAL; |
139 | default_search_path[i], session.release); | ||
140 | if (ret >= MAX_PATH_LEN || ret < 0) { | ||
141 | pr_debug("Filename(%d,%s) is too long.\n", i, | ||
142 | uts.release); | ||
143 | errno = E2BIG; | ||
144 | return -E2BIG; | ||
145 | } | ||
146 | pr_debug("try to open %s\n", fname); | ||
147 | fd = open(fname, O_RDONLY); | ||
148 | if (fd >= 0) | ||
149 | break; | ||
150 | } | 131 | } |
151 | return fd; | 132 | pr_debug("Try to open %s\n", kmap->dso->long_name); |
133 | return open(kmap->dso->long_name, O_RDONLY); | ||
152 | } | 134 | } |
153 | #endif | 135 | #endif |
154 | 136 | ||
@@ -164,8 +146,8 @@ static const struct option options[] = { | |||
164 | OPT_BOOLEAN('v', "verbose", &verbose, | 146 | OPT_BOOLEAN('v', "verbose", &verbose, |
165 | "be more verbose (show parsed arguments, etc)"), | 147 | "be more verbose (show parsed arguments, etc)"), |
166 | #ifndef NO_LIBDWARF | 148 | #ifndef NO_LIBDWARF |
167 | OPT_STRING('k', "vmlinux", &session.vmlinux, "file", | 149 | OPT_STRING('k', "vmlinux", &session.conf.vmlinux_name, |
168 | "vmlinux/module pathname"), | 150 | "file", "vmlinux pathname"), |
169 | #endif | 151 | #endif |
170 | OPT_BOOLEAN('l', "list", &session.list_events, | 152 | OPT_BOOLEAN('l', "list", &session.list_events, |
171 | "list up current probe events"), | 153 | "list up current probe events"), |
@@ -236,17 +218,23 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
236 | return 0; | 218 | return 0; |
237 | } | 219 | } |
238 | 220 | ||
221 | /* Initialize symbol maps for vmlinux */ | ||
222 | if (session.conf.vmlinux_name == NULL) | ||
223 | session.conf.try_vmlinux_path = true; | ||
224 | if (symbol__init(&session.conf) < 0) | ||
225 | die("Failed to init symbol map."); | ||
226 | session.psession = perf_session__new(NULL, O_WRONLY, false, | ||
227 | &session.conf); | ||
228 | if (session.psession == NULL) | ||
229 | die("Failed to init perf_session."); | ||
230 | |||
239 | if (session.need_dwarf) | 231 | if (session.need_dwarf) |
240 | #ifdef NO_LIBDWARF | 232 | #ifdef NO_LIBDWARF |
241 | die("Debuginfo-analysis is not supported"); | 233 | die("Debuginfo-analysis is not supported"); |
242 | #else /* !NO_LIBDWARF */ | 234 | #else /* !NO_LIBDWARF */ |
243 | pr_debug("Some probes require debuginfo.\n"); | 235 | pr_debug("Some probes require debuginfo.\n"); |
244 | 236 | ||
245 | if (session.vmlinux) { | 237 | fd = open_vmlinux(); |
246 | pr_debug("Try to open %s.", session.vmlinux); | ||
247 | fd = open(session.vmlinux, O_RDONLY); | ||
248 | } else | ||
249 | fd = open_default_vmlinux(); | ||
250 | if (fd < 0) { | 238 | if (fd < 0) { |
251 | if (session.need_dwarf) | 239 | if (session.need_dwarf) |
252 | die("Could not open debuginfo file."); | 240 | die("Could not open debuginfo file."); |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index a92e0b039a6a..8027309b0422 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -152,6 +152,8 @@ size_t map__fprintf(struct map *self, FILE *fp); | |||
152 | 152 | ||
153 | struct perf_session; | 153 | struct perf_session; |
154 | 154 | ||
155 | int map__load(struct map *self, struct perf_session *session, | ||
156 | symbol_filter_t filter); | ||
155 | struct symbol *map__find_symbol(struct map *self, struct perf_session *session, | 157 | struct symbol *map__find_symbol(struct map *self, struct perf_session *session, |
156 | u64 addr, symbol_filter_t filter); | 158 | u64 addr, symbol_filter_t filter); |
157 | struct symbol *map__find_symbol_by_name(struct map *self, const char *name, | 159 | struct symbol *map__find_symbol_by_name(struct map *self, const char *name, |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 8b3dd467adb5..c4d55a0da2ea 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -104,12 +104,16 @@ void map__fixup_end(struct map *self) | |||
104 | 104 | ||
105 | #define DSO__DELETED "(deleted)" | 105 | #define DSO__DELETED "(deleted)" |
106 | 106 | ||
107 | static int map__load(struct map *self, struct perf_session *session, | 107 | int map__load(struct map *self, struct perf_session *session, |
108 | symbol_filter_t filter) | 108 | symbol_filter_t filter) |
109 | { | 109 | { |
110 | const char *name = self->dso->long_name; | 110 | const char *name = self->dso->long_name; |
111 | int nr = dso__load(self->dso, self, session, filter); | 111 | int nr; |
112 | 112 | ||
113 | if (dso__loaded(self->dso, self->type)) | ||
114 | return 0; | ||
115 | |||
116 | nr = dso__load(self->dso, self, session, filter); | ||
113 | if (nr < 0) { | 117 | if (nr < 0) { |
114 | if (self->dso->has_build_id) { | 118 | if (self->dso->has_build_id) { |
115 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | 119 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; |
@@ -147,7 +151,7 @@ static int map__load(struct map *self, struct perf_session *session, | |||
147 | struct symbol *map__find_symbol(struct map *self, struct perf_session *session, | 151 | struct symbol *map__find_symbol(struct map *self, struct perf_session *session, |
148 | u64 addr, symbol_filter_t filter) | 152 | u64 addr, symbol_filter_t filter) |
149 | { | 153 | { |
150 | if (!dso__loaded(self->dso, self->type) && map__load(self, session, filter) < 0) | 154 | if (map__load(self, session, filter) < 0) |
151 | return NULL; | 155 | return NULL; |
152 | 156 | ||
153 | return dso__find_symbol(self->dso, self->type, addr); | 157 | return dso__find_symbol(self->dso, self->type, addr); |
@@ -157,7 +161,7 @@ struct symbol *map__find_symbol_by_name(struct map *self, const char *name, | |||
157 | struct perf_session *session, | 161 | struct perf_session *session, |
158 | symbol_filter_t filter) | 162 | symbol_filter_t filter) |
159 | { | 163 | { |
160 | if (!dso__loaded(self->dso, self->type) && map__load(self, session, filter) < 0) | 164 | if (map__load(self, session, filter) < 0) |
161 | return NULL; | 165 | return NULL; |
162 | 166 | ||
163 | if (!dso__sorted_by_name(self->dso, self->type)) | 167 | if (!dso__sorted_by_name(self->dso, self->type)) |