From 9d9c29a1aa9837578feb803888454a5844537ebf Mon Sep 17 00:00:00 2001 From: jakub Date: Wed, 14 Feb 2018 14:19:36 +0000 Subject: [PATCH] PR other/82368 * elf.c (EM_PPC64, EF_PPC64_ABI): Undefine and define. (struct elf_ppc64_opd_data): New type. (elf_initialize_syminfo): Add opd argument, handle symbols pointing into the PowerPC64 ELFv1 .opd section. (elf_add): Read .opd section on PowerPC64 ELFv1, pass pointer to structure with .opd data to elf_initialize_syminfo. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257658 138bc75d-0d04-0410-961f-82ee72b054a4 --- libbacktrace/ChangeLog | 10 ++++++++ libbacktrace/elf.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index 9ebce200e37..60e67a72de7 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,13 @@ +2018-02-14 Jakub Jelinek + + PR other/82368 + * elf.c (EM_PPC64, EF_PPC64_ABI): Undefine and define. + (struct elf_ppc64_opd_data): New type. + (elf_initialize_syminfo): Add opd argument, handle symbols + pointing into the PowerPC64 ELFv1 .opd section. + (elf_add): Read .opd section on PowerPC64 ELFv1, pass pointer + to structure with .opd data to elf_initialize_syminfo. + 2018-01-31 Ian Lance Taylor * elf.c (elf_add): Close descriptor if we use a debugfile. diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c index 3ee1dbeaf79..8ff3c47320e 100644 --- a/libbacktrace/elf.c +++ b/libbacktrace/elf.c @@ -165,6 +165,8 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *, #undef ELFDATA2MSB #undef EV_CURRENT #undef ET_DYN +#undef EM_PPC64 +#undef EF_PPC64_ABI #undef SHN_LORESERVE #undef SHN_XINDEX #undef SHN_UNDEF @@ -245,6 +247,9 @@ typedef struct { #define ET_DYN 3 +#define EM_PPC64 21 +#define EF_PPC64_ABI 3 + typedef struct { b_elf_word sh_name; /* Section name, index in string tbl */ b_elf_word sh_type; /* Type of section */ @@ -405,6 +410,20 @@ struct elf_syminfo_data size_t count; }; +/* Information about PowerPC64 ELFv1 .opd section. */ + +struct elf_ppc64_opd_data +{ + /* Address of the .opd section. */ + b_elf_addr addr; + /* Section data. */ + const char *data; + /* Size of the .opd section. */ + size_t size; + /* Corresponding section view. */ + struct backtrace_view view; +}; + /* Compute the CRC-32 of BUF/LEN. This uses the CRC used for .gnu_debuglink files. */ @@ -569,7 +588,8 @@ elf_initialize_syminfo (struct backtrace_state *state, const unsigned char *symtab_data, size_t symtab_size, const unsigned char *strtab, size_t strtab_size, backtrace_error_callback error_callback, - void *data, struct elf_syminfo_data *sdata) + void *data, struct elf_syminfo_data *sdata, + struct elf_ppc64_opd_data *opd) { size_t sym_count; const b_elf_sym *sym; @@ -620,7 +640,17 @@ elf_initialize_syminfo (struct backtrace_state *state, return 0; } elf_symbols[j].name = (const char *) strtab + sym->st_name; - elf_symbols[j].address = sym->st_value + base_address; + /* Special case PowerPC64 ELFv1 symbols in .opd section, if the symbol + is a function descriptor, read the actual code address from the + descriptor. */ + if (opd + && sym->st_value >= opd->addr + && sym->st_value < opd->addr + opd->size) + elf_symbols[j].address + = *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr)); + else + elf_symbols[j].address = sym->st_value; + elf_symbols[j].address += base_address; elf_symbols[j].size = sym->st_size; ++j; } @@ -2637,6 +2667,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, int debug_view_valid; unsigned int using_debug_view; uint16_t *zdebug_table; + struct elf_ppc64_opd_data opd_data, *opd; if (!debuginfo) { @@ -2655,6 +2686,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, debuglink_name = NULL; debuglink_crc = 0; debug_view_valid = 0; + opd = NULL; if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback, data, &ehdr_view)) @@ -2857,6 +2889,23 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, debuglink_crc = *(const uint32_t*)(debuglink_data + crc_offset); } } + + /* Read the .opd section on PowerPC64 ELFv1. */ + if (ehdr.e_machine == EM_PPC64 + && (ehdr.e_flags & EF_PPC64_ABI) < 2 + && shdr->sh_type == SHT_PROGBITS + && strcmp (name, ".opd") == 0) + { + if (!backtrace_get_view (state, descriptor, shdr->sh_offset, + shdr->sh_size, error_callback, data, + &opd_data.view)) + goto fail; + + opd = &opd_data; + opd->addr = shdr->sh_addr; + opd->data = (const char *) opd_data.view.data; + opd->size = shdr->sh_size; + } } if (symtab_shndx == 0) @@ -2898,7 +2947,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, if (!elf_initialize_syminfo (state, base_address, symtab_view.data, symtab_shdr->sh_size, strtab_view.data, strtab_shdr->sh_size, - error_callback, data, sdata)) + error_callback, data, sdata, opd)) { backtrace_free (state, sdata, sizeof *sdata, error_callback, data); goto fail; @@ -2951,6 +3000,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, buildid_view_valid = 0; } + if (opd) + { + backtrace_release_view (state, &opd->view, error_callback, data); + opd = NULL; + } + if (debuglink_name != NULL) { int d; @@ -3139,6 +3194,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, backtrace_release_view (state, &buildid_view, error_callback, data); if (debug_view_valid) backtrace_release_view (state, &debug_view, error_callback, data); + if (opd) + backtrace_release_view (state, &opd->view, error_callback, data); if (descriptor != -1) backtrace_close (descriptor, error_callback, data); return 0; -- 2.11.4.GIT