mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 01:33:06 +00:00
libdrgn: debug_info: get address range of reported ET_EXEC files
When explicitly reporting a debugging information file for a userspace program, userspace_report_debug_info() currently always reports it with a load address range of [0, 0) (i.e., not actually loaded into the program). This is because for ET_DYN and ET_REL files, we have to determine the address range by inspecting the core dump or program state, which is a bit involved. However, ET_EXEC is much easier: we can get the address range from the segment headers. In fact, we already implemented this for vmlinux files, so we can reuse that with a modification to make it more permissive. ET_CORE debug info files don't make much sense, but libdwfl seems to treat a reported ET_CORE file the same as ET_EXEC (see dwfl_report_elf()), so we do, too. Unfortunately, most executables on modern Linux distributions are ET_DYN, but this will at least make testing easier. Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
c3f31e28f9
commit
4808ef72ee
@ -581,28 +581,52 @@ err:
|
|||||||
return DWARF_CB_ABORT;
|
return DWARF_CB_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct drgn_error *
|
||||||
|
userspace_report_elf_file(struct drgn_debug_info_load_state *load,
|
||||||
|
const char *path)
|
||||||
|
{
|
||||||
|
struct drgn_error *err;
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
Elf *elf;
|
||||||
|
err = open_elf_file(path, &fd, &elf);
|
||||||
|
if (err)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
GElf_Ehdr ehdr_mem, *ehdr;
|
||||||
|
ehdr = gelf_getehdr(elf, &ehdr_mem);
|
||||||
|
if (!ehdr) {
|
||||||
|
err = drgn_error_libelf();
|
||||||
|
goto err_close;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* We haven't implemented a way to get the load address for dynamically
|
||||||
|
* loaded or relocatable files, so for now we report those as unloaded.
|
||||||
|
*/
|
||||||
|
uint64_t start = 0, end = 0;
|
||||||
|
if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_CORE) {
|
||||||
|
err = elf_address_range(elf, 0, &start, &end);
|
||||||
|
if (err)
|
||||||
|
goto err_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
return drgn_debug_info_report_elf(load, path, fd, elf, start, end, NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
err_close:
|
||||||
|
elf_end(elf);
|
||||||
|
close(fd);
|
||||||
|
err:
|
||||||
|
return drgn_debug_info_report_error(load, path, NULL, err);
|
||||||
|
}
|
||||||
|
|
||||||
static struct drgn_error *
|
static struct drgn_error *
|
||||||
userspace_report_debug_info(struct drgn_debug_info_load_state *load)
|
userspace_report_debug_info(struct drgn_debug_info_load_state *load)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
|
|
||||||
for (size_t i = 0; i < load->num_paths; i++) {
|
for (size_t i = 0; i < load->num_paths; i++) {
|
||||||
int fd;
|
err = userspace_report_elf_file(load, load->paths[i]);
|
||||||
Elf *elf;
|
|
||||||
err = open_elf_file(load->paths[i], &fd, &elf);
|
|
||||||
if (err) {
|
|
||||||
err = drgn_debug_info_report_error(load, load->paths[i],
|
|
||||||
NULL, err);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We haven't implemented a way to get the load address for
|
|
||||||
* anything reported here, so for now we report it as unloaded.
|
|
||||||
*/
|
|
||||||
err = drgn_debug_info_report_elf(load, load->paths[i], fd, elf,
|
|
||||||
0, 0, NULL, NULL);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1338,10 +1362,9 @@ struct drgn_error *elf_address_range(Elf *elf, uint64_t bias,
|
|||||||
end = segment_end;
|
end = segment_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (start >= end) {
|
/* There were no loadable segments. */
|
||||||
return drgn_error_create(DRGN_ERROR_OTHER,
|
if (start >= end)
|
||||||
"ELF file has no loadable segments");
|
start = end = 0;
|
||||||
}
|
|
||||||
*start_ret = start;
|
*start_ret = start;
|
||||||
*end_ret = end;
|
*end_ret = end;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user