perf-probe: Fix offline module and cross-arch support
cover perf-probe: Fix offline module and cross-arch support
Hello,
This series fixes some issues on offline module/cross-arch probe support. While I was debuging arm32 kernel with cross-arch perf-probe, I found several issues.
- perf-probe didn't show correct probe definition on gcc-generated symbols (on both of kernel and module).
- perf-probe didn't show available functions for offline module even if full path of the module was given.
This series fixes those issues.
---
Masami Hiramatsu (3):
perf-probe: Fix --funcs to show correct symbols for offline module
perf-probe: Fix to probe on gcc generated symbols for offline kernel
perf-probe: Fix to probe on gcc generated functions in modules
tools/perf/util/probe-event.c | 111 +++++++++++++++++++++++++++------------- tools/perf/util/probe-finder.c | 2 - tools/perf/util/probe-finder.h | 2 + 3 files changed, 79 insertions(+), 36 deletions(-)
--
Masami Hiramatsu (Linaro)
PATCH 1/3 perf-probe: Fix --funcs to show correct symbols for offline module
Fix --funcs (-F) option to show correct symbols for offline module. Since previous perf-probe uses machine__findnew_module_map() for offline module, even if user passes a module file (with full path) which is for other architecture, perf-probe always tries to load symbol map for current kernel module.
This fix uses dso__new_map() to load the map from given binary as same as a map for user applications.
--- tools/perf/util/probe-event.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-)
tools/perf/util/probe-event.c +6 -19
@@ -163,7 +163,7 @@ static struct map *kernel_get_module_map(const char *module)/* A file path -- this is an offline module */ if (module &&strchr (module,'/' )) -return machine__findnew_module_map (host_machine,0 , module); +return dso__new_map (module);if (!module) module ="kernel" ;
@@ -173,6 +173,7 @@ static struct map *kernel_get_module_map(const char *module)if (strncmp (pos->dso->short_name +1 , module, pos->dso->short_name_len -2 ) ==0 && module[pos->dso->short_name_len -2 ] =='\0' ) { +map__get (pos);return pos; } }
@@ -188,15 +189,6 @@ struct map *get_target_map(const char *target, bool user)return kernel_get_module_map (target); } -static void put_target_map (struct map *map,bool user) -{ -if (map && user) { -/* Only the user map needs to be released */ -map__put (map); - } -} - -static int convert_exec_to_group (const char *exec,char **result) {char *ptr1, *ptr2, *exec_copy;
@@ -412,7 +404,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, } out: -put_target_map (map, uprobes); +map__put (map);return ret; }
@@ -2869,7 +2861,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, } out: -put_target_map (map, pev->uprobes); +map__put (map);free (syms);return ret;
@@ -3362,10 +3354,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,return ret;/* Get a symbol map */ -if (user) - map =dso__new_map (target); -else - map =kernel_get_module_map (target); + map =get_target_map (target, user);if (!map) {pr_err ("Failed to get a map for %s\n" , (target) ? :"kernel" );return -EINVAL ;
@@ -3397,9 +3386,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter, } end: -if (user) { -map__put (map); - } +map__put (map);exit_probe_symbol_maps ();return ret;
tip-bot for Masami Hiramatsu
merge bot[tip:perf/urgent] perf probe: Fix --funcs to show correct symbols for offline module
perf probe: Fix --funcs to show correct symbols for offline module
Commit-ID: eebc509b20881b92d62e317b2c073e57c5f200f0 Gitweb: http://git.kernel.org/tip/eebc509b20881b92d62e317b2c073e57c5f200f0 Author: Masami Hiramatsu <[email protected]> AuthorDate: Wed, 4 Jan 2017 12:29:05 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 4 Jan 2017 11:15:09 -0300
perf probe: Fix --funcs to show correct symbols for offline module
Fix --funcs (-F) option to show correct symbols for offline module. Since previous perf-probe uses machine__findnew_module_map() for offline module, even if user passes a module file (with full path) which is for other architecture, perf-probe always tries to load symbol map for current kernel module.
This fix uses dso__new_map() to load the map from given binary as same as a map for user applications.
--- tools/perf/util/probe-event.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-)
tools/perf/util/probe-event.c +6 -19
@@ -163,7 +163,7 @@ static struct map *kernel_get_module_map(const char *module)/* A file path -- this is an offline module */ if (module &&strchr (module,'/' )) -return machine__findnew_module_map (host_machine,0 , module); +return dso__new_map (module);if (!module) module ="kernel" ;
@@ -173,6 +173,7 @@ static struct map *kernel_get_module_map(const char *module)if (strncmp (pos->dso->short_name +1 , module, pos->dso->short_name_len -2 ) ==0 && module[pos->dso->short_name_len -2 ] =='\0' ) { +map__get (pos);return pos; } }
@@ -188,15 +189,6 @@ struct map *get_target_map(const char *target, bool user)return kernel_get_module_map (target); } -static void put_target_map (struct map *map,bool user) -{ -if (map && user) { -/* Only the user map needs to be released */ -map__put (map); - } -} - -static int convert_exec_to_group (const char *exec,char **result) {char *ptr1, *ptr2, *exec_copy;
@@ -412,7 +404,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, } out: -put_target_map (map, uprobes); +map__put (map);return ret; }
@@ -2869,7 +2861,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, } out: -put_target_map (map, pev->uprobes); +map__put (map);free (syms);return ret;
@@ -3362,10 +3354,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,return ret;/* Get a symbol map */ -if (user) - map =dso__new_map (target); -else - map =kernel_get_module_map (target); + map =get_target_map (target, user);if (!map) {pr_err ("Failed to get a map for %s\n" , (target) ? :"kernel" );return -EINVAL ;
@@ -3397,9 +3386,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter, } end: -if (user) { -map__put (map); - } +map__put (map);exit_probe_symbol_maps ();return ret;
PATCH 2/3 perf-probe: Fix to probe on gcc generated symbols for offline kernel
In reply to Masami HiramatsuFix perf-probe to show probe definition on gcc generated symbols for offline kernel (including cross-arch kernel image).
Gcc sometimes optimizes functions and generate new symbols with suffixes such as ".constprop.N" or ".isra.N" etc. Since those symbol names are not recorded in DWARF, we have to find correct generated symbols from offline ELF binary to probe on it (kallsyms doesn't correct it).
For online kernel or uprobes we don't need it because those are rebased on _text, or a section relative address.
E.g. Without this;
-----
$ perf probe -k build-arm/vmlinux -F __slab_alloc* __slab_alloc.constprop.9 $ perf probe -k build-arm/vmlinux -D __slab_alloc p:probe/__slab_alloc __slab_alloc+0 ----- If you put above definition on target machine, it should fail because there is no __slab_alloc in kallsyms.
With this fix, perf probe shows correct probe definition on __slab_alloc.constprop.9.
-----
$ perf probe -k build-arm/vmlinux -D __slab_alloc p:probe/__slab_alloc __slab_alloc.constprop.9+0 -----
--- tools/perf/util/probe-event.c | 48 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-)
tools/perf/util/probe-event.c +47 -1
@@ -610,6 +610,51 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,return ret ? : -ENOENT ; } +/* +* Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions +* and generate new symbols with suffixes such as .constprop.N or .isra.N +* etc. Since those symbols are not recorded in DWARF, we have to find +* correct generated symbols from offline ELF binary. +* For online kernel or uprobes we don't need this because those are +* rebased on _text, or already a section relative address. +*/ +static int +post_process_offline_probe_trace_events (struct probe_trace_event *tevs, +int ntevs,const char *pathname) +{ +struct symbol *sym; +struct map *map; +unsigned long stext =0 ; +u64 addr; +int i; + +/* Prepare a map for offline binary */ + map =dso__new_map (pathname); +if (!map ||get_text_start_address (pathname, &stext) <0 ) { +pr_warning ("Failed to get ELF symbols for %s\n" , pathname); +return -EINVAL ; + } + +for (i =0 ; i < ntevs; i++) { + addr = tevs[i].point.address + tevs[i].point.offset - stext; + sym =map__find_symbol (map, addr); +if (!sym) +continue ; +if (!strcmp (sym->name, tevs[i].point.symbol)) +continue ; +/* If we have no realname, use symbol for it */ +if (!tevs[i].point.realname) + tevs[i].point.realname = tevs[i].point.symbol; +else +free (tevs[i].point.symbol); + tevs[i].point.symbol =strdup (sym->name); + tevs[i].point.offset = addr - sym->start; + } +map__put (map); + +return 0 ; +} +static int add_exec_to_probe_trace_events (struct probe_trace_event *tevs,int ntevs,const char *exec) {
@@ -671,7 +716,8 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,/* Skip post process if the target is an offline kernel */ if (symbol_conf.ignore_vmlinux_buildid) -return 0 ; +return post_process_offline_probe_trace_events (tevs, ntevs, + symbol_conf.vmlinux_name); reloc_sym =kernel_get_ref_reloc_sym ();if (!reloc_sym) {
tip-bot for Masami Hiramatsu
merge bot[tip:perf/urgent] perf probe: Fix to probe on gcc generated symbols for offline kernel
perf probe: Fix to probe on gcc generated symbols for offline kernel
Commit-ID: 8a937a25a7e3c19d5fb3f9d92f605cf5fda219d8 Gitweb: http://git.kernel.org/tip/8a937a25a7e3c19d5fb3f9d92f605cf5fda219d8 Author: Masami Hiramatsu <[email protected]> AuthorDate: Wed, 4 Jan 2017 12:30:19 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 4 Jan 2017 11:44:22 -0300
perf probe: Fix to probe on gcc generated symbols for offline kernel
Fix perf-probe to show probe definition on gcc generated symbols for offline kernel (including cross-arch kernel image).
gcc sometimes optimizes functions and generate new symbols with suffixes such as ".constprop.N" or ".isra.N" etc. Since those symbol names are not recorded in DWARF, we have to find correct generated symbols from offline ELF binary to probe on it (kallsyms doesn't correct it). For online kernel or uprobes we don't need it because those are rebased on _text, or a section relative address.
E.g. Without this:
$ perf probe -k build-arm/vmlinux -F __slab_alloc* __slab_alloc.constprop.9 $ perf probe -k build-arm/vmlinux -D __slab_alloc p:probe/__slab_alloc __slab_alloc+0
If you put above definition on target machine, it should fail because there is no __slab_alloc in kallsyms.
With this fix, perf probe shows correct probe definition on __slab_alloc.constprop.9:
$ perf probe -k build-arm/vmlinux -D __slab_alloc p:probe/__slab_alloc __slab_alloc.constprop.9+0
--- tools/perf/util/probe-event.c | 48 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-)
tools/perf/util/probe-event.c +47 -1
@@ -610,6 +610,51 @@ error:return ret ? : -ENOENT ; } +/* +* Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions +* and generate new symbols with suffixes such as .constprop.N or .isra.N +* etc. Since those symbols are not recorded in DWARF, we have to find +* correct generated symbols from offline ELF binary. +* For online kernel or uprobes we don't need this because those are +* rebased on _text, or already a section relative address. +*/ +static int +post_process_offline_probe_trace_events (struct probe_trace_event *tevs, +int ntevs,const char *pathname) +{ +struct symbol *sym; +struct map *map; +unsigned long stext =0 ; +u64 addr; +int i; + +/* Prepare a map for offline binary */ + map =dso__new_map (pathname); +if (!map ||get_text_start_address (pathname, &stext) <0 ) { +pr_warning ("Failed to get ELF symbols for %s\n" , pathname); +return -EINVAL ; + } + +for (i =0 ; i < ntevs; i++) { + addr = tevs[i].point.address + tevs[i].point.offset - stext; + sym =map__find_symbol (map, addr); +if (!sym) +continue ; +if (!strcmp (sym->name, tevs[i].point.symbol)) +continue ; +/* If we have no realname, use symbol for it */ +if (!tevs[i].point.realname) + tevs[i].point.realname = tevs[i].point.symbol; +else +free (tevs[i].point.symbol); + tevs[i].point.symbol =strdup (sym->name); + tevs[i].point.offset = addr - sym->start; + } +map__put (map); + +return 0 ; +} +static int add_exec_to_probe_trace_events (struct probe_trace_event *tevs,int ntevs,const char *exec) {
@@ -671,7 +716,8 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,/* Skip post process if the target is an offline kernel */ if (symbol_conf.ignore_vmlinux_buildid) -return 0 ; +return post_process_offline_probe_trace_events (tevs, ntevs, + symbol_conf.vmlinux_name); reloc_sym =kernel_get_ref_reloc_sym ();if (!reloc_sym) {
PATCH 3/3 perf-probe: Fix to probe on gcc generated functions in modules
In reply to Masami HiramatsuFix to probe on gcc generated functions on modules. Since probing on a module is based on its symbol name, it should be adjusted on actual symbols.
E.g. without this fix, perf probe shows probe definition on non-exist symbol as below.
-----
$ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -F in_range* in_range.isra.12 $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range+0 ----- With this fix, perf probe correctly shows a probe on gcc-generated symbol. ----- $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range.isra.12+0 -----
--- tools/perf/util/probe-event.c | 38 +++++++++++++++++++++++--------------- tools/perf/util/probe-finder.c | 2 +- tools/perf/util/probe-finder.h | 2 ++ 3 files changed, 26 insertions(+), 16 deletions(-)
tools/perf/util/probe-event.c +23 -15
@@ -682,15 +682,19 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,return ret; } -static int add_module_to_probe_trace_events (struct probe_trace_event *tevs, -int ntevs,const char *module) +static int +post_process_module_probe_trace_events (struct probe_trace_event *tevs, +int ntevs,const char *module, +struct debuginfo *dinfo) { +Dwarf_Addr text_offs;int i, ret =0 ;char *mod_name =NULL ;if (!module)return 0 ; +debuginfo__get_text_offset (dinfo, &text_offs); mod_name =find_module_name (module);for (i =0 ; i < ntevs; i++) {
@@ -700,9 +704,15 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, ret = -ENOMEM ;break ; } +/* kernel module needs a special care to adjust addresses */ + tevs[i].point.address -= (unsigned long )text_offs; }free (mod_name); + +if (!ret) + ret =post_process_offline_probe_trace_events (tevs, ntevs, + module);return ret; }
@@ -760,7 +770,7 @@ arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unusestatic int post_process_probe_trace_events (struct perf_probe_event *pev,struct probe_trace_event *tevs,int ntevs,const char *module, -bool uprobe) +bool uprobe,struct debuginfo *dinfo) {int ret;
@@ -768,7 +778,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev, ret =add_exec_to_probe_trace_events (tevs, ntevs, module); else if (module)/* Currently ref_reloc_sym based probe is not for drivers */ - ret =add_module_to_probe_trace_events (tevs, ntevs, module); + ret =post_process_module_probe_trace_events (tevs, ntevs, + module, dinfo); else ret =post_process_kernel_probe_trace_events (tevs, ntevs);
@@ -812,30 +823,27 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, } } -debuginfo__delete (dinfo); -if (ntevs >0 ) {/* Succeeded to find trace events */ pr_debug ("Found %d probe_trace_events.\n" , ntevs); ret =post_process_probe_trace_events (pev, *tevs, ntevs, - pev->target, pev->uprobes); + pev->target, pev->uprobes, dinfo);if (ret <0 || ret == ntevs) { +pr_debug ("Post processing failed or all events are skipped. (%d)\n" , ret);clear_probe_trace_events (*tevs, ntevs);zfree (tevs); + ntevs =0 ; } -if (ret != ntevs) -return ret <0 ? ret : ntevs; - ntevs =0 ; -/* Fall through */ } +debuginfo__delete (dinfo); +if (ntevs ==0 ) {/* No error but failed to find probe point. */ pr_warning ("Probe point '%s' not found.\n" ,synthesize_perf_probe_point (&pev->point));return -ENOENT ; - } -/* Error path : ntevs < 0 */ -pr_debug ("An error occurred in debuginfo analysis (%d).\n" , ntevs); -if (ntevs <0 ) { + }else if (ntevs <0 ) { +/* Error path : ntevs < 0 */ +pr_debug ("An error occurred in debuginfo analysis (%d).\n" , ntevs);if (ntevs == -EBADF )pr_warning ("Warning: No dwarf info found in the vmlinux - " "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n" );
tools/perf/util/probe-finder.c +1 -1
@@ -1501,7 +1501,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, }/* For the kernel module, we need a special code to get a DIE */ -static int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs) +int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs) {int n, i;Elf32_Word shndx;
tools/perf/util/probe-finder.h +2 -0
@@ -46,6 +46,8 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,int debuginfo__find_probe_point (struct debuginfo *dbg,unsigned long addr,struct perf_probe_point *ppt); +int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs); +/* Find a line range */ int debuginfo__find_line_range (struct debuginfo *dbg,struct line_range *lr);
Re: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
Em Wed, Jan 04, 2017 at 12:31:39PM +0900, Masami Hiramatsu escreveu:
Quoted 7 lines
Fix to probe on gcc generated functions on modules. Since probing on a module is based on its symbol name, it should be adjusted on actual symbols.
E.g. without this fix, perf probe shows probe definition on non-exist symbol as below.
-----
Quoted 11 lines
$ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -F in_range* in_range.isra.12 $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range+0 ----- With this fix, perf probe correctly shows a probe on gcc-generated symbol. ----- $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range.isra.12+0 -----
Tested this one on a x86-64 fedora25 system, applied all three.
As always, please take a look at the patch when sent to Ingo, I usually put some committer notes there, in this case I put the test steps I performed, using e1000e.ko and e1000_flash_cycle_ich8lan.constprop.22
BTW, it would be cool if...
Oops, I retract that, while I was testing what I was went to ask you to implement, I saw that this last patch broke this use case:
[root@jouet ~]# perf probe -m e1000e e1000_xmit_frame Failed to get ELF symbols for e1000e
Probe point 'e1000_xmit_frame' not found.
Error: Failed to add events.
[root@jouet ~]#
If I remove it, I get it back:
[root@jouet ~]# perf probe -m e1000e e1000_xmit_frame Added new event:
probe:e1000_xmit_frame (on e1000_xmit_frame in e1000e)
You can now use it in all perf tools, such as:
perf record -e probe:e1000_xmit_frame -aR sleep 1
[root@jouet ~]# perf probe -l
probe:e1000_xmit_frame (on e1000_get_link_up_info_80003es2lan:7@intel/e1000e/80003es2lan.c in e1000e)
[root@jouet ~]#
BTW, what I would find cool, besides fixing this new problem, would be that:
perf probe e1000_xmit_frame
worked, as we can get the module name from kallsyms:
[acme@jouet linux]$ grep e1000_xmit_frame /proc/kallsymsffffffffc046fc10 t e1000_xmit_frame [e1000e]
[acme@jouet linux]$
I applied the first two patches, and now I'm preparing a pull req to Ingo,
Thanks!
- Arnaldo
Quoted 133 lines
Signed-off-by Masami Hiramatsu <[email protected]>--- tools/perf/util/probe-event.c | 38 +++++++++++++++++++++++--------------- tools/perf/util/probe-finder.c | 2 +- tools/perf/util/probe-finder.h | 2 ++ 3 files changed, 26 insertions(+), 16 deletions(-)tools/perf/util/probe-event.c +23
-15@@ -682,15 +682,19 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,return ret; } -static int add_module_to_probe_trace_events (struct probe_trace_event *tevs, -int ntevs,const char *module) +static int +post_process_module_probe_trace_events (struct probe_trace_event *tevs, +int ntevs,const char *module, +struct debuginfo *dinfo) { +Dwarf_Addr text_offs;int i, ret =0 ;char *mod_name =NULL ;if (!module)return 0 ; +debuginfo__get_text_offset (dinfo, &text_offs); mod_name =find_module_name (module);for (i =0 ; i < ntevs; i++) {@@ -700,9 +704,15 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, ret = -ENOMEM ;break ; } +/* kernel module needs a special care to adjust addresses */ + tevs[i].point.address -= (unsigned long )text_offs; }free (mod_name); + +if (!ret) + ret =post_process_offline_probe_trace_events (tevs, ntevs, + module);return ret; }@@ -760,7 +770,7 @@ arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unusestatic int post_process_probe_trace_events (struct perf_probe_event *pev,struct probe_trace_event *tevs,int ntevs,const char *module, -bool uprobe) +bool uprobe,struct debuginfo *dinfo) {int ret;@@ -768,7 +778,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev, ret =add_exec_to_probe_trace_events (tevs, ntevs, module); else if (module)/* Currently ref_reloc_sym based probe is not for drivers */ - ret =add_module_to_probe_trace_events (tevs, ntevs, module); + ret =post_process_module_probe_trace_events (tevs, ntevs, + module, dinfo); else ret =post_process_kernel_probe_trace_events (tevs, ntevs);@@ -812,30 +823,27 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, } } -debuginfo__delete (dinfo); -if (ntevs >0 ) {/* Succeeded to find trace events */ pr_debug ("Found %d probe_trace_events.\n" , ntevs); ret =post_process_probe_trace_events (pev, *tevs, ntevs, - pev->target, pev->uprobes); + pev->target, pev->uprobes, dinfo);if (ret <0 || ret == ntevs) { +pr_debug ("Post processing failed or all events are skipped. (%d)\n" , ret);clear_probe_trace_events (*tevs, ntevs);zfree (tevs); + ntevs =0 ; } -if (ret != ntevs) -return ret <0 ? ret : ntevs; - ntevs =0 ; -/* Fall through */ } +debuginfo__delete (dinfo); +if (ntevs ==0 ) {/* No error but failed to find probe point. */ pr_warning ("Probe point '%s' not found.\n" ,synthesize_perf_probe_point (&pev->point));return -ENOENT ; - } -/* Error path : ntevs < 0 */ -pr_debug ("An error occurred in debuginfo analysis (%d).\n" , ntevs); -if (ntevs <0 ) { + }else if (ntevs <0 ) { +/* Error path : ntevs < 0 */ +pr_debug ("An error occurred in debuginfo analysis (%d).\n" , ntevs);if (ntevs == -EBADF )pr_warning ("Warning: No dwarf info found in the vmlinux - " "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n" );tools/perf/util/probe-finder.c +1
-1@@ -1501,7 +1501,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, }/* For the kernel module, we need a special code to get a DIE */ -static int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs) +int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs) {int n, i;Elf32_Word shndx;tools/perf/util/probe-finder.h +2
-0@@ -46,6 +46,8 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,int debuginfo__find_probe_point (struct debuginfo *dbg,unsigned long addr,struct perf_probe_point *ppt); +int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs); +/* Find a line range */ int debuginfo__find_line_range (struct debuginfo *dbg,struct line_range *lr);
Re: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
Quoted 28 lines · On Wed, 4 Jan 2017 11:48:56 -0300 Arnaldo Carvalho de Melo <[email protected]>…
Em Wed, Jan 04, 2017 at 12:31:39PM +0900, Masami Hiramatsu escreveu:
Quoted 7 lines
Fix to probe on gcc generated functions on modules. Since probing on a module is based on its symbol name, it should be adjusted on actual symbols.
E.g. without this fix, perf probe shows probe definition on non-exist symbol as below.
-----Quoted 11 lines
$ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -F in_range* in_range.isra.12 $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range+0 ----- With this fix, perf probe correctly shows a probe on gcc-generated symbol. ----- $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range.isra.12+0 -----Tested this one on a x86-64 fedora25 system, applied all three.
As always, please take a look at the patch when sent to Ingo, I usually put some committer notes there, in this case I put the test steps I performed, using e1000e.ko and e1000_flash_cycle_ich8lan.constprop.22
BTW, it would be cool if...
Quoted 8 lines
Oops, I retract that, while I was testing what I was went to ask you to implement, I saw that this last patch broke this use case:
[root@jouet ~]# perf probe -m e1000e
e1000_xmit_frameFailed to get ELF symbols for e1000e
Probe point 'e1000_xmit_frame' not found.
Error: Failed to add events.
[root@jouet ~]#
Oops, I missed that case.
However, when I trided to fix that on fedora25,
$ perf probe -m i915 -vD assert_plane probe-definition(0): assert_plane symbol:assert_plane file:(null) line:0 offset:0 return:0 lazy:(null) 0 arguments No kprobe blacklist support, ignored Failed to get build-id from i915. Cache open error: -1 Open Debuginfo file: /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz Try to find probe point from debuginfo. Matched function: assert_plane [6fb806] found inline addr: 0x886a0 Probe point found: assert_plane+0 Found 1 probe_trace_events. text offset: 10030 Failed to get ELF symbols for /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz Post processing failed or all events are skipped. (-22) Probe point 'assert_plane' not found. Error: Failed to add events. Reason: No such file or directory (Code: -2)
As far as I can see, elfutils's libdw supports compressed file, but libelf API (perf's API) seems not supporting it. This results in succeeding opening debuginfo, but failing ELF symbols.
Quoted 17 lines
If I remove it, I get it back:
[root@jouet ~]# perf probe -m e1000e
e1000_xmit_frameAdded new event:
probe:e1000_xmit_frame (one1000_xmit_framein e1000e)You can now use it in all perf tools, such as:
perf record -e probe:e1000_xmit_frame -aR sleep 1
[root@jouet ~]# perf probe -l
probe:e1000_xmit_frame (on e1000_get_link_up_info_80003es2lan:7@intel/e1000e/80003es2lan.c in e1000e)
[root@jouet ~]#BTW, what I would find cool, besides fixing this new problem, would be that:
Quoted 7 lines
perf probe
e1000_xmit_frameworked, as we can get the module name from kallsyms:
[acme@jouet linux]$ grep
e1000_xmit_frame/proc/kallsymsffffffffc046fc10te1000_xmit_frame[e1000e]
[acme@jouet linux]$
OK, it sounds reasonable to me too. BTW, how can I get the map for kallsyms? May machine__findnew_module_map(host_machine, ,"[kernel.kallsyms]") include module symbols too?
Quoted 2 lines
I applied the first two patches, and now I'm preparing a pull req to Ingo,
Thanks!
Quoted 138 lines
Thanks!
- Arnaldo
Quoted 133 lines
Signed-off-by Masami Hiramatsu <[email protected]>--- tools/perf/util/probe-event.c | 38 +++++++++++++++++++++++--------------- tools/perf/util/probe-finder.c | 2 +- tools/perf/util/probe-finder.h | 2 ++ 3 files changed, 26 insertions(+), 16 deletions(-)tools/perf/util/probe-event.c +23
-15@@ -682,15 +682,19 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,return ret; } -static int add_module_to_probe_trace_events (struct probe_trace_event *tevs, -int ntevs,const char *module) +static int +post_process_module_probe_trace_events (struct probe_trace_event *tevs, +int ntevs,const char *module, +struct debuginfo *dinfo) { +Dwarf_Addr text_offs;int i, ret =0 ;char *mod_name =NULL ;if (!module)return 0 ; +debuginfo__get_text_offset (dinfo, &text_offs); mod_name =find_module_name (module);for (i =0 ; i < ntevs; i++) {@@ -700,9 +704,15 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, ret = -ENOMEM ;break ; } +/* kernel module needs a special care to adjust addresses */ + tevs[i].point.address -= (unsigned long )text_offs; }free (mod_name); + +if (!ret) + ret =post_process_offline_probe_trace_events (tevs, ntevs, + module);return ret; }@@ -760,7 +770,7 @@ arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unusestatic int post_process_probe_trace_events (struct perf_probe_event *pev,struct probe_trace_event *tevs,int ntevs,const char *module, -bool uprobe) +bool uprobe,struct debuginfo *dinfo) {int ret;@@ -768,7 +778,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev, ret =add_exec_to_probe_trace_events (tevs, ntevs, module); else if (module)/* Currently ref_reloc_sym based probe is not for drivers */ - ret =add_module_to_probe_trace_events (tevs, ntevs, module); + ret =post_process_module_probe_trace_events (tevs, ntevs, + module, dinfo); else ret =post_process_kernel_probe_trace_events (tevs, ntevs);@@ -812,30 +823,27 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, } } -debuginfo__delete (dinfo); -if (ntevs >0 ) {/* Succeeded to find trace events */ pr_debug ("Found %d probe_trace_events.\n" , ntevs); ret =post_process_probe_trace_events (pev, *tevs, ntevs, - pev->target, pev->uprobes); + pev->target, pev->uprobes, dinfo);if (ret <0 || ret == ntevs) { +pr_debug ("Post processing failed or all events are skipped. (%d)\n" , ret);clear_probe_trace_events (*tevs, ntevs);zfree (tevs); + ntevs =0 ; } -if (ret != ntevs) -return ret <0 ? ret : ntevs; - ntevs =0 ; -/* Fall through */ } +debuginfo__delete (dinfo); +if (ntevs ==0 ) {/* No error but failed to find probe point. */ pr_warning ("Probe point '%s' not found.\n" ,synthesize_perf_probe_point (&pev->point));return -ENOENT ; - } -/* Error path : ntevs < 0 */ -pr_debug ("An error occurred in debuginfo analysis (%d).\n" , ntevs); -if (ntevs <0 ) { + }else if (ntevs <0 ) { +/* Error path : ntevs < 0 */ +pr_debug ("An error occurred in debuginfo analysis (%d).\n" , ntevs);if (ntevs == -EBADF )pr_warning ("Warning: No dwarf info found in the vmlinux - " "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n" );tools/perf/util/probe-finder.c +1
-1@@ -1501,7 +1501,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, }/* For the kernel module, we need a special code to get a DIE */ -static int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs) +int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs) {int n, i;Elf32_Word shndx;tools/perf/util/probe-finder.h +2
-0@@ -46,6 +46,8 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,int debuginfo__find_probe_point (struct debuginfo *dbg,unsigned long addr,struct perf_probe_point *ppt); +int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs); +/* Find a line range */ int debuginfo__find_line_range (struct debuginfo *dbg,struct line_range *lr);
Signature · 1 line
Masami Hiramatsu <[email protected]>
Re: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
Quoted 62 lines · On Thu, 5 Jan 2017 20:20:19 +0900 Masami Hiramatsu <[email protected]> wrote:
Quoted 28 lines · On Wed, 4 Jan 2017 11:48:56 -0300 Arnaldo Carvalho de Melo <[email protected]>…
Em Wed, Jan 04, 2017 at 12:31:39PM +0900, Masami Hiramatsu escreveu:
Quoted 7 lines
Fix to probe on gcc generated functions on modules. Since probing on a module is based on its symbol name, it should be adjusted on actual symbols.
E.g. without this fix, perf probe shows probe definition on non-exist symbol as below.
-----Quoted 11 lines
$ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -F in_range* in_range.isra.12 $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range+0 ----- With this fix, perf probe correctly shows a probe on gcc-generated symbol. ----- $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range.isra.12+0 -----Tested this one on a x86-64 fedora25 system, applied all three.
As always, please take a look at the patch when sent to Ingo, I usually put some committer notes there, in this case I put the test steps I performed, using e1000e.ko and e1000_flash_cycle_ich8lan.constprop.22
BTW, it would be cool if...
Quoted 8 lines
Oops, I retract that, while I was testing what I was went to ask you to implement, I saw that this last patch broke this use case:
[root@jouet ~]# perf probe -m e1000e
e1000_xmit_frameFailed to get ELF symbols for e1000e
Probe point 'e1000_xmit_frame' not found.
Error: Failed to add events.
[root@jouet ~]#Oops, I missed that case.
However, when I trided to fix that on fedora25,$ perf probe -m i915 -vD assert_plane probe-definition(0): assert_plane symbol:assert_plane file:(null) line:0 offset:0 return:0 lazy:(null) 0 arguments No kprobe blacklist support, ignored Failed to get build-id from i915. Cache open error: -1 Open Debuginfo file: /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz Try to find probe point from debuginfo. Matched function: assert_plane [6fb806] found inline addr: 0x886a0 Probe point found: assert_plane+0 Found 1 probe_trace_events. text offset: 10030 Failed to get ELF symbols for /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz Post processing failed or all events are skipped. (-22) Probe point 'assert_plane' not found. Error: Failed to add events. Reason: No such file or directory (Code: -2)
Quoted 3 lines
As far as I can see, elfutils's libdw supports compressed file, but libelf API (perf's API) seems not supporting it. This results in succeeding opening debuginfo, but failing ELF symbols.
Sorry, this is my fault, perf's map already supported that. Anyway, I can get ELF headers from debuginfo. However, I'm still trying to fix an text section offset issue in modules.
Thanks,
Signature · 1 line
Masami Hiramatsu <[email protected]>
Arnaldo Carvalho de Melo
maintainerRe: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
In reply to Masami HiramatsuEm Thu, Jan 05, 2017 at 08:20:19PM +0900, Masami Hiramatsu escreveu:
Quoted 87 lines
Quoted 28 lines · On Wed, 4 Jan 2017 11:48:56 -0300 Arnaldo Carvalho de Melo <[email protected]>…
Em Wed, Jan 04, 2017 at 12:31:39PM +0900, Masami Hiramatsu escreveu:
Quoted 7 lines
Fix to probe on gcc generated functions on modules. Since probing on a module is based on its symbol name, it should be adjusted on actual symbols.
E.g. without this fix, perf probe shows probe definition on non-exist symbol as below.
-----Quoted 11 lines
$ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -F in_range* in_range.isra.12 $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range+0 ----- With this fix, perf probe correctly shows a probe on gcc-generated symbol. ----- $ perf probe -m build-x86_64/net/netfilter/nf_nat.ko -D in_range p:probe/in_range nf_nat:in_range.isra.12+0 -----Tested this one on a x86-64 fedora25 system, applied all three.
As always, please take a look at the patch when sent to Ingo, I usually put some committer notes there, in this case I put the test steps I performed, using e1000e.ko and e1000_flash_cycle_ich8lan.constprop.22
BTW, it would be cool if...
Quoted 8 lines
Oops, I retract that, while I was testing what I was went to ask you to implement, I saw that this last patch broke this use case:
[root@jouet ~]# perf probe -m e1000e
e1000_xmit_frameFailed to get ELF symbols for e1000e
Probe point 'e1000_xmit_frame' not found.
Error: Failed to add events.
[root@jouet ~]#Oops, I missed that case.
However, when I trided to fix that on fedora25,$ perf probe -m i915 -vD assert_plane probe-definition(0): assert_plane symbol:assert_plane file:(null) line:0 offset:0 return:0 lazy:(null) 0 arguments No kprobe blacklist support, ignored Failed to get build-id from i915. Cache open error: -1 Open Debuginfo file: /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz Try to find probe point from debuginfo. Matched function: assert_plane [6fb806] found inline addr: 0x886a0 Probe point found: assert_plane+0 Found 1 probe_trace_events. text offset: 10030 Failed to get ELF symbols for /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz Post processing failed or all events are skipped. (-22) Probe point 'assert_plane' not found. Error: Failed to add events. Reason: No such file or directory (Code: -2)As far as I can see, elfutils's libdw supports compressed file, but libelf API (perf's API) seems not supporting it. This results in succeeding opening debuginfo, but failing ELF symbols.
Quoted 21 lines
If I remove it, I get it back:
[root@jouet ~]# perf probe -m e1000e
e1000_xmit_frameAdded new event:
probe:e1000_xmit_frame (one1000_xmit_framein e1000e)You can now use it in all perf tools, such as:
perf record -e probe:e1000_xmit_frame -aR sleep 1
[root@jouet ~]# perf probe -l
probe:e1000_xmit_frame (on e1000_get_link_up_info_80003es2lan:7@intel/e1000e/80003es2lan.c in e1000e)
[root@jouet ~]#BTW, what I would find cool, besides fixing this new problem, would be that:
perf probe
e1000_xmit_frameworked, as we can get the module name from kallsyms:
Quoted 7 lines
Quoted 3 lines
[acme@jouet linux]$ grep
e1000_xmit_frame/proc/kallsymsffffffffc046fc10te1000_xmit_frame[e1000e]
[acme@jouet linux]$OK, it sounds reasonable to me too. BTW, how can I get the map for kallsyms? May
machine__findnew_module_map(host_machine, ,"[kernel.kallsyms]")include module symbols too?
Well, the machine abstraction is there for that, i.e. to get all the abstractions related to a machine (kernel, kernel modules, threads, maps, symbols).
We have 'struct machines' as well, to deal with VMs, etc. This can come from the running system or from a perf.data file, when it may be for a different architecture than the machine where analysis is done.
So, "map for kallsyms" in fact should be "maps for kallsyms", as it will split the maps for each module, etc.
Probably what you want is:
symbol = machine__find_kernel_function_by_name(machine, name, &map);
Then, if symbol is not NULL, map->dso->name will have your module name, map->dso->long_name will have the .ko path, etc.
- Arnaldo
Quoted 148 lines
Quoted 3 lines
I applied the first two patches, and now I'm preparing a pull req to Ingo,
Thanks!
Quoted 138 lines
Thanks!
- Arnaldo
Quoted 133 lines
Signed-off-by Masami Hiramatsu <[email protected]>--- tools/perf/util/probe-event.c | 38 +++++++++++++++++++++++--------------- tools/perf/util/probe-finder.c | 2 +- tools/perf/util/probe-finder.h | 2 ++ 3 files changed, 26 insertions(+), 16 deletions(-)tools/perf/util/probe-event.c +23
-15@@ -682,15 +682,19 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,return ret; } -static int add_module_to_probe_trace_events (struct probe_trace_event *tevs, -int ntevs,const char *module) +static int +post_process_module_probe_trace_events (struct probe_trace_event *tevs, +int ntevs,const char *module, +struct debuginfo *dinfo) { +Dwarf_Addr text_offs;int i, ret =0 ;char *mod_name =NULL ;if (!module)return 0 ; +debuginfo__get_text_offset (dinfo, &text_offs); mod_name =find_module_name (module);for (i =0 ; i < ntevs; i++) {@@ -700,9 +704,15 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, ret = -ENOMEM ;break ; } +/* kernel module needs a special care to adjust addresses */ + tevs[i].point.address -= (unsigned long )text_offs; }free (mod_name); + +if (!ret) + ret =post_process_offline_probe_trace_events (tevs, ntevs, + module);return ret; }@@ -760,7 +770,7 @@ arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unusestatic int post_process_probe_trace_events (struct perf_probe_event *pev,struct probe_trace_event *tevs,int ntevs,const char *module, -bool uprobe) +bool uprobe,struct debuginfo *dinfo) {int ret;@@ -768,7 +778,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev, ret =add_exec_to_probe_trace_events (tevs, ntevs, module); else if (module)/* Currently ref_reloc_sym based probe is not for drivers */ - ret =add_module_to_probe_trace_events (tevs, ntevs, module); + ret =post_process_module_probe_trace_events (tevs, ntevs, + module, dinfo); else ret =post_process_kernel_probe_trace_events (tevs, ntevs);@@ -812,30 +823,27 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, } } -debuginfo__delete (dinfo); -if (ntevs >0 ) {/* Succeeded to find trace events */ pr_debug ("Found %d probe_trace_events.\n" , ntevs); ret =post_process_probe_trace_events (pev, *tevs, ntevs, - pev->target, pev->uprobes); + pev->target, pev->uprobes, dinfo);if (ret <0 || ret == ntevs) { +pr_debug ("Post processing failed or all events are skipped. (%d)\n" , ret);clear_probe_trace_events (*tevs, ntevs);zfree (tevs); + ntevs =0 ; } -if (ret != ntevs) -return ret <0 ? ret : ntevs; - ntevs =0 ; -/* Fall through */ } +debuginfo__delete (dinfo); +if (ntevs ==0 ) {/* No error but failed to find probe point. */ pr_warning ("Probe point '%s' not found.\n" ,synthesize_perf_probe_point (&pev->point));return -ENOENT ; - } -/* Error path : ntevs < 0 */ -pr_debug ("An error occurred in debuginfo analysis (%d).\n" , ntevs); -if (ntevs <0 ) { + }else if (ntevs <0 ) { +/* Error path : ntevs < 0 */ +pr_debug ("An error occurred in debuginfo analysis (%d).\n" , ntevs);if (ntevs == -EBADF )pr_warning ("Warning: No dwarf info found in the vmlinux - " "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n" );tools/perf/util/probe-finder.c +1
-1@@ -1501,7 +1501,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, }/* For the kernel module, we need a special code to get a DIE */ -static int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs) +int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs) {int n, i;Elf32_Word shndx;tools/perf/util/probe-finder.h +2
-0@@ -46,6 +46,8 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,int debuginfo__find_probe_point (struct debuginfo *dbg,unsigned long addr,struct perf_probe_point *ppt); +int debuginfo__get_text_offset (struct debuginfo *dbg,Dwarf_Addr *offs); +/* Find a line range */ int debuginfo__find_line_range (struct debuginfo *dbg,struct line_range *lr);Signature · 1 line
Masami Hiramatsu <[email protected]>
Arnaldo Carvalho de Melo
maintainerRe: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
Em Thu, Jan 05, 2017 at 12:30:37PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 11 lines
Em Thu, Jan 05, 2017 at 08:20:19PM +0900, Masami Hiramatsu escreveu:
Quoted 9 lines
Quoted 3 lines · On Wed, 4 Jan 2017 11:48:56 -0300 Arnaldo Carvalho de Melo <[email protected]>…
[acme@jouet linux]$ grep
e1000_xmit_frame/proc/kallsymsffffffffc046fc10te1000_xmit_frame[e1000e]
[acme@jouet linux]$OK, it sounds reasonable to me too. BTW, how can I get the map for kallsyms? May
machine__findnew_module_map(host_machine, ,"[kernel.kallsyms]")include module symbols too?
Quoted 6 lines
Probably what you want is:
symbol =
machine__find_kernel_function_by_name(machine, name, &map);Then, if symbol is not NULL,
map->dso->namewill have your module name,map->dso->long_namewill have the .ko path, etc.
Take a look at 'perf kallsyms' a simple toy cmd that exercises the APIs you need:
Basically:
struct machine *machine = machine__new_kallsyms(); struct map *map; struct symbol *symbol = machine__find_kernel_function_by_name(machine, symbol_name, &map);
Then you have symbol->{addr,end,name,etc} and map->dso->{long,short}_name
$ perf kallsyms e1000_xmit_frame usb_stor_set_xfer_buf e1000_xmit_frame: [e1000e] /lib/modules/4.9.0+/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko 0xffffffffc046fc10-0xffffffffc0470bb0 (0x19c80-0x1ac20) usb_stor_set_xfer_buf: [usb_storage] /lib/modules/4.9.0+/kernel/drivers/usb/storage/usb-storage.ko 0xffffffffc057aea0-0xffffffffc057af19 (0xf10-0xf89)
- Arnaldo
Re: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
Quoted 24 lines · On Thu, 5 Jan 2017 15:47:43 -0300 Arnaldo Carvalho de Melo <[email protected]>…
Em Thu, Jan 05, 2017 at 12:30:37PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 11 lines
Em Thu, Jan 05, 2017 at 08:20:19PM +0900, Masami Hiramatsu escreveu:
Quoted 9 lines
Quoted 3 lines · On Wed, 4 Jan 2017 11:48:56 -0300 Arnaldo Carvalho de Melo <[email protected]>…
[acme@jouet linux]$ grep
e1000_xmit_frame/proc/kallsymsffffffffc046fc10te1000_xmit_frame[e1000e]
[acme@jouet linux]$OK, it sounds reasonable to me too. BTW, how can I get the map for kallsyms? May
machine__findnew_module_map(host_machine, ,"[kernel.kallsyms]")include module symbols too?Quoted 6 lines
Probably what you want is:
symbol =
machine__find_kernel_function_by_name(machine, name, &map);Then, if symbol is not NULL,
map->dso->namewill have your module name,map->dso->long_namewill have the .ko path, etc.Take a look at 'perf kallsyms' a simple toy cmd that exercises the APIs you need:
Quoted 7 lines
Basically:
struct machine *machine = machine__new_kallsyms(); struct map *map; struct symbol *symbol = machine__find_kernel_function_by_name(machine, symbol_name, &map);Then you have symbol->{addr,end,name,etc} and map->dso->{long,short}_name
Thanks for the precise information :)
I'll make and send it with updated 3rd patch.
Thanks again!
Quoted 6 lines
$ perf kallsyms e1000_xmit_frame usb_stor_set_xfer_buf e1000_xmit_frame: [e1000e] /lib/modules/4.9.0+/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko 0xffffffffc046fc10-0xffffffffc0470bb0 (0x19c80-0x1ac20) usb_stor_set_xfer_buf: [usb_storage] /lib/modules/4.9.0+/kernel/drivers/usb/storage/usb-storage.ko 0xffffffffc057aea0-0xffffffffc057af19 (0xf10-0xf89)- Arnaldo
Signature · 1 line
Masami Hiramatsu <[email protected]>
Re: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
In reply to Arnaldo Carvalho de MeloHi Arnaldo,
Quoted 30 lines · On Thu, 5 Jan 2017 15:47:43 -0300 Arnaldo Carvalho de Melo <[email protected]>…
Em Thu, Jan 05, 2017 at 12:30:37PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 11 lines
Em Thu, Jan 05, 2017 at 08:20:19PM +0900, Masami Hiramatsu escreveu:
Quoted 9 lines
Quoted 3 lines · On Wed, 4 Jan 2017 11:48:56 -0300 Arnaldo Carvalho de Melo <[email protected]>…
[acme@jouet linux]$ grep
e1000_xmit_frame/proc/kallsymsffffffffc046fc10te1000_xmit_frame[e1000e]
[acme@jouet linux]$OK, it sounds reasonable to me too. BTW, how can I get the map for kallsyms? May
machine__findnew_module_map(host_machine, ,"[kernel.kallsyms]")include module symbols too?Quoted 6 lines
Probably what you want is:
symbol =
machine__find_kernel_function_by_name(machine, name, &map);Then, if symbol is not NULL,
map->dso->namewill have your module name,map->dso->long_namewill have the .ko path, etc.Take a look at 'perf kallsyms' a simple toy cmd that exercises the APIs you need:
Basically:
struct machine *machine = machine__new_kallsyms(); struct map *map; struct symbol *symbol = machine__find_kernel_function_by_name(machine, symbol_name, &map);
Quoted 5 lines
Then you have symbol->{addr,end,name,etc} and map->dso->{long,short}_name
$ perf kallsyms e1000_xmit_frame usb_stor_set_xfer_buf e1000_xmit_frame: [e1000e] /lib/modules/4.9.0+/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko 0xffffffffc046fc10-0xffffffffc0470bb0 (0x19c80-0x1ac20) usb_stor_set_xfer_buf: [usb_storage] /lib/modules/4.9.0+/kernel/drivers/usb/storage/usb-storage.ko 0xffffffffc057aea0-0xffffffffc057af19 (0xf10-0xf89)
I've found an issue on perf kallsyms. Please see below.
When I run kallsyms without root privilege, it works well.
$ ./perf kallsyms -vv drm_malloc_ab Failed to open /proc/kcore. Note /proc/kcore requires CAP_SYS_RAWIO capability to access. drm_malloc_ab: [i915] /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz 0xffffffffc0211950-0xffffffffc02119a6 (0x309c0-0x30a16)
However, with root privilege it failed to get correct module name...
$ sudo ./perf kallsyms -vv drm_malloc_ab Using /proc/kcore for kernel object code drm_malloc_ab: [kernel] /proc/kcore 0xffffffffc0211950-0xffffffffc02119b0 (0x7fffc0214950-0x7fffc02149b0)
Thank you,
Quoted 2 lines
- Arnaldo
Signature · 1 line
Masami Hiramatsu <[email protected]>
Arnaldo Carvalho de Melo
maintainerRe: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
Em Sat, Jan 07, 2017 at 01:22:23AM +0900, Masami Hiramatsu escreveu:
Quoted 46 lines
Quoted 30 lines · On Thu, 5 Jan 2017 15:47:43 -0300 Arnaldo Carvalho de Melo <[email protected]>…
Em Thu, Jan 05, 2017 at 12:30:37PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 11 lines
Em Thu, Jan 05, 2017 at 08:20:19PM +0900, Masami Hiramatsu escreveu:
Quoted 9 lines
Quoted 3 lines · On Wed, 4 Jan 2017 11:48:56 -0300 Arnaldo Carvalho de Melo <[email protected]>…
[acme@jouet linux]$ grep
e1000_xmit_frame/proc/kallsymsffffffffc046fc10te1000_xmit_frame[e1000e]
[acme@jouet linux]$OK, it sounds reasonable to me too. BTW, how can I get the map for kallsyms? May
machine__findnew_module_map(host_machine, ,"[kernel.kallsyms]")include module symbols too?Quoted 6 lines
Probably what you want is:
symbol =
machine__find_kernel_function_by_name(machine, name, &map);Then, if symbol is not NULL,
map->dso->namewill have your module name,map->dso->long_namewill have the .ko path, etc.Take a look at 'perf kallsyms' a simple toy cmd that exercises the APIs you need:
Basically:
struct machine *machine = machine__new_kallsyms(); struct map *map; struct symbol *symbol = machine__find_kernel_function_by_name(machine, symbol_name, &map);Quoted 5 lines
Then you have symbol->{addr,end,name,etc} and map->dso->{long,short}_name
$ perf kallsyms e1000_xmit_frame usb_stor_set_xfer_buf e1000_xmit_frame: [e1000e] /lib/modules/4.9.0+/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko 0xffffffffc046fc10-0xffffffffc0470bb0 (0x19c80-0x1ac20) usb_stor_set_xfer_buf: [usb_storage] /lib/modules/4.9.0+/kernel/drivers/usb/storage/usb-storage.ko 0xffffffffc057aea0-0xffffffffc057af19 (0xf10-0xf89)I've found an issue on perf kallsyms. Please see below.
When I run kallsyms without root privilege, it works well.
$ ./perf kallsyms -vv drm_malloc_ab Failed to open /proc/kcore. Note /proc/kcore requires CAP_SYS_RAWIO capability to access. drm_malloc_ab: [i915] /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz 0xffffffffc0211950-0xffffffffc02119a6 (0x309c0-0x30a16)
Quoted 5 lines
However, with root privilege it failed to get correct module name...
$ sudo ./perf kallsyms -vv drm_malloc_ab Using /proc/kcore for kernel object code drm_malloc_ab: [kernel] /proc/kcore 0xffffffffc0211950-0xffffffffc02119b0 (0x7fffc0214950-0x7fffc02149b0)
Right, that is something that needs fixing, please try with the patch below.
The problem is that when using /proc/kcore it messes up the creation of one map per module :-\
tools/perf/util/machine.c +1 -1
@@ -91,7 +91,7 @@ struct machine *machine__new_kallsyms(void) {struct machine *machine =machine__new_host (); -if (machine &&machine__load_kallsyms (machine,"/proc/kallsyms" ,MAP__FUNCTION ) <=0 ) { +if (machine &&__machine__load_kallsyms (machine,"/proc/kallsyms" ,MAP__FUNCTION , true) <=0 ) {machine__delete (machine); machine =NULL ; }
Masami Hiramatsu
Tested-byRe: [PATCH perf/core 3/3] perf-probe: Fix to probe on gcc generated functions in modules
Quoted 53 lines · On Fri, 6 Jan 2017 15:17:11 -0300 Arnaldo Carvalho de Melo <[email protected]>…
Em Sat, Jan 07, 2017 at 01:22:23AM +0900, Masami Hiramatsu escreveu:
Quoted 46 lines
Quoted 30 lines · On Thu, 5 Jan 2017 15:47:43 -0300 Arnaldo Carvalho de Melo <[email protected]>…
Em Thu, Jan 05, 2017 at 12:30:37PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 11 lines
Em Thu, Jan 05, 2017 at 08:20:19PM +0900, Masami Hiramatsu escreveu:
Quoted 9 lines
Quoted 3 lines · On Wed, 4 Jan 2017 11:48:56 -0300 Arnaldo Carvalho de Melo <[email protected]>…
[acme@jouet linux]$ grep
e1000_xmit_frame/proc/kallsymsffffffffc046fc10te1000_xmit_frame[e1000e]
[acme@jouet linux]$OK, it sounds reasonable to me too. BTW, how can I get the map for kallsyms? May
machine__findnew_module_map(host_machine, ,"[kernel.kallsyms]")include module symbols too?Quoted 6 lines
Probably what you want is:
symbol =
machine__find_kernel_function_by_name(machine, name, &map);Then, if symbol is not NULL,
map->dso->namewill have your module name,map->dso->long_namewill have the .ko path, etc.Take a look at 'perf kallsyms' a simple toy cmd that exercises the APIs you need:
Basically:
struct machine *machine = machine__new_kallsyms(); struct map *map; struct symbol *symbol = machine__find_kernel_function_by_name(machine, symbol_name, &map);Quoted 5 lines
Then you have symbol->{addr,end,name,etc} and map->dso->{long,short}_name
$ perf kallsyms e1000_xmit_frame usb_stor_set_xfer_buf e1000_xmit_frame: [e1000e] /lib/modules/4.9.0+/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko 0xffffffffc046fc10-0xffffffffc0470bb0 (0x19c80-0x1ac20) usb_stor_set_xfer_buf: [usb_storage] /lib/modules/4.9.0+/kernel/drivers/usb/storage/usb-storage.ko 0xffffffffc057aea0-0xffffffffc057af19 (0xf10-0xf89)I've found an issue on perf kallsyms. Please see below.
When I run kallsyms without root privilege, it works well.
$ ./perf kallsyms -vv drm_malloc_ab Failed to open /proc/kcore. Note /proc/kcore requires CAP_SYS_RAWIO capability to access. drm_malloc_ab: [i915] /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz 0xffffffffc0211950-0xffffffffc02119a6 (0x309c0-0x30a16)Quoted 5 lines
However, with root privilege it failed to get correct module name...
$ sudo ./perf kallsyms -vv drm_malloc_ab Using /proc/kcore for kernel object code drm_malloc_ab: [kernel] /proc/kcore 0xffffffffc0211950-0xffffffffc02119b0 (0x7fffc0214950-0x7fffc02149b0)
Quoted 5 lines
Right, that is something that needs fixing, please try with the patch below.
The problem is that when using
/proc/kcoreit messes up the creation of one map per module :-\
OK, it works now :)
$ sudo ./perf kallsyms drm_malloc_ab drm_malloc_ab: [i915] /lib/modules/4.8.15-300.fc25.x86_64/kernel/drivers/gpu/drm/i915/i915.ko.xz 0xffffffffc0188950-0xffffffffc01889a6 (0x309c0-0x30a16)
Thanks!
Quoted 14 lines
tools/perf/util/machine.c +1
-1@@ -91,7 +91,7 @@ struct machine *machine__new_kallsyms(void) {struct machine *machine =machine__new_host (); -if (machine &&machine__load_kallsyms (machine,"/proc/kallsyms" ,MAP__FUNCTION ) <=0 ) { +if (machine &&__machine__load_kallsyms (machine,"/proc/kallsyms" ,MAP__FUNCTION , true) <=0 ) {machine__delete (machine); machine =NULL ; }
Signature · 1 line
Masami Hiramatsu <[email protected]>