Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753400AbcD0Ucb (ORCPT ); Wed, 27 Apr 2016 16:32:31 -0400 Received: from e28smtp03.in.ibm.com ([125.16.236.3]:46432 "EHLO e28smtp03.in.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752561AbcD0Uca (ORCPT ); Wed, 27 Apr 2016 16:32:30 -0400 X-IBM-Helo: d28dlp03.in.ibm.com X-IBM-MailFrom: hemant@linux.vnet.ibm.com X-IBM-RcptTo: linux-kernel@vger.kernel.org Message-ID: <572121D0.1060503@linux.vnet.ibm.com> Date: Thu, 28 Apr 2016 02:02:16 +0530 From: Hemant Kumar User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Masami Hiramatsu , Arnaldo Carvalho de Melo CC: linux-kernel@vger.kernel.org, Namhyung Kim , Peter Zijlstra , Ingo Molnar , Ananth N Mavinakayanahalli Subject: Re: [PATCH perf/core v5 10/15] perf buildid-cache: Scan and import user SDT events to probe cache References: <20160427183701.23446.15293.stgit@devbox> <20160427183839.23446.79864.stgit@devbox> In-Reply-To: <20160427183839.23446.79864.stgit@devbox> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16042720-0009-0000-0000-00000C665E78 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7533 Lines: 234 On 04/28/2016 12:08 AM, Masami Hiramatsu wrote: > From: Masami Hiramatsu > > perf buildid-cache --add scans given binary and add > the SDT events to probe cache. "sdt_" prefix is appended for > all SDT providers to avoid event-name clash with other pre-defined > events. It is possible to use the cached SDT events as other cached > events, via perf probe --add "sdt_:=". > > e.g. > ---- > # perf buildid-cache --add /lib/libc-2.17.so > # perf probe --cache --list | head -n 5 > /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392): > sdt_libc:setjmp=setjmp > sdt_libc:longjmp=longjmp > sdt_libc:longjmp_target=longjmp_target > sdt_libc:memory_heap_new=memory_heap_new > # perf probe -x /usr/lib/libc-2.17.so \ > -a sdt_libc:memory_heap_new=memory_heap_new > Added new event: > sdt_libc:memory_heap_new (on memory_heap_new > in /usr/lib/libc-2.17.so) > > You can now use it in all perf tools, such as: > > perf record -e sdt_libc:memory_heap_new -aR sleep 1 > > # perf probe -l > sdt_libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so) > ---- > > Note that SDT event entries in probe-cache file is somewhat different > from normal cached events. Normal one starts with "#", but SDTs are > starting with "%". > > Signed-off-by: Masami Hiramatsu > Signed-off-by: Masami Hiramatsu > --- > Changes in v4: > - Fix a bug to copy correct group name to entries. > - Fix to consolidate same-name entries. Acked-by: Hemant Kumar > --- > tools/perf/util/build-id.c | 27 +++++++++++++++-- > tools/perf/util/probe-file.c | 67 ++++++++++++++++++++++++++++++++++++++++-- > tools/perf/util/probe-file.h | 2 + > 3 files changed, 90 insertions(+), 6 deletions(-) > > diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c > index a7da315..49a467b9 100644 > --- a/tools/perf/util/build-id.c > +++ b/tools/perf/util/build-id.c > @@ -17,6 +17,7 @@ > #include "tool.h" > #include "header.h" > #include "vdso.h" > +#include "probe-file.h" > > > static bool no_buildid_cache; > @@ -490,6 +491,23 @@ int build_id_cache__list_build_ids(const char *pathname, > return ret; > } > > +#ifdef HAVE_LIBELF_SUPPORT > +static void build_id_cache__add_sdt_cache(const char *sbuild_id, > + const char *realname) > +{ > + struct probe_cache *cache; > + > + cache = probe_cache__new(sbuild_id); > + if (!cache) > + return; > + if (probe_cache__scan_sdt(cache, realname) >= 0) > + probe_cache__commit(cache); > + probe_cache__delete(cache); > +} > +#else > +#define build_id_cache__add_sdt_cache(sbuild_id, realname) do { } while (0) > +#endif > + > int build_id_cache__add_s(const char *sbuild_id, const char *name, > bool is_kallsyms, bool is_vdso) > { > @@ -533,20 +551,23 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name, > goto out_free; > } > > + /* Make a symbolic link */ > if (!build_id_cache__linkname(sbuild_id, linkname, size)) > goto out_free; > + > tmp = strrchr(linkname, '/'); > *tmp = '\0'; > - > if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) > goto out_free; > - > *tmp = '/'; > tmp = dir_name + strlen(buildid_dir) - 5; > memcpy(tmp, "../..", 5); > - > if (symlink(tmp, linkname) == 0) > err = 0; > + > + /* Update SDT cache */ > + build_id_cache__add_sdt_cache(sbuild_id, realname); > + > out_free: > if (!is_kallsyms) > free(realname); > diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c > index 46f006e..c10a647 100644 > --- a/tools/perf/util/probe-file.c > +++ b/tools/perf/util/probe-file.c > @@ -428,9 +428,12 @@ static int probe_cache__load(struct probe_cache *pcache) > p = strchr(buf, '\n'); > if (p) > *p = '\0'; > - if (buf[0] == '#') { /* #perf_probe_event */ > + /* #perf_probe_event or %sdt_event */ > + if (buf[0] == '#' || buf[0] == '%') { > entry = probe_cache_entry__new(NULL); > entry->spev = strdup(buf + 1); > + if (buf[0] == '%') > + entry->sdt = true; > ret = parse_perf_probe_command(buf + 1, &entry->pev); > if (!entry->spev || ret < 0) { > probe_cache_entry__delete(entry); > @@ -602,14 +605,72 @@ out_err: > return ret; > } > > +static unsigned long long sdt_note__get_addr(struct sdt_note *note) > +{ > + return note->bit32 ? (unsigned long long)note->addr.a32[0] > + : (unsigned long long)note->addr.a64[0]; > +} > + > +int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname) > +{ > + struct probe_cache_entry *entry = NULL; > + struct list_head sdtlist; > + struct sdt_note *note; > + char *buf; > + char sdtgrp[64]; > + int ret; > + > + INIT_LIST_HEAD(&sdtlist); > + ret = get_sdt_note_list(&sdtlist, pathname); > + if (ret < 0) { > + pr_debug("Failed to get sdt note: %d\n", ret); > + return ret; > + } > + list_for_each_entry(note, &sdtlist, note_list) { > + ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider); > + if (ret < 0) > + break; > + /* Try to find same-name entry */ > + entry = probe_cache__find_by_name(pcache, sdtgrp, note->name); > + if (!entry) { > + entry = probe_cache_entry__new(NULL); > + if (!entry) { > + ret = -ENOMEM; > + break; > + } > + entry->sdt = true; > + ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp, > + note->name, note->name); > + if (ret < 0) > + break; > + entry->pev.event = strdup(note->name); > + entry->pev.group = strdup(sdtgrp); > + list_add_tail(&entry->list, &pcache->list); > + } > + ret = asprintf(&buf, "p:%s/%s %s:0x%llx", > + sdtgrp, note->name, pathname, > + sdt_note__get_addr(note)); > + if (ret < 0) > + break; > + strlist__add(entry->tevlist, buf); > + free(buf); > + entry = NULL; > + } > + if (entry) > + probe_cache_entry__delete(entry); > + cleanup_sdt_note_list(&sdtlist); > + return ret; > +} > + > static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd) > { > struct str_node *snode; > struct iovec iov[3]; > + const char *prefix = entry->sdt ? "%" : "#"; > int ret; > > - pr_debug("Writing cache: #%s\n", entry->spev); > - iov[0].iov_base = (void *)"#"; iov[0].iov_len = 1; > + pr_debug("Writing cache: %s%s\n", prefix, entry->spev); > + iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1; > iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev); > iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1; > ret = writev(fd, iov, 3); > diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h > index e6fd9b9..93aa193 100644 > --- a/tools/perf/util/probe-file.h > +++ b/tools/perf/util/probe-file.h > @@ -8,6 +8,7 @@ > /* Cache of probe definitions */ > struct probe_cache_entry { > struct list_head list; > + bool sdt; > struct perf_probe_event pev; > char *spev; > struct strlist *tevlist; > @@ -35,6 +36,7 @@ struct probe_cache *probe_cache__new(const char *target); > int probe_cache__add_entry(struct probe_cache *pcache, > struct perf_probe_event *pev, > struct probe_trace_event *tevs, int ntevs); > +int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname); > int probe_cache__commit(struct probe_cache *pcache); > void probe_cache__delete(struct probe_cache *pcache); > int probe_cache__remove_entries(struct probe_cache *pcache, > -- Thanks, Hemant Kumar