From a15ad2f5360c821f030c53266ebf467738249c68 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 6 Feb 2014 05:32:27 +0000 Subject: [PATCH] perf probe: Support distro-style debuginfo for uprobe Support distro-style debuginfo supported by dso for setting uprobes. Note that this tries to find a debuginfo file based on the real path of the target binary. If the debuginfo is not correctly installed on the system, this can not find it. Signed-off-by: Masami Hiramatsu Cc: David Ahern Cc: "David A. Long" Cc: Ingo Molnar Cc: Namhyung Kim Cc: Oleg Nesterov Cc: Srikar Dronamraju Cc: Steven Rostedt Cc: yrl.pp-manager.tt@hitachi.com Link: http://lkml.kernel.org/r/20140206053227.29635.54434.stgit@kbuild-fedora.yrl.intra.hitachi.co.jp Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 9 +++----- tools/perf/util/probe-finder.c | 41 ++++++++++++++++++++++++++++++++-- tools/perf/util/probe-finder.h | 1 + 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 42bec67aaa38..0d1542f33d87 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -256,17 +256,14 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) } #ifdef HAVE_DWARF_SUPPORT + /* Open new debuginfo of given module */ static struct debuginfo *open_debuginfo(const char *module) { - const char *path; + const char *path = module; - /* A file path -- this is an offline module */ - if (module && strchr(module, '/')) - path = module; - else { + if (!module || !strchr(module, '/')) { path = kernel_get_module_path(module); - if (!path) { pr_err("Failed to find path of %s module.\n", module ?: "kernel"); diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 4f6e277c457c..df0238654698 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -34,6 +34,7 @@ #include #include "event.h" +#include "dso.h" #include "debug.h" #include "intlist.h" #include "util.h" @@ -89,7 +90,7 @@ error: return -ENOENT; } -struct debuginfo *debuginfo__new(const char *path) +static struct debuginfo *__debuginfo__new(const char *path) { struct debuginfo *dbg = zalloc(sizeof(*dbg)); if (!dbg) @@ -97,10 +98,46 @@ struct debuginfo *debuginfo__new(const char *path) if (debuginfo__init_offline_dwarf(dbg, path) < 0) zfree(&dbg); - + if (dbg) + pr_debug("Open Debuginfo file: %s\n", path); return dbg; } +enum dso_binary_type distro_dwarf_types[] = { + DSO_BINARY_TYPE__FEDORA_DEBUGINFO, + DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, + DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, + DSO_BINARY_TYPE__BUILDID_DEBUGINFO, + DSO_BINARY_TYPE__NOT_FOUND, +}; + +struct debuginfo *debuginfo__new(const char *path) +{ + enum dso_binary_type *type; + char buf[PATH_MAX], nil = '\0'; + struct dso *dso; + struct debuginfo *dinfo = NULL; + + /* Try to open distro debuginfo files */ + dso = dso__new(path); + if (!dso) + goto out; + + for (type = distro_dwarf_types; + !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; + type++) { + if (dso__read_binary_type_filename(dso, *type, &nil, + buf, PATH_MAX) < 0) + continue; + dinfo = __debuginfo__new(buf); + } + dso__delete(dso); + +out: + /* if failed to open all distro debuginfo, open given binary */ + return dinfo ? : __debuginfo__new(path); +} + void debuginfo__delete(struct debuginfo *dbg) { if (dbg) { diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 3fc597365ce6..92590b2c7e1c 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -30,6 +30,7 @@ struct debuginfo { Dwarf_Addr bias; }; +/* This also tries to open distro debuginfo */ extern struct debuginfo *debuginfo__new(const char *path); extern void debuginfo__delete(struct debuginfo *dbg);