summaryrefslogtreecommitdiff
path: root/libbacktrace/elf.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-12-06 14:48:17 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-12-06 14:48:17 +0000
commit84ade58db7a58c310e42e55633c9d8d52fc5c994 (patch)
tree62e73fccfcd14dbc8f71e874338ac6901fd4adb0 /libbacktrace/elf.c
parent438167ebef173f07a6ec740c4bcd31c470caba0f (diff)
downloadgcc-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.c54
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);