aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@kernel.org>2017-01-02 10:20:49 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-01-02 12:09:17 -0500
commit1f2ed153b916c95a49a1ca9d7107738664224b7f (patch)
treece166577010cd469d79483384a42ab746e19c71f /tools/perf
parentb6f4c66704b875aba9b8c912532323e3cc89824c (diff)
perf probe: Fix to get correct modname from elf header
Since 'perf probe' supports cross-arch probes, it is possible to analyze different arch kernel image which has different bits-per-long. In that case, it fails to get the module name because it uses the MOD_NAME_OFFSET macro based on the host machine bits-per-long, instead of the target arch bits-per-long. This fixes above issue by changing modname-offset based on the target archs bit width. This is ok because linux kernel uses LP64 model on 64bit arch. E.g. without this (on x86_64, and target module is arm32): $ perf probe -m build-arm/fs/configfs/configfs.ko -D configfs_lookup p:probe/configfs_lookup :configfs_lookup+0 ^-Here is an empty module name. With this fix, you can see correct module name: $ perf probe -m build-arm/fs/configfs/configfs.ko -D configfs_lookup p:probe/configfs_lookup configfs:configfs_lookup+0 Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/148337043836.6752.383495516397005695.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/probe-event.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d281ae2b54e8..8f810961ec78 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -268,21 +268,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
268} 268}
269 269
270/* 270/*
271 * NOTE:
272 * '.gnu.linkonce.this_module' section of kernel module elf directly
273 * maps to 'struct module' from linux/module.h. This section contains
274 * actual module name which will be used by kernel after loading it.
275 * But, we cannot use 'struct module' here since linux/module.h is not
276 * exposed to user-space. Offset of 'name' has remained same from long
277 * time, so hardcoding it here.
278 */
279#ifdef __LP64__
280#define MOD_NAME_OFFSET 24
281#else
282#define MOD_NAME_OFFSET 12
283#endif
284
285/*
286 * @module can be module name of module file path. In case of path, 271 * @module can be module name of module file path. In case of path,
287 * inspect elf and find out what is actual module name. 272 * inspect elf and find out what is actual module name.
288 * Caller has to free mod_name after using it. 273 * Caller has to free mod_name after using it.
@@ -296,6 +281,7 @@ static char *find_module_name(const char *module)
296 Elf_Data *data; 281 Elf_Data *data;
297 Elf_Scn *sec; 282 Elf_Scn *sec;
298 char *mod_name = NULL; 283 char *mod_name = NULL;
284 int name_offset;
299 285
300 fd = open(module, O_RDONLY); 286 fd = open(module, O_RDONLY);
301 if (fd < 0) 287 if (fd < 0)
@@ -317,7 +303,21 @@ static char *find_module_name(const char *module)
317 if (!data || !data->d_buf) 303 if (!data || !data->d_buf)
318 goto ret_err; 304 goto ret_err;
319 305
320 mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET); 306 /*
307 * NOTE:
308 * '.gnu.linkonce.this_module' section of kernel module elf directly
309 * maps to 'struct module' from linux/module.h. This section contains
310 * actual module name which will be used by kernel after loading it.
311 * But, we cannot use 'struct module' here since linux/module.h is not
312 * exposed to user-space. Offset of 'name' has remained same from long
313 * time, so hardcoding it here.
314 */
315 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
316 name_offset = 12;
317 else /* expect ELFCLASS64 by default */
318 name_offset = 24;
319
320 mod_name = strdup((char *)data->d_buf + name_offset);
321 321
322ret_err: 322ret_err:
323 elf_end(elf); 323 elf_end(elf);