]> git.itanic.dy.fi Git - linux-stable/commitdiff
perf tools: Add util/debuginfo.[ch] files
authorNamhyung Kim <namhyung@kernel.org>
Thu, 9 Nov 2023 23:59:22 +0000 (15:59 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 10 Nov 2023 12:03:54 +0000 (09:03 -0300)
Split debuginfo data structure and related functions into a separate
file so that it can be used by other components than the probe-finder.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: linux-toolchains@vger.kernel.org
Cc: linux-trace-devel@vger.kernel.org
Link: https://lore.kernel.org/r/20231110000012.3538610-4-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/Build
tools/perf/util/debuginfo.c [new file with mode: 0644]
tools/perf/util/debuginfo.h [new file with mode: 0644]
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h

index 96058f949ec9fcef5781dcb09664ded909185e70..73e3f194f949f1dee39813388fda2df5ec016c28 100644 (file)
@@ -195,6 +195,7 @@ endif
 perf-$(CONFIG_DWARF) += probe-finder.o
 perf-$(CONFIG_DWARF) += dwarf-aux.o
 perf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_DWARF) += debuginfo.o
 
 perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
 perf-$(CONFIG_LOCAL_LIBUNWIND)    += unwind-libunwind-local.o
diff --git a/tools/perf/util/debuginfo.c b/tools/perf/util/debuginfo.c
new file mode 100644 (file)
index 0000000..19acf47
--- /dev/null
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DWARF debug information handling code.  Copied from probe-finder.c.
+ *
+ * Written by Masami Hiramatsu <mhiramat@redhat.com>
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/zalloc.h>
+
+#include "build-id.h"
+#include "dso.h"
+#include "debug.h"
+#include "debuginfo.h"
+#include "symbol.h"
+
+#ifdef HAVE_DEBUGINFOD_SUPPORT
+#include <elfutils/debuginfod.h>
+#endif
+
+/* Dwarf FL wrappers */
+static char *debuginfo_path;   /* Currently dummy */
+
+static const Dwfl_Callbacks offline_callbacks = {
+       .find_debuginfo = dwfl_standard_find_debuginfo,
+       .debuginfo_path = &debuginfo_path,
+
+       .section_address = dwfl_offline_section_address,
+
+       /* We use this table for core files too.  */
+       .find_elf = dwfl_build_id_find_elf,
+};
+
+/* Get a Dwarf from offline image */
+static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
+                                        const char *path)
+{
+       GElf_Addr dummy;
+       int fd;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return fd;
+
+       dbg->dwfl = dwfl_begin(&offline_callbacks);
+       if (!dbg->dwfl)
+               goto error;
+
+       dwfl_report_begin(dbg->dwfl);
+       dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
+       if (!dbg->mod)
+               goto error;
+
+       dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
+       if (!dbg->dbg)
+               goto error;
+
+       dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy);
+
+       dwfl_report_end(dbg->dwfl, NULL, NULL);
+
+       return 0;
+error:
+       if (dbg->dwfl)
+               dwfl_end(dbg->dwfl);
+       else
+               close(fd);
+       memset(dbg, 0, sizeof(*dbg));
+
+       return -ENOENT;
+}
+
+static struct debuginfo *__debuginfo__new(const char *path)
+{
+       struct debuginfo *dbg = zalloc(sizeof(*dbg));
+       if (!dbg)
+               return NULL;
+
+       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__MIXEDUP_UBUNTU_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;
+       struct build_id bid;
+
+       /* Try to open distro debuginfo files */
+       dso = dso__new(path);
+       if (!dso)
+               goto out;
+
+       /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */
+       if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0)
+               dso__set_build_id(dso, &bid);
+
+       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__put(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) {
+               if (dbg->dwfl)
+                       dwfl_end(dbg->dwfl);
+               free(dbg);
+       }
+}
+
+/* For the kernel module, we need a special code to get a DIE */
+int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
+                               bool adjust_offset)
+{
+       int n, i;
+       Elf32_Word shndx;
+       Elf_Scn *scn;
+       Elf *elf;
+       GElf_Shdr mem, *shdr;
+       const char *p;
+
+       elf = dwfl_module_getelf(dbg->mod, &dbg->bias);
+       if (!elf)
+               return -EINVAL;
+
+       /* Get the number of relocations */
+       n = dwfl_module_relocations(dbg->mod);
+       if (n < 0)
+               return -ENOENT;
+       /* Search the relocation related .text section */
+       for (i = 0; i < n; i++) {
+               p = dwfl_module_relocation_info(dbg->mod, i, &shndx);
+               if (strcmp(p, ".text") == 0) {
+                       /* OK, get the section header */
+                       scn = elf_getscn(elf, shndx);
+                       if (!scn)
+                               return -ENOENT;
+                       shdr = gelf_getshdr(scn, &mem);
+                       if (!shdr)
+                               return -ENOENT;
+                       *offs = shdr->sh_addr;
+                       if (adjust_offset)
+                               *offs -= shdr->sh_offset;
+               }
+       }
+       return 0;
+}
+
+#ifdef HAVE_DEBUGINFOD_SUPPORT
+int get_source_from_debuginfod(const char *raw_path,
+                              const char *sbuild_id, char **new_path)
+{
+       debuginfod_client *c = debuginfod_begin();
+       const char *p = raw_path;
+       int fd;
+
+       if (!c)
+               return -ENOMEM;
+
+       fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id,
+                               0, p, new_path);
+       pr_debug("Search %s from debuginfod -> %d\n", p, fd);
+       if (fd >= 0)
+               close(fd);
+       debuginfod_end(c);
+       if (fd < 0) {
+               pr_debug("Failed to find %s in debuginfod (%s)\n",
+                       raw_path, sbuild_id);
+               return -ENOENT;
+       }
+       pr_debug("Got a source %s\n", *new_path);
+
+       return 0;
+}
+#endif /* HAVE_DEBUGINFOD_SUPPORT */
diff --git a/tools/perf/util/debuginfo.h b/tools/perf/util/debuginfo.h
new file mode 100644 (file)
index 0000000..4d65b8c
--- /dev/null
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _PERF_DEBUGINFO_H
+#define _PERF_DEBUGINFO_H
+
+#include <errno.h>
+#include <linux/compiler.h>
+
+#ifdef HAVE_DWARF_SUPPORT
+
+#include "dwarf-aux.h"
+
+/* debug information structure */
+struct debuginfo {
+       Dwarf           *dbg;
+       Dwfl_Module     *mod;
+       Dwfl            *dwfl;
+       Dwarf_Addr      bias;
+       const unsigned char     *build_id;
+};
+
+/* This also tries to open distro debuginfo */
+struct debuginfo *debuginfo__new(const char *path);
+void debuginfo__delete(struct debuginfo *dbg);
+
+int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
+                              bool adjust_offset);
+
+#else /* HAVE_DWARF_SUPPORT */
+
+/* dummy debug information structure */
+struct debuginfo {
+};
+
+static inline struct debuginfo *debuginfo__new(const char *path __maybe_unused)
+{
+       return NULL;
+}
+
+static inline void debuginfo__delete(struct debuginfo *dbg __maybe_unused)
+{
+}
+
+static inline int debuginfo__get_text_offset(struct debuginfo *dbg __maybe_unused,
+                                            Dwarf_Addr *offs __maybe_unused,
+                                            bool adjust_offset __maybe_unused)
+{
+       return -EINVAL;
+}
+
+#endif /* HAVE_DWARF_SUPPORT */
+
+#ifdef HAVE_DEBUGINFOD_SUPPORT
+int get_source_from_debuginfod(const char *raw_path, const char *sbuild_id,
+                              char **new_path);
+#else /* HAVE_DEBUGINFOD_SUPPORT */
+static inline int get_source_from_debuginfod(const char *raw_path __maybe_unused,
+                                            const char *sbuild_id __maybe_unused,
+                                            char **new_path __maybe_unused)
+{
+       return -ENOTSUP;
+}
+#endif /* HAVE_DEBUGINFOD_SUPPORT */
+
+#endif /* _PERF_DEBUGINFO_H */
index f171360b0ef4db06eb0ff760619996cf58339943..8d3dd85f9ff4ce7c93071956206fab3c48434a97 100644 (file)
@@ -23,6 +23,7 @@
 #include "event.h"
 #include "dso.h"
 #include "debug.h"
