Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf tools: Add util/debuginfo.[ch] files

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>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
6f1b6291 fb7fd2a1

+272 -210
+1
tools/perf/util/Build
··· 195 195 perf-$(CONFIG_DWARF) += probe-finder.o 196 196 perf-$(CONFIG_DWARF) += dwarf-aux.o 197 197 perf-$(CONFIG_DWARF) += dwarf-regs.o 198 + perf-$(CONFIG_DWARF) += debuginfo.o 198 199 199 200 perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 200 201 perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
+205
tools/perf/util/debuginfo.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * DWARF debug information handling code. Copied from probe-finder.c. 4 + * 5 + * Written by Masami Hiramatsu <mhiramat@redhat.com> 6 + */ 7 + 8 + #include <errno.h> 9 + #include <fcntl.h> 10 + #include <stdio.h> 11 + #include <stdlib.h> 12 + #include <string.h> 13 + #include <unistd.h> 14 + #include <linux/zalloc.h> 15 + 16 + #include "build-id.h" 17 + #include "dso.h" 18 + #include "debug.h" 19 + #include "debuginfo.h" 20 + #include "symbol.h" 21 + 22 + #ifdef HAVE_DEBUGINFOD_SUPPORT 23 + #include <elfutils/debuginfod.h> 24 + #endif 25 + 26 + /* Dwarf FL wrappers */ 27 + static char *debuginfo_path; /* Currently dummy */ 28 + 29 + static const Dwfl_Callbacks offline_callbacks = { 30 + .find_debuginfo = dwfl_standard_find_debuginfo, 31 + .debuginfo_path = &debuginfo_path, 32 + 33 + .section_address = dwfl_offline_section_address, 34 + 35 + /* We use this table for core files too. */ 36 + .find_elf = dwfl_build_id_find_elf, 37 + }; 38 + 39 + /* Get a Dwarf from offline image */ 40 + static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, 41 + const char *path) 42 + { 43 + GElf_Addr dummy; 44 + int fd; 45 + 46 + fd = open(path, O_RDONLY); 47 + if (fd < 0) 48 + return fd; 49 + 50 + dbg->dwfl = dwfl_begin(&offline_callbacks); 51 + if (!dbg->dwfl) 52 + goto error; 53 + 54 + dwfl_report_begin(dbg->dwfl); 55 + dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); 56 + if (!dbg->mod) 57 + goto error; 58 + 59 + dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); 60 + if (!dbg->dbg) 61 + goto error; 62 + 63 + dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy); 64 + 65 + dwfl_report_end(dbg->dwfl, NULL, NULL); 66 + 67 + return 0; 68 + error: 69 + if (dbg->dwfl) 70 + dwfl_end(dbg->dwfl); 71 + else 72 + close(fd); 73 + memset(dbg, 0, sizeof(*dbg)); 74 + 75 + return -ENOENT; 76 + } 77 + 78 + static struct debuginfo *__debuginfo__new(const char *path) 79 + { 80 + struct debuginfo *dbg = zalloc(sizeof(*dbg)); 81 + if (!dbg) 82 + return NULL; 83 + 84 + if (debuginfo__init_offline_dwarf(dbg, path) < 0) 85 + zfree(&dbg); 86 + if (dbg) 87 + pr_debug("Open Debuginfo file: %s\n", path); 88 + return dbg; 89 + } 90 + 91 + enum dso_binary_type distro_dwarf_types[] = { 92 + DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 93 + DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 94 + DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 95 + DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 96 + DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO, 97 + DSO_BINARY_TYPE__NOT_FOUND, 98 + }; 99 + 100 + struct debuginfo *debuginfo__new(const char *path) 101 + { 102 + enum dso_binary_type *type; 103 + char buf[PATH_MAX], nil = '\0'; 104 + struct dso *dso; 105 + struct debuginfo *dinfo = NULL; 106 + struct build_id bid; 107 + 108 + /* Try to open distro debuginfo files */ 109 + dso = dso__new(path); 110 + if (!dso) 111 + goto out; 112 + 113 + /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */ 114 + if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0) 115 + dso__set_build_id(dso, &bid); 116 + 117 + for (type = distro_dwarf_types; 118 + !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; 119 + type++) { 120 + if (dso__read_binary_type_filename(dso, *type, &nil, 121 + buf, PATH_MAX) < 0) 122 + continue; 123 + dinfo = __debuginfo__new(buf); 124 + } 125 + dso__put(dso); 126 + 127 + out: 128 + /* if failed to open all distro debuginfo, open given binary */ 129 + return dinfo ? : __debuginfo__new(path); 130 + } 131 + 132 + void debuginfo__delete(struct debuginfo *dbg) 133 + { 134 + if (dbg) { 135 + if (dbg->dwfl) 136 + dwfl_end(dbg->dwfl); 137 + free(dbg); 138 + } 139 + } 140 + 141 + /* For the kernel module, we need a special code to get a DIE */ 142 + int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, 143 + bool adjust_offset) 144 + { 145 + int n, i; 146 + Elf32_Word shndx; 147 + Elf_Scn *scn; 148 + Elf *elf; 149 + GElf_Shdr mem, *shdr; 150 + const char *p; 151 + 152 + elf = dwfl_module_getelf(dbg->mod, &dbg->bias); 153 + if (!elf) 154 + return -EINVAL; 155 + 156 + /* Get the number of relocations */ 157 + n = dwfl_module_relocations(dbg->mod); 158 + if (n < 0) 159 + return -ENOENT; 160 + /* Search the relocation related .text section */ 161 + for (i = 0; i < n; i++) { 162 + p = dwfl_module_relocation_info(dbg->mod, i, &shndx); 163 + if (strcmp(p, ".text") == 0) { 164 + /* OK, get the section header */ 165 + scn = elf_getscn(elf, shndx); 166 + if (!scn) 167 + return -ENOENT; 168 + shdr = gelf_getshdr(scn, &mem); 169 + if (!shdr) 170 + return -ENOENT; 171 + *offs = shdr->sh_addr; 172 + if (adjust_offset) 173 + *offs -= shdr->sh_offset; 174 + } 175 + } 176 + return 0; 177 + } 178 + 179 + #ifdef HAVE_DEBUGINFOD_SUPPORT 180 + int get_source_from_debuginfod(const char *raw_path, 181 + const char *sbuild_id, char **new_path) 182 + { 183 + debuginfod_client *c = debuginfod_begin(); 184 + const char *p = raw_path; 185 + int fd; 186 + 187 + if (!c) 188 + return -ENOMEM; 189 + 190 + fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id, 191 + 0, p, new_path); 192 + pr_debug("Search %s from debuginfod -> %d\n", p, fd); 193 + if (fd >= 0) 194 + close(fd); 195 + debuginfod_end(c); 196 + if (fd < 0) { 197 + pr_debug("Failed to find %s in debuginfod (%s)\n", 198 + raw_path, sbuild_id); 199 + return -ENOENT; 200 + } 201 + pr_debug("Got a source %s\n", *new_path); 202 + 203 + return 0; 204 + } 205 + #endif /* HAVE_DEBUGINFOD_SUPPORT */
+64
tools/perf/util/debuginfo.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + #ifndef _PERF_DEBUGINFO_H 3 + #define _PERF_DEBUGINFO_H 4 + 5 + #include <errno.h> 6 + #include <linux/compiler.h> 7 + 8 + #ifdef HAVE_DWARF_SUPPORT 9 + 10 + #include "dwarf-aux.h" 11 + 12 + /* debug information structure */ 13 + struct debuginfo { 14 + Dwarf *dbg; 15 + Dwfl_Module *mod; 16 + Dwfl *dwfl; 17 + Dwarf_Addr bias; 18 + const unsigned char *build_id; 19 + }; 20 + 21 + /* This also tries to open distro debuginfo */ 22 + struct debuginfo *debuginfo__new(const char *path); 23 + void debuginfo__delete(struct debuginfo *dbg); 24 + 25 + int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, 26 + bool adjust_offset); 27 + 28 + #else /* HAVE_DWARF_SUPPORT */ 29 + 30 + /* dummy debug information structure */ 31 + struct debuginfo { 32 + }; 33 + 34 + static inline struct debuginfo *debuginfo__new(const char *path __maybe_unused) 35 + { 36 + return NULL; 37 + } 38 + 39 + static inline void debuginfo__delete(struct debuginfo *dbg __maybe_unused) 40 + { 41 + } 42 + 43 + static inline int debuginfo__get_text_offset(struct debuginfo *dbg __maybe_unused, 44 + Dwarf_Addr *offs __maybe_unused, 45 + bool adjust_offset __maybe_unused) 46 + { 47 + return -EINVAL; 48 + } 49 + 50 + #endif /* HAVE_DWARF_SUPPORT */ 51 + 52 + #ifdef HAVE_DEBUGINFOD_SUPPORT 53 + int get_source_from_debuginfod(const char *raw_path, const char *sbuild_id, 54 + char **new_path); 55 + #else /* HAVE_DEBUGINFOD_SUPPORT */ 56 + static inline int get_source_from_debuginfod(const char *raw_path __maybe_unused, 57 + const char *sbuild_id __maybe_unused, 58 + char **new_path __maybe_unused) 59 + { 60 + return -ENOTSUP; 61 + } 62 + #endif /* HAVE_DEBUGINFOD_SUPPORT */ 63 + 64 + #endif /* _PERF_DEBUGINFO_H */
+1 -192
tools/perf/util/probe-finder.c
··· 23 23 #include "event.h" 24 24 #include "dso.h" 25 25 #include "debug.h" 26 + #include "debuginfo.h" 26 27 #include "intlist.h" 27 28 #include "strbuf.h" 28 29 #include "strlist.h" ··· 32 31 #include "probe-file.h" 33 32 #include "string2.h" 34 33 35 - #ifdef HAVE_DEBUGINFOD_SUPPORT 36 - #include <elfutils/debuginfod.h> 37 - #endif 38 - 39 34 /* Kprobe tracer basic type is up to u64 */ 40 35 #define MAX_BASIC_TYPE_BITS 64 41 - 42 - /* Dwarf FL wrappers */ 43 - static char *debuginfo_path; /* Currently dummy */ 44 - 45 - static const Dwfl_Callbacks offline_callbacks = { 46 - .find_debuginfo = dwfl_standard_find_debuginfo, 47 - .debuginfo_path = &debuginfo_path, 48 - 49 - .section_address = dwfl_offline_section_address, 50 - 51 - /* We use this table for core files too. */ 52 - .find_elf = dwfl_build_id_find_elf, 53 - }; 54 - 55 - /* Get a Dwarf from offline image */ 56 - static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, 57 - const char *path) 58 - { 59 - GElf_Addr dummy; 60 - int fd; 61 - 62 - fd = open(path, O_RDONLY); 63 - if (fd < 0) 64 - return fd; 65 - 66 - dbg->dwfl = dwfl_begin(&offline_callbacks); 67 - if (!dbg->dwfl) 68 - goto error; 69 - 70 - dwfl_report_begin(dbg->dwfl); 71 - dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); 72 - if (!dbg->mod) 73 - goto error; 74 - 75 - dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); 76 - if (!dbg->dbg) 77 - goto error; 78 - 79 - dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy); 80 - 81 - dwfl_report_end(dbg->dwfl, NULL, NULL); 82 - 83 - return 0; 84 - error: 85 - if (dbg->dwfl) 86 - dwfl_end(dbg->dwfl); 87 - else 88 - close(fd); 89 - memset(dbg, 0, sizeof(*dbg)); 90 - 91 - return -ENOENT; 92 - } 93 - 94 - static struct debuginfo *__debuginfo__new(const char *path) 95 - { 96 - struct debuginfo *dbg = zalloc(sizeof(*dbg)); 97 - if (!dbg) 98 - return NULL; 99 - 100 - if (debuginfo__init_offline_dwarf(dbg, path) < 0) 101 - zfree(&dbg); 102 - if (dbg) 103 - pr_debug("Open Debuginfo file: %s\n", path); 104 - return dbg; 105 - } 106 - 107 - enum dso_binary_type distro_dwarf_types[] = { 108 - DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 109 - DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 110 - DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 111 - DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 112 - DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO, 113 - DSO_BINARY_TYPE__NOT_FOUND, 114 - }; 115 - 116 - struct debuginfo *debuginfo__new(const char *path) 117 - { 118 - enum dso_binary_type *type; 119 - char buf[PATH_MAX], nil = '\0'; 120 - struct dso *dso; 121 - struct debuginfo *dinfo = NULL; 122 - struct build_id bid; 123 - 124 - /* Try to open distro debuginfo files */ 125 - dso = dso__new(path); 126 - if (!dso) 127 - goto out; 128 - 129 - /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */ 130 - if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0) 131 - dso__set_build_id(dso, &bid); 132 - 133 - for (type = distro_dwarf_types; 134 - !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; 135 - type++) { 136 - if (dso__read_binary_type_filename(dso, *type, &nil, 137 - buf, PATH_MAX) < 0) 138 - continue; 139 - dinfo = __debuginfo__new(buf); 140 - } 141 - dso__put(dso); 142 - 143 - out: 144 - /* if failed to open all distro debuginfo, open given binary */ 145 - return dinfo ? : __debuginfo__new(path); 146 - } 147 - 148 - void debuginfo__delete(struct debuginfo *dbg) 149 - { 150 - if (dbg) { 151 - if (dbg->dwfl) 152 - dwfl_end(dbg->dwfl); 153 - free(dbg); 154 - } 155 - } 156 36 157 37 /* 158 38 * Probe finder related functions ··· 1559 1677 return (ret < 0) ? ret : af.nvls; 1560 1678 } 1561 1679 1562 - /* For the kernel module, we need a special code to get a DIE */ 1563 - int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, 1564 - bool adjust_offset) 1565 - { 1566 - int n, i; 1567 - Elf32_Word shndx; 1568 - Elf_Scn *scn; 1569 - Elf *elf; 1570 - GElf_Shdr mem, *shdr; 1571 - const char *p; 1572 - 1573 - elf = dwfl_module_getelf(dbg->mod, &dbg->bias); 1574 - if (!elf) 1575 - return -EINVAL; 1576 - 1577 - /* Get the number of relocations */ 1578 - n = dwfl_module_relocations(dbg->mod); 1579 - if (n < 0) 1580 - return -ENOENT; 1581 - /* Search the relocation related .text section */ 1582 - for (i = 0; i < n; i++) { 1583 - p = dwfl_module_relocation_info(dbg->mod, i, &shndx); 1584 - if (strcmp(p, ".text") == 0) { 1585 - /* OK, get the section header */ 1586 - scn = elf_getscn(elf, shndx); 1587 - if (!scn) 1588 - return -ENOENT; 1589 - shdr = gelf_getshdr(scn, &mem); 1590 - if (!shdr) 1591 - return -ENOENT; 1592 - *offs = shdr->sh_addr; 1593 - if (adjust_offset) 1594 - *offs -= shdr->sh_offset; 1595 - } 1596 - } 1597 - return 0; 1598 - } 1599 - 1600 1680 /* Reverse search */ 1601 1681 int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr, 1602 1682 struct perf_probe_point *ppt) ··· 1853 2009 return (ret < 0) ? ret : lf.found; 1854 2010 } 1855 2011 1856 - #ifdef HAVE_DEBUGINFOD_SUPPORT 1857 - /* debuginfod doesn't require the comp_dir but buildid is required */ 1858 - static int get_source_from_debuginfod(const char *raw_path, 1859 - const char *sbuild_id, char **new_path) 1860 - { 1861 - debuginfod_client *c = debuginfod_begin(); 1862 - const char *p = raw_path; 1863 - int fd; 1864 - 1865 - if (!c) 1866 - return -ENOMEM; 1867 - 1868 - fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id, 1869 - 0, p, new_path); 1870 - pr_debug("Search %s from debuginfod -> %d\n", p, fd); 1871 - if (fd >= 0) 1872 - close(fd); 1873 - debuginfod_end(c); 1874 - if (fd < 0) { 1875 - pr_debug("Failed to find %s in debuginfod (%s)\n", 1876 - raw_path, sbuild_id); 1877 - return -ENOENT; 1878 - } 1879 - pr_debug("Got a source %s\n", *new_path); 1880 - 1881 - return 0; 1882 - } 1883 - #else 1884 - static inline int get_source_from_debuginfod(const char *raw_path __maybe_unused, 1885 - const char *sbuild_id __maybe_unused, 1886 - char **new_path __maybe_unused) 1887 - { 1888 - return -ENOTSUP; 1889 - } 1890 - #endif 1891 2012 /* 1892 2013 * Find a src file from a DWARF tag path. Prepend optional source path prefix 1893 2014 * and chop off leading directories that do not exist. Result is passed back as
+1 -18
tools/perf/util/probe-finder.h
··· 24 24 #ifdef HAVE_DWARF_SUPPORT 25 25 26 26 #include "dwarf-aux.h" 27 - 28 - /* TODO: export debuginfo data structure even if no dwarf support */ 29 - 30 - /* debug information structure */ 31 - struct debuginfo { 32 - Dwarf *dbg; 33 - Dwfl_Module *mod; 34 - Dwfl *dwfl; 35 - Dwarf_Addr bias; 36 - const unsigned char *build_id; 37 - }; 38 - 39 - /* This also tries to open distro debuginfo */ 40 - struct debuginfo *debuginfo__new(const char *path); 41 - void debuginfo__delete(struct debuginfo *dbg); 27 + #include "debuginfo.h" 42 28 43 29 /* Find probe_trace_events specified by perf_probe_event from debuginfo */ 44 30 int debuginfo__find_trace_events(struct debuginfo *dbg, ··· 34 48 /* Find a perf_probe_point from debuginfo */ 35 49 int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr, 36 50 struct perf_probe_point *ppt); 37 - 38 - int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, 39 - bool adjust_offset); 40 51 41 52 /* Find a line range */ 42 53 int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr);