From 012b950b3741625a8766e9558ace6f3272c58de5 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 17 Apr 2018 07:04:02 -0700 Subject: [PATCH] Copy changes from GCC: 2018-04-17 Ian Lance Taylor * backtrace.c (backtrace_full): When testing whether we can allocate memory, call mmap directly, and munmap the memory. 2018-04-04 Jakub Jelinek PR other/85161 * elf.c (elf_zlib_fetch): Fix up predefined macro names in test for big endian, only use 32-bit loads if endianity macros are predefined and indicate big or little endian. 2018-02-15 Jakub Jelinek PR other/82368 * elf.c (SHT_PROGBITS): Undefine and define. 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-19 Tony Reix * xcoff.c (xcoff_incl_compare): New function. (xcoff_incl_search): New function. (xcoff_process_linenos): Use bsearch to find include file. (xcoff_initialize_fileline): Sort include file information. Fixes #13 --- backtrace.c | 44 +++++++++++++++++++++++-------- elf.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++--- xcoff.c | 52 ++++++++++++++++++++++++++++++------- 3 files changed, 146 insertions(+), 24 deletions(-) diff --git a/backtrace.c b/backtrace.c index f8e3dc5..319edcf 100644 --- a/backtrace.c +++ b/backtrace.c @@ -32,12 +32,26 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" +#include #include +#if !BACKTRACE_USES_MALLOC +#include +#endif + #include "unwind.h" #include "backtrace.h" +#include "backtrace-supported.h" #include "internal.h" +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + /* The main backtrace_full routine. */ /* Data passed through _Unwind_Backtrace. */ @@ -104,7 +118,6 @@ backtrace_full (struct backtrace_state *state, int skip, backtrace_error_callback error_callback, void *data) { struct backtrace_data bdata; - void *p; bdata.skip = skip + 1; bdata.state = state; @@ -113,16 +126,25 @@ backtrace_full (struct backtrace_state *state, int skip, bdata.data = data; bdata.ret = 0; - /* If we can't allocate any memory at all, don't try to produce - file/line information. */ - p = backtrace_alloc (state, 4096, NULL, NULL); - if (p == NULL) - bdata.can_alloc = 0; - else - { - backtrace_free (state, p, 4096, NULL, NULL); - bdata.can_alloc = 1; - } +#if !BACKTRACE_USES_MALLOC + { + size_t pagesize; + void *page; + + /* If we can't allocate any memory at all, don't try to produce + file/line information. */ + pagesize = getpagesize (); + page = mmap (NULL, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (page == MAP_FAILED) + bdata.can_alloc = 0; + else + { + munmap (page, pagesize); + bdata.can_alloc = 1; + } + } +#endif _Unwind_Backtrace (unwind, &bdata); return bdata.ret; diff --git a/elf.c b/elf.c index 3ee1dbe..0fd5e6f 100644 --- a/elf.c +++ b/elf.c @@ -165,9 +165,12 @@ 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 +#undef SHT_PROGBITS #undef SHT_SYMTAB #undef SHT_STRTAB #undef SHT_DYNSYM @@ -245,6 +248,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 */ @@ -262,6 +268,7 @@ typedef struct { #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ +#define SHT_PROGBITS 1 #define SHT_SYMTAB 2 #define SHT_STRTAB 3 #define SHT_DYNSYM 11 @@ -405,6 +412,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 +590,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 +642,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; } @@ -1054,12 +1086,19 @@ elf_zlib_fetch (const unsigned char **ppin, const unsigned char *pinend, return 0; } +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \ + && defined(__ORDER_BIG_ENDIAN__) \ + && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ \ + || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) /* We've ensured that PIN is aligned. */ next = *(const uint32_t *)pin; -#if __BYTE_ORDER == __ORDER_BIG_ENDIAN +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ next = __builtin_bswap32 (next); #endif +#else + next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24); +#endif val |= (uint64_t)next << bits; bits += 32; @@ -2637,6 +2676,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 +2695,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 +2898,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 +2956,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 +3009,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 +3203,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; diff --git a/xcoff.c b/xcoff.c index 4b2fdad..1ae001d 100644 --- a/xcoff.c +++ b/xcoff.c @@ -760,6 +760,40 @@ xcoff_fileline (struct backtrace_state *state, uintptr_t pc, return callback (data, pc, NULL, 0, NULL); } +/* Compare struct xcoff_incl for qsort. */ + +static int +xcoff_incl_compare (const void *v1, const void *v2) +{ + const struct xcoff_incl *in1 = (const struct xcoff_incl *) v1; + const struct xcoff_incl *in2 = (const struct xcoff_incl *) v2; + + if (in1->begin < in2->begin) + return -1; + else if (in1->begin > in2->begin) + return 1; + else + return 0; +} + +/* Find a lnnoptr in an include file. */ + +static int +xcoff_incl_search (const void *vkey, const void *ventry) +{ + const uintptr_t *key = (const uintptr_t *) vkey; + const struct xcoff_incl *entry = (const struct xcoff_incl *) ventry; + uintptr_t lnno; + + lnno = *key; + if (lnno < entry->begin) + return -1; + else if (lnno > entry->end) + return 1; + else + return 0; +} + /* Add a new mapping to the vector of line mappings that we are building. Returns 1 on success, 0 on failure. */ @@ -809,7 +843,6 @@ xcoff_process_linenos (struct backtrace_state *state, uintptr_t base_address, uintptr_t pc; uint32_t lnno; int begincl; - size_t i; aux = (const b_xcoff_auxent *) (fsym + 1); lnnoptr = aux->x_fcn.x_lnnoptr; @@ -839,15 +872,13 @@ xcoff_process_linenos (struct backtrace_state *state, uintptr_t base_address, /* If part of a function other than the beginning comes from an include file, the line numbers are absolute, rather than relative to the beginning of the function. */ - for (i = 0; i < vec->count; ++i) - { - incl = (struct xcoff_incl *) vec->vec.base + i; - if (incl->begin <= lnnoptr && lnnoptr <= incl->end) - break; - } + incl = (struct xcoff_incl *) bsearch (&lnnoptr, vec->vec.base, + vec->count, + sizeof (struct xcoff_incl), + xcoff_incl_search); if (begincl == -1) - begincl = (i < vec->count); - if (i < vec->count) + begincl = incl != NULL; + if (incl != NULL) { filename = incl->filename; if (begincl == 1) @@ -935,6 +966,9 @@ xcoff_initialize_fileline (struct backtrace_state *state, i += asym->n_numaux; } + backtrace_qsort (vec.vec.base, vec.count, + sizeof (struct xcoff_incl), xcoff_incl_compare); + filename = NULL; fsym = NULL; for (i = 0; i < nsyms; ++i)