1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * DWARF debug information handling code. Copied from probe-finder.c.
14 #include <linux/zalloc.h>
19 #include "debuginfo.h"
22 #ifdef HAVE_DEBUGINFOD_SUPPORT
23 #include <elfutils/debuginfod.h>
26 /* Dwarf FL wrappers */
27 static char *debuginfo_path; /* Currently dummy */
29 static const Dwfl_Callbacks offline_callbacks = {
30 .find_debuginfo = dwfl_standard_find_debuginfo,
31 .debuginfo_path = &debuginfo_path,
33 .section_address = dwfl_offline_section_address,
35 /* We use this table for core files too. */
36 .find_elf = dwfl_build_id_find_elf,
39 /* Get a Dwarf from offline image */
40 static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
46 fd = open(path, O_RDONLY);
50 dbg->dwfl = dwfl_begin(&offline_callbacks);
54 dwfl_report_begin(dbg->dwfl);
55 dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
59 dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
63 dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy);
65 dwfl_report_end(dbg->dwfl, NULL, NULL);
73 memset(dbg, 0, sizeof(*dbg));
78 static struct debuginfo *__debuginfo__new(const char *path)
80 struct debuginfo *dbg = zalloc(sizeof(*dbg));
84 if (debuginfo__init_offline_dwarf(dbg, path) < 0)
87 pr_debug("Open Debuginfo file: %s\n", path);
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,
100 struct debuginfo *debuginfo__new(const char *path)
102 enum dso_binary_type *type;
103 char buf[PATH_MAX], nil = '\0';
105 struct debuginfo *dinfo = NULL;
108 /* Try to open distro debuginfo files */
109 dso = dso__new(path);
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);
117 for (type = distro_dwarf_types;
118 !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;
120 if (dso__read_binary_type_filename(dso, *type, &nil,
123 dinfo = __debuginfo__new(buf);
128 /* if failed to open all distro debuginfo, open given binary */
129 return dinfo ? : __debuginfo__new(path);
132 void debuginfo__delete(struct debuginfo *dbg)
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,
149 GElf_Shdr mem, *shdr;
152 elf = dwfl_module_getelf(dbg->mod, &dbg->bias);
156 /* Get the number of relocations */
157 n = dwfl_module_relocations(dbg->mod);
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);
168 shdr = gelf_getshdr(scn, &mem);
171 *offs = shdr->sh_addr;
173 *offs -= shdr->sh_offset;
179 #ifdef HAVE_DEBUGINFOD_SUPPORT
180 int get_source_from_debuginfod(const char *raw_path,
181 const char *sbuild_id, char **new_path)
183 debuginfod_client *c = debuginfod_begin();
184 const char *p = raw_path;
190 fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id,
192 pr_debug("Search %s from debuginfod -> %d\n", p, fd);
197 pr_debug("Failed to find %s in debuginfod (%s)\n",
198 raw_path, sbuild_id);
201 pr_debug("Got a source %s\n", *new_path);
205 #endif /* HAVE_DEBUGINFOD_SUPPORT */