perf-probe: Fix to get correct modname from elf header
PATCH 1/1 perf-probe: Fix to get correct modname from elf header
Since perf-probe supports cross-arch probe, it is possible to analyze different arch kernel image which has different bits-per-long. In that case, it fails to get module name because perf probe uses MOD_NAME_OFFSET macro based on host machines bits-per-long, instead of the target archs bits-per-long.
This fixes above issue by changing modname-offset based on the target archs bitwidth. 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 -----
--- tools/perf/util/probe-event.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
tools/perf/util/probe-event.c +16 -16
@@ -268,21 +268,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address) }/* -* 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, * inspect elf and find out what is actual module name. * Caller has to free mod_name after using it.
@@ -296,6 +281,7 @@ static char *find_module_name(const char *module)Elf_Data *data;Elf_Scn *sec;char *mod_name =NULL ; +int name_offset; fd =open (module,O_RDONLY );if (fd <0 )
@@ -317,7 +303,21 @@ static char *find_module_name(const char *module)if (!data || !data->d_buf) 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:elf_end (elf);
Arnaldo Carvalho de Melo
maintainerEm Tue, Jan 03, 2017 at 12:20:49AM +0900, Masami Hiramatsu escreveu:
Quoted 10 lines
Since perf-probe supports cross-arch probe, it is possible to analyze different arch kernel image which has different bits-per-long. In that case, it fails to get module name because perf probe uses
MOD_NAME_OFFSETmacro based on host machines bits-per-long, instead of the target archs bits-per-long.This fixes above issue by changing modname-offset based on the target archs bitwidth. This is ok because linux kernel uses LP64 model on 64bit arch.
Seems simple enough, thanks, applied.
- Arnaldo
tip-bot for Masami Hiramatsu
merge bot[tip:perf/urgent] perf probe: Fix to get correct modname from elf header
In reply to Masami Hiramatsuperf probe: Fix to get correct modname from elf header
Commit-ID: 1f2ed153b916c95a49a1ca9d7107738664224b7f Gitweb: http://git.kernel.org/tip/1f2ed153b916c95a49a1ca9d7107738664224b7f Author: Masami Hiramatsu <[email protected]> AuthorDate: Tue, 3 Jan 2017 00:20:49 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 2 Jan 2017 14:09:17 -0300
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
--- tools/perf/util/probe-event.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
tools/perf/util/probe-event.c +16 -16
@@ -268,21 +268,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address) }/* -* 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, * inspect elf and find out what is actual module name. * Caller has to free mod_name after using it.
@@ -296,6 +281,7 @@ static char *find_module_name(const char *module)Elf_Data *data;Elf_Scn *sec;char *mod_name =NULL ; +int name_offset; fd =open (module,O_RDONLY );if (fd <0 )
@@ -317,7 +303,21 @@ static char *find_module_name(const char *module)if (!data || !data->d_buf) 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:elf_end (elf);