+#include "debuginfo.h"
 #include "intlist.h"
 #include "strbuf.h"
 #include "strlist.h"
 #include "probe-file.h"
 #include "string2.h"
 
-#ifdef HAVE_DEBUGINFOD_SUPPORT
-#include <elfutils/debuginfod.h>
-#endif
-
 /* Kprobe tracer basic type is up to u64 */
 #define MAX_BASIC_TYPE_BITS    64
 
-/* Dwarf FL wrappers */
-static char *debuginfo_path;   /* Currently dummy */
-
-static const Dwfl_Callbacks offline_callbacks = {
-       .find_debuginfo = dwfl_standard_find_debuginfo,
-       .debuginfo_path = &debuginfo_path,
-
-       .section_address = dwfl_offline_section_address,
-
-       /* We use this table for core files too.  */
-       .find_elf = dwfl_build_id_find_elf,
-};
-
-/* Get a Dwarf from offline image */
-static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
-                                        const char *path)
-{
-       GElf_Addr dummy;
-       int fd;
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0)
-               return fd;
-
-       dbg->dwfl = dwfl_begin(&offline_callbacks);
-       if (!dbg->dwfl)
-               goto error;
-
-       dwfl_report_begin(dbg->dwfl);
-       dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
-       if (!dbg->mod)
-               goto error;
-
-       dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
-       if (!dbg->dbg)
-               goto error;
-
-       dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy);
-
-       dwfl_report_end(dbg->dwfl, NULL, NULL);
-
-       return 0;
-error:
-       if (dbg->dwfl)
-               dwfl_end(dbg->dwfl);
-       else
-               close(fd);
-       memset(dbg, 0, sizeof(*dbg));
-
-       return -ENOENT;
-}
-
-static struct debuginfo *__debuginfo__new(const char *path)
-{
-       struct debuginfo *dbg = zalloc(sizeof(*dbg));
-       if (!dbg)
-               return NULL;
-
-       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__MIXEDUP_UBUNTU_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;
-       struct build_id bid;
-
-       /* Try to open distro debuginfo files */
-       dso = dso__new(path);
-       if (!dso)
-               goto out;
-
-       /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */
-       if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0)
-               dso__set_build_id(dso, &bid);
-
-       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__put(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) {
-               if (dbg->dwfl)
-                       dwfl_end(dbg->dwfl);
-               free(dbg);
-       }
-}
-
 /*
  * Probe finder related functions
  */
