From 0284b52ec9c54f2071f3f71cd994c2bf49b38639 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 6 Dec 2013 15:48:17 +0100 Subject: elf.c (ET_DYN): Undefine and define again. * elf.c (ET_DYN): Undefine and define again. (elf_add): Add exe argument, if true and ehdr.e_type is ET_DYN, return early -1 without closing the descriptor. (struct phdr_data): Add exe_descriptor. (phdr_callback): If pd->exe_descriptor is not -1, for very first call if dlpi_name is NULL just call elf_add with the exe_descriptor, otherwise backtrace_close the exe_descriptor if not -1. Adjust call to elf_add. (backtrace_initialize): Adjust call to elf_add. If it returns -1, set pd.exe_descriptor to descriptor, otherwise set it to -1. From-SVN: r205748 --- libbacktrace/ChangeLog | 13 ++++++++++++ libbacktrace/elf.c | 54 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 11 deletions(-) (limited to 'libbacktrace') diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index 43ad82a55db..0c41f0135c4 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,16 @@ +2013-12-06 Jakub Jelinek + + * elf.c (ET_DYN): Undefine and define again. + (elf_add): Add exe argument, if true and ehdr.e_type is ET_DYN, + return early -1 without closing the descriptor. + (struct phdr_data): Add exe_descriptor. + (phdr_callback): If pd->exe_descriptor is not -1, for very first + call if dlpi_name is NULL just call elf_add with the exe_descriptor, + otherwise backtrace_close the exe_descriptor if not -1. Adjust + call to elf_add. + (backtrace_initialize): Adjust call to elf_add. If it returns + -1, set pd.exe_descriptor to descriptor, otherwise set it to -1. + 2013-12-05 Ian Lance Taylor * alloc.c (backtrace_vector_finish): Add error_callback and data diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c index 3747c03079c..c7e646744dd 100644 --- a/libbacktrace/elf.c +++ b/libbacktrace/elf.c @@ -96,6 +96,7 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *, #undef ELFDATA2LSB #undef ELFDATA2MSB #undef EV_CURRENT +#undef ET_DYN #undef SHN_LORESERVE #undef SHN_XINDEX #undef SHN_UNDEF @@ -171,6 +172,8 @@ typedef struct { #define EV_CURRENT 1 +#define ET_DYN 3 + typedef struct { b_elf_word sh_name; /* Section name, index in string tbl */ b_elf_word sh_type; /* Type of section */ @@ -507,12 +510,16 @@ elf_syminfo (struct backtrace_state *state, uintptr_t addr, callback (data, addr, sym->name, sym->address, sym->size); } -/* Add the backtrace data for one ELF file. */ +/* Add the backtrace data for one ELF file. Returns 1 on success, + 0 on failure (in both cases descriptor is closed) or -1 if exe + is non-zero and the ELF file is ET_DYN, which tells the caller that + elf_add will need to be called on the descriptor again after + base_address is determined. */ static int elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address, backtrace_error_callback error_callback, void *data, - fileline *fileline_fn, int *found_sym, int *found_dwarf) + fileline *fileline_fn, int *found_sym, int *found_dwarf, int exe) { struct backtrace_view ehdr_view; b_elf_ehdr ehdr; @@ -591,6 +598,12 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address, goto fail; } + /* If the executable is ET_DYN, it is either a PIE, or we are running + directly a shared library with .interp. We need to wait for + dl_iterate_phdr in that case to determine the actual base_address. */ + if (exe && ehdr.e_type == ET_DYN) + return -1; + shoff = ehdr.e_shoff; shnum = ehdr.e_shnum; shstrndx = ehdr.e_shstrndx; @@ -847,6 +860,7 @@ struct phdr_data fileline *fileline_fn; int *found_sym; int *found_dwarf; + int exe_descriptor; }; /* Callback passed to dl_iterate_phdr. Load debug info from shared @@ -862,17 +876,32 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED, fileline elf_fileline_fn; int found_dwarf; - /* There is not much we can do if we don't have the module name. */ + /* There is not much we can do if we don't have the module name, + unless executable is ET_DYN, where we expect the very first + phdr_callback to be for the PIE. */ if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0') - return 0; + { + if (pd->exe_descriptor == -1) + return 0; + descriptor = pd->exe_descriptor; + pd->exe_descriptor = -1; + } + else + { + if (pd->exe_descriptor != -1) + { + backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data); + pd->exe_descriptor = -1; + } - descriptor = backtrace_open (info->dlpi_name, pd->error_callback, pd->data, - &does_not_exist); - if (descriptor < 0) - return 0; + descriptor = backtrace_open (info->dlpi_name, pd->error_callback, + pd->data, &does_not_exist); + if (descriptor < 0) + return 0; + } if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback, - pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf)) + pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf, 0)) { if (found_dwarf) { @@ -893,13 +922,15 @@ backtrace_initialize (struct backtrace_state *state, int descriptor, backtrace_error_callback error_callback, void *data, fileline *fileline_fn) { + int ret; int found_sym; int found_dwarf; fileline elf_fileline_fn; struct phdr_data pd; - if (!elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn, - &found_sym, &found_dwarf)) + ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn, + &found_sym, &found_dwarf, 1); + if (!ret) return 0; pd.state = state; @@ -908,6 +939,7 @@ backtrace_initialize (struct backtrace_state *state, int descriptor, pd.fileline_fn = &elf_fileline_fn; pd.found_sym = &found_sym; pd.found_dwarf = &found_dwarf; + pd.exe_descriptor = ret < 0 ? descriptor : -1; dl_iterate_phdr (phdr_callback, (void *) &pd); -- cgit v1.2.1