1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * DWARF debug information handling code. Copied from probe-finder.c.
5 * Written by Masami Hiramatsu <mhiramat@redhat.com>
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 */