Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752235AbcDZOfB (ORCPT ); Tue, 26 Apr 2016 10:35:01 -0400 Received: from mail.kernel.org ([198.145.29.136]:44766 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751848AbcDZOfA (ORCPT ); Tue, 26 Apr 2016 10:35:00 -0400 Date: Tue, 26 Apr 2016 11:34:53 -0300 From: Arnaldo Carvalho de Melo To: Ravi Bangoria Cc: linux-kernel@vger.kernel.org, peterz@infradead.org, mingo@redhat.com, alexander.shishkin@linux.intel.com, mhiramat@kernel.org, wangnan0@huawei.com, namhyung@kernel.org, srikar@linux.vnet.ibm.com, naveen.n.rao@linux.vnet.ibm.com Subject: Re: [PATCH 1/2] perf probe: Fix module probe issue if no dwarf support Message-ID: <20160426143453.GD11033@kernel.org> References: <1461680741-12517-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1461680741-12517-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com> X-Url: http://acmel.wordpress.com User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5062 Lines: 161 Em Tue, Apr 26, 2016 at 07:55:40PM +0530, Ravi Bangoria escreveu: > Perf is not able to register probe in kernel module when dwarf supprt > is not there(and so it goes for symtab). Perf passes full path of > module where only module name is required which is causing the problem. > This patch fixes this issue. Is this v3? What has changed from v2? - Arnaldo > Before applying patch: > > $ dpkg -s libdw-dev > dpkg-query: package 'libdw-dev' is not installed and no information is... > > $ sudo ./perf probe -m /linux/samples/kprobes/kprobe_example.ko kprobe_init > Added new event: > probe:kprobe_init (on kprobe_init in /linux/samples/kprobes/kprobe_example.ko) > > You can now use it in all perf tools, such as: > > perf record -e probe:kprobe_init -aR sleep 1 > > $ sudo cat /sys/kernel/debug/tracing/kprobe_events > p:probe/kprobe_init /linux/samples/kprobes/kprobe_example.ko:kprobe_init > > $ sudo ./perf record -a -e probe:kprobe_init > [ perf record: Woken up 1 times to write data ] > [ perf record: Captured and wrote 0.105 MB perf.data ] > > $ sudo ./perf script # No output here > > After applying patch: > > $ sudo ./perf probe -m /linux/samples/kprobes/kprobe_example.ko kprobe_init > Added new event: > probe:kprobe_init (on kprobe_init in kprobe_example) > > You can now use it in all perf tools, such as: > > perf record -e probe:kprobe_init -aR sleep 1 > > $ sudo cat /sys/kernel/debug/tracing/kprobe_events > p:probe/kprobe_init kprobe_example:kprobe_init > > $ sudo ./perf record -a -e probe:kprobe_init > [ perf record: Woken up 1 times to write data ] > [ perf record: Captured and wrote 0.105 MB perf.data (2 samples) ] > > $ sudo ./perf script > insmod 13990 [002] 5961.216833: probe:kprobe_init: ... > insmod 13995 [002] 5962.889384: probe:kprobe_init: ... > > Signed-off-by: Ravi Bangoria > --- > tools/perf/util/probe-event.c | 76 +++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 73 insertions(+), 3 deletions(-) > > diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c > index 8319fbb..d58de20 100644 > --- a/tools/perf/util/probe-event.c > +++ b/tools/perf/util/probe-event.c > @@ -265,6 +265,65 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address) > 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, > + * inspect elf and find out what is actual module name. > + * Caller has to free mod_name after using it. > + */ > +static char *find_module_name(const char *module) > +{ > + int fd; > + Elf *elf; > + GElf_Ehdr ehdr; > + GElf_Shdr shdr; > + Elf_Data *data; > + Elf_Scn *sec; > + char *mod_name = NULL; > + > + fd = open(module, O_RDONLY); > + if (fd < 0) > + return NULL; > + > + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); > + if (elf == NULL) > + goto elf_err; > + > + if (gelf_getehdr(elf, &ehdr) == NULL) > + goto ret_err; > + > + sec = elf_section_by_name(elf, &ehdr, &shdr, > + ".gnu.linkonce.this_module", NULL); > + if (!sec) > + goto ret_err; > + > + data = elf_getdata(sec, NULL); > + if (!data || !data->d_buf) > + goto ret_err; > + > + mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET); > + > +ret_err: > + elf_end(elf); > +elf_err: > + close(fd); > + return mod_name; > +} > + > #ifdef HAVE_DWARF_SUPPORT > > static int kernel_get_module_dso(const char *module, struct dso **pdso) > @@ -2516,6 +2575,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, > struct probe_trace_point *tp; > int num_matched_functions; > int ret, i, j, skipped = 0; > + char *mod_name; > > map = get_target_map(pev->target, pev->uprobes); > if (!map) { > @@ -2600,9 +2660,19 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, > tp->realname = strdup_or_goto(sym->name, nomem_out); > > tp->retprobe = pp->retprobe; > - if (pev->target) > - tev->point.module = strdup_or_goto(pev->target, > - nomem_out); > + if (pev->target) { > + if (pev->uprobes) { > + tev->point.module = strdup_or_goto(pev->target, > + nomem_out); > + } else { > + mod_name = find_module_name(pev->target); > + tev->point.module = > + strdup(mod_name ? mod_name : pev->target); > + free(mod_name); > + if (!tev->point.module) > + goto nomem_out; > + } > + } > tev->uprobes = pev->uprobes; > tev->nargs = pev->nargs; > if (tev->nargs) { > -- > 1.9.1