diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-12-06 14:48:17 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-12-06 14:48:17 +0000 |
commit | 84ade58db7a58c310e42e55633c9d8d52fc5c994 (patch) | |
tree | 62e73fccfcd14dbc8f71e874338ac6901fd4adb0 /libbacktrace/elf.c | |
parent | 438167ebef173f07a6ec740c4bcd31c470caba0f (diff) | |
download | gcc-84ade58db7a58c310e42e55633c9d8d52fc5c994.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@205748 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libbacktrace/elf.c')
-rw-r--r-- | libbacktrace/elf.c | 54 |
1 files changed, 43 insertions, 11 deletions
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); |