mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 09:13:06 +00:00
libdrgn: save Elf handle for core dump
Currently, we close the Elf handle in drgn_set_core_dump() after we're done with it. However, we need the Elf handle in userspace_report_debug_info(), so we reopen it temporarily. We will also need it to support getting stack traces from core dumps, so we might as well keep it open. Note that we keep it even if we're using libkdumpfile because libkdumpfile doesn't seem to have an API to access ELF notes.
This commit is contained in:
parent
c243daed59
commit
75c74022ff
@ -82,7 +82,7 @@ void drgn_program_deinit(struct drgn_program *prog)
|
||||
if (prog->kdump_ctx)
|
||||
kdump_free(prog->kdump_ctx);
|
||||
#endif
|
||||
|
||||
elf_end(prog->core);
|
||||
if (prog->core_fd != -1)
|
||||
close(prog->core_fd);
|
||||
|
||||
@ -172,7 +172,6 @@ LIBDRGN_PUBLIC struct drgn_error *
|
||||
drgn_program_set_core_dump(struct drgn_program *prog, const char *path)
|
||||
{
|
||||
struct drgn_error *err;
|
||||
Elf *elf;
|
||||
GElf_Ehdr ehdr_mem, *ehdr;
|
||||
struct drgn_platform platform;
|
||||
bool is_64_bit, is_kdump;
|
||||
@ -196,7 +195,6 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path)
|
||||
if (err)
|
||||
goto out_fd;
|
||||
if (is_kdump) {
|
||||
set_kdump:
|
||||
err = drgn_program_set_kdump(prog);
|
||||
if (err)
|
||||
goto out_fd;
|
||||
@ -205,13 +203,13 @@ set_kdump:
|
||||
|
||||
elf_version(EV_CURRENT);
|
||||
|
||||
elf = elf_begin(prog->core_fd, ELF_C_READ, NULL);
|
||||
if (!elf) {
|
||||
prog->core = elf_begin(prog->core_fd, ELF_C_READ, NULL);
|
||||
if (!prog->core) {
|
||||
err = drgn_error_libelf();
|
||||
goto out_fd;
|
||||
}
|
||||
|
||||
ehdr = gelf_getehdr(elf, &ehdr_mem);
|
||||
ehdr = gelf_getehdr(prog->core, &ehdr_mem);
|
||||
if (!ehdr || ehdr->e_type != ET_CORE) {
|
||||
err = drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT,
|
||||
"not an ELF core file");
|
||||
@ -221,7 +219,7 @@ set_kdump:
|
||||
drgn_platform_from_elf(ehdr, &platform);
|
||||
is_64_bit = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
|
||||
|
||||
if (elf_getphdrnum(elf, &phnum) != 0) {
|
||||
if (elf_getphdrnum(prog->core, &phnum) != 0) {
|
||||
err = drgn_error_libelf();
|
||||
goto out_elf;
|
||||
}
|
||||
@ -234,7 +232,7 @@ set_kdump:
|
||||
for (i = 0; i < phnum; i++) {
|
||||
GElf_Phdr phdr_mem, *phdr;
|
||||
|
||||
phdr = gelf_getphdr(elf, i, &phdr_mem);
|
||||
phdr = gelf_getphdr(prog->core, i, &phdr_mem);
|
||||
if (!phdr) {
|
||||
err = drgn_error_libelf();
|
||||
goto out_elf;
|
||||
@ -250,7 +248,7 @@ set_kdump:
|
||||
GElf_Nhdr nhdr;
|
||||
size_t name_offset, desc_offset;
|
||||
|
||||
data = elf_getdata_rawchunk(elf, phdr->p_offset,
|
||||
data = elf_getdata_rawchunk(prog->core, phdr->p_offset,
|
||||
phdr->p_filesz,
|
||||
note_header_type(phdr));
|
||||
if (!data) {
|
||||
@ -315,8 +313,10 @@ set_kdump:
|
||||
#endif
|
||||
}
|
||||
if (use_libkdumpfile) {
|
||||
elf_end(elf);
|
||||
goto set_kdump;
|
||||
err = drgn_program_set_kdump(prog);
|
||||
if (err)
|
||||
goto out_elf;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,7 +333,7 @@ set_kdump:
|
||||
for (i = 0; i < phnum; i++) {
|
||||
GElf_Phdr phdr_mem, *phdr;
|
||||
|
||||
phdr = gelf_getphdr(elf, i, &phdr_mem);
|
||||
phdr = gelf_getphdr(prog->core, i, &phdr_mem);
|
||||
if (!phdr) {
|
||||
err = drgn_error_libelf();
|
||||
goto out_segments;
|
||||
@ -380,8 +380,6 @@ set_kdump:
|
||||
if (err)
|
||||
goto out_segments;
|
||||
}
|
||||
elf_end(elf);
|
||||
elf = NULL;
|
||||
|
||||
if (is_proc_kcore) {
|
||||
if (!vmcoreinfo_note) {
|
||||
@ -393,6 +391,8 @@ set_kdump:
|
||||
}
|
||||
prog->flags |= (DRGN_PROGRAM_IS_LINUX_KERNEL |
|
||||
DRGN_PROGRAM_IS_LIVE);
|
||||
elf_end(prog->core);
|
||||
prog->core = NULL;
|
||||
} else if (vmcoreinfo_note) {
|
||||
prog->flags |= DRGN_PROGRAM_IS_LINUX_KERNEL;
|
||||
}
|
||||
@ -407,7 +407,8 @@ out_segments:
|
||||
prog->file_segments = NULL;
|
||||
prog->num_file_segments = 0;
|
||||
out_elf:
|
||||
elf_end(elf);
|
||||
elf_end(prog->core);
|
||||
prog->core = NULL;
|
||||
out_fd:
|
||||
close(prog->core_fd);
|
||||
prog->core_fd = -1;
|
||||
@ -561,17 +562,9 @@ userspace_report_debug_info(struct drgn_program *prog,
|
||||
return drgn_error_create_os("dwfl_linux_proc_report",
|
||||
ret, NULL);
|
||||
}
|
||||
} else {
|
||||
Elf *elf;
|
||||
int ret;
|
||||
|
||||
elf = elf_begin(prog->core_fd, ELF_C_READ, NULL);
|
||||
if (!elf)
|
||||
return drgn_error_libelf();
|
||||
ret = dwfl_core_file_report(dindex->dwfl, elf, NULL);
|
||||
elf_end(elf);
|
||||
if (ret == -1)
|
||||
return drgn_error_libdwfl();
|
||||
} else if (dwfl_core_file_report(dindex->dwfl, prog->core,
|
||||
NULL) == -1) {
|
||||
return drgn_error_libdwfl();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -62,21 +62,26 @@ struct drgn_program {
|
||||
* Valid iff <tt>flags & DRGN_PROGRAM_IS_LINUX_KERNEL</tt>.
|
||||
*/
|
||||
struct vmcoreinfo vmcoreinfo;
|
||||
#ifdef WITH_LIBKDUMPFILE
|
||||
kdump_ctx_t *kdump_ctx;
|
||||
#endif
|
||||
/*
|
||||
* Valid iff <tt>!(flags & DRGN_PROGRAM_IS_LIVE)</tt>, unless the file
|
||||
* was a kdump file.
|
||||
*/
|
||||
Elf *core;
|
||||
int core_fd;
|
||||
/*
|
||||
* Valid iff
|
||||
* <tt>(flags & (DRGN_PROGRAM_IS_LINUX_KERNEL | DRGN_PROGRAM_IS_LIVE)) ==
|
||||
* DRGN_PROGRAM_IS_LIVE</tt>.
|
||||
*/
|
||||
pid_t pid;
|
||||
#ifdef WITH_LIBKDUMPFILE
|
||||
kdump_ctx_t *kdump_ctx;
|
||||
#endif
|
||||
struct drgn_dwarf_info_cache *_dicache;
|
||||
/* See @ref drgn_object_stack_trace_next_thread(). */
|
||||
const struct drgn_object *stack_trace_obj;
|
||||
/* See @ref drgn_object_stack_trace(). */
|
||||
struct drgn_error *stack_trace_err;
|
||||
int core_fd;
|
||||
enum drgn_program_flags flags;
|
||||
struct drgn_platform platform;
|
||||
bool has_platform;
|
||||
|
Loading…
Reference in New Issue
Block a user