@@ -1677,44 +1559,6 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
        return (ret < 0) ? ret : af.nvls;
 }
 
-/* For the kernel module, we need a special code to get a DIE */
-int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
-                               bool adjust_offset)
-{
-       int n, i;
-       Elf32_Word shndx;
-       Elf_Scn *scn;
-       Elf *elf;
-       GElf_Shdr mem, *shdr;
-       const char *p;
-
-       elf = dwfl_module_getelf(dbg->mod, &dbg->bias);
-       if (!elf)
-               return -EINVAL;
-
-       /* Get the number of relocations */
-       n = dwfl_module_relocations(dbg->mod);
-       if (n < 0)
-               return -ENOENT;
-       /* Search the relocation related .text section */
-       for (i = 0; i < n; i++) {
-               p = dwfl_module_relocation_info(dbg->mod, i, &shndx);
-               if (strcmp(p, ".text") == 0) {
-                       /* OK, get the section header */
-                       scn = elf_getscn(elf, shndx);
-                       if (!scn)
-                               return -ENOENT;
-                       shdr = gelf_getshdr(scn, &mem);
-                       if (!shdr)
-                               return -ENOENT;
-                       *offs = shdr->sh_addr;
-                       if (adjust_offset)
-                               *offs -= shdr->sh_offset;
-               }
-       }
-       return 0;
-}
-
 /* Reverse search */
 int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr,
                                struct perf_probe_point *ppt)
@@ -2009,41 +1853,6 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
        return (ret < 0) ? ret : lf.found;
 }
 
-#ifdef HAVE_DEBUGINFOD_SUPPORT
-/* debuginfod doesn't require the comp_dir but buildid is required */
-static int get_source_from_debuginfod(const char *raw_path,
-                               const char *sbuild_id, char **new_path)
-{
-       debuginfod_client *c = debuginfod_begin();
-       const char *p = raw_path;
-       int fd;
-
-       if (!c)
-               return -ENOMEM;
-
-       fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id,
-                               0, p, new_path);
-       pr_debug("Search %s from debuginfod -> %d\n", p, fd);
-       if (fd >= 0)
-               close(fd);
-       debuginfod_end(c);
-       if (fd < 0) {
-               pr_debug("Failed to find %s in debuginfod (%s)\n",
-                       raw_path, sbuild_id);
-               return -ENOENT;
-       }
-       pr_debug("Got a source %s\n", *new_path);
-
-       return 0;
-}
-#else
-static inline int get_source_from_debuginfod(const char *raw_path __maybe_unused,
-                               const char *sbuild_id __maybe_unused,
-                               char **new_path __maybe_unused)
-{
-       return -ENOTSUP;
-}
-#endif
 /*
  * Find a src file from a DWARF tag path. Prepend optional source path prefix
  * and chop off leading directories that do not exist. Result is passed back as
index 8bc1c80d3c1c0b616659a10183d9f463c1008ffe..3add5ff516e12de544b38cf5e48a45f922b0dee2 100644 (file)
@@ -24,21 +24,7 @@ static inline int is_c_varname(const char *name)
 #ifdef HAVE_DWARF_SUPPORT
 
 #include "dwarf-aux.h"
-
-/* TODO: export debuginfo data structure even if no dwarf support */
-
-/* debug information structure */
-struct debuginfo {
-       Dwarf           *dbg;
-       Dwfl_Module     *mod;
-       Dwfl            *dwfl;
-       Dwarf_Addr      bias;
-       const unsigned char     *build_id;
-};
-
-/* This also tries to open distro debuginfo */
-struct debuginfo *debuginfo__new(const char *path);
-void debuginfo__delete(struct debuginfo *dbg);
+#include "debuginfo.h"
 
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
 int debuginfo__find_trace_events(struct debuginfo *dbg,
@@ -49,9 +35,6 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
 int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr,
                                struct perf_probe_point *ppt);
 
-int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
-                              bool adjust_offset);
-
 /* Find a line range */
 int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr);