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>
This commit is contained in:
parent
b6f4c66704
commit
1f2ed153b9
|
@ -267,21 +267,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE:
|
|
||||||
* '.gnu.linkonce.this_module' section of kernel module elf directly
|
|
||||||
* maps to 'struct module' from linux/module.h. This section contains
|
|
||||||
* actual module name which will be used by kernel after loading it.
|
|
||||||
* But, we cannot use 'struct module' here since linux/module.h is not
|
|
||||||
* exposed to user-space. Offset of 'name' has remained same from long
|
|
||||||
* time, so hardcoding it here.
|
|
||||||
*/
|
|
||||||
#ifdef __LP64__
|
|
||||||
#define MOD_NAME_OFFSET 24
|
|
||||||
#else
|
|
||||||
#define MOD_NAME_OFFSET 12
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @module can be module name of module file path. In case of path,
|
* @module can be module name of module file path. In case of path,
|
||||||
* inspect elf and find out what is actual module name.
|
* inspect elf and find out what is actual module name.
|
||||||
|
@ -296,6 +281,7 @@ static char *find_module_name(const char *module)
|
||||||
Elf_Data *data;
|
Elf_Data *data;
|
||||||
Elf_Scn *sec;
|
Elf_Scn *sec;
|
||||||
char *mod_name = NULL;
|
char *mod_name = NULL;
|
||||||
|
int name_offset;
|
||||||
|
|
||||||
fd = open(module, O_RDONLY);
|
fd = open(module, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
@ -317,7 +303,21 @@ static char *find_module_name(const char *module)
|
||||||
if (!data || !data->d_buf)
|
if (!data || !data->d_buf)
|
||||||
goto ret_err;
|
goto ret_err;
|
||||||
|
|
||||||
mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET);
|
/*
|
||||||
|
* NOTE:
|
||||||
|
* '.gnu.linkonce.this_module' section of kernel module elf directly
|
||||||
|
* maps to 'struct module' from linux/module.h. This section contains
|
||||||
|
* actual module name which will be used by kernel after loading it.
|
||||||
|
* But, we cannot use 'struct module' here since linux/module.h is not
|
||||||
|
* exposed to user-space. Offset of 'name' has remained same from long
|
||||||
|
* time, so hardcoding it here.
|
||||||
|
*/
|
||||||
|
if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
|
||||||
|
name_offset = 12;
|
||||||
|
else /* expect ELFCLASS64 by default */
|
||||||
|
name_offset = 24;
|
||||||
|
|
||||||
|
mod_name = strdup((char *)data->d_buf + name_offset);
|
||||||
|
|
||||||
ret_err:
|
ret_err:
|
||||||
elf_end(elf);
|
elf_end(elf);
|
||||||
|
|
Loading…
Reference in a new issue