mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 07:12:09 +00:00
perf buildid-cache: Scan and import user SDT events to probe cache
perf buildid-cache --add <binary> 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_<provider>:<event>=<event>". 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 <mhiramat@kernel.org> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com> Cc: Brendan Gregg <brendan.d.gregg@gmail.com> Cc: Hemant Kumar <hemant@linux.vnet.ibm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/146736025058.27797.13043265488541434502.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
8d993d9690
commit
6430a94ead
4 changed files with 101 additions and 3 deletions
|
@ -434,12 +434,15 @@ 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);
|
||||
if (!entry) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (buf[0] == '%')
|
||||
entry->sdt = true;
|
||||
entry->spev = strdup(buf + 1);
|
||||
if (entry->spev)
|
||||
ret = parse_perf_probe_command(buf + 1,
|
||||
|
@ -621,19 +624,79 @@ 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->node, &pcache->entries);
|
||||
}
|
||||
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) {
|
||||
list_del_init(&entry->node);
|
||||
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 stat st;
|
||||
struct iovec iov[3];
|
||||
const char *prefix = entry->sdt ? "%" : "#";
|
||||
int ret;
|
||||
/* Save stat for rollback */
|
||||
ret = fstat(fd, &st);
|
||||
if (ret < 0)
|
||||
return 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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue