Commit 012b950b by Ian Lance Taylor

Copy changes from GCC:

2018-04-17 Ian Lance Taylor <iant@golang.org> * backtrace.c (backtrace_full): When testing whether we can allocate memory, call mmap directly, and munmap the memory. 2018-04-04 Jakub Jelinek <jakub@redhat.com> 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 <jakub@redhat.com> PR other/82368 * elf.c (SHT_PROGBITS): Undefine and define. 2018-02-14 Jakub Jelinek <jakub@redhat.com> 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 <tony.reix@atos.net> * 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
parent 17794037
...@@ -32,12 +32,26 @@ POSSIBILITY OF SUCH DAMAGE. */ ...@@ -32,12 +32,26 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "config.h" #include "config.h"
#include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#if !BACKTRACE_USES_MALLOC
#include <sys/mman.h>
#endif
#include "unwind.h" #include "unwind.h"
#include "backtrace.h" #include "backtrace.h"
#include "backtrace-supported.h"
#include "internal.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. */ /* The main backtrace_full routine. */
/* Data passed through _Unwind_Backtrace. */ /* Data passed through _Unwind_Backtrace. */
...@@ -104,7 +118,6 @@ backtrace_full (struct backtrace_state *state, int skip, ...@@ -104,7 +118,6 @@ backtrace_full (struct backtrace_state *state, int skip,
backtrace_error_callback error_callback, void *data) backtrace_error_callback error_callback, void *data)
{ {
struct backtrace_data bdata; struct backtrace_data bdata;
void *p;
bdata.skip = skip + 1; bdata.skip = skip + 1;
bdata.state = state; bdata.state = state;
...@@ -113,16 +126,25 @@ backtrace_full (struct backtrace_state *state, int skip, ...@@ -113,16 +126,25 @@ backtrace_full (struct backtrace_state *state, int skip,
bdata.data = data; bdata.data = data;
bdata.ret = 0; bdata.ret = 0;
/* If we can't allocate any memory at all, don't try to produce #if !BACKTRACE_USES_MALLOC
file/line information. */ {
p = backtrace_alloc (state, 4096, NULL, NULL); size_t pagesize;
if (p == NULL) void *page;
bdata.can_alloc = 0;
else /* If we can't allocate any memory at all, don't try to produce
{ file/line information. */
backtrace_free (state, p, 4096, NULL, NULL); pagesize = getpagesize ();
bdata.can_alloc = 1; 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); _Unwind_Backtrace (unwind, &bdata);
return bdata.ret; return bdata.ret;
......
...@@ -165,9 +165,12 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *, ...@@ -165,9 +165,12 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
#undef ELFDATA2MSB #undef ELFDATA2MSB
#undef EV_CURRENT #undef EV_CURRENT
#undef ET_DYN #undef ET_DYN
#undef EM_PPC64
#undef EF_PPC64_ABI
#undef SHN_LORESERVE #undef SHN_LORESERVE
#undef SHN_XINDEX #undef SHN_XINDEX
#undef SHN_UNDEF #undef SHN_UNDEF
#undef SHT_PROGBITS
#undef SHT_SYMTAB #undef SHT_SYMTAB
#undef SHT_STRTAB #undef SHT_STRTAB
#undef SHT_DYNSYM #undef SHT_DYNSYM
...@@ -245,6 +248,9 @@ typedef struct { ...@@ -245,6 +248,9 @@ typedef struct {
#define ET_DYN 3 #define ET_DYN 3
#define EM_PPC64 21
#define EF_PPC64_ABI 3
typedef struct { typedef struct {
b_elf_word sh_name; /* Section name, index in string tbl */ b_elf_word sh_name; /* Section name, index in string tbl */
b_elf_word sh_type; /* Type of section */ b_elf_word sh_type; /* Type of section */
...@@ -262,6 +268,7 @@ typedef struct { ...@@ -262,6 +268,7 @@ typedef struct {
#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2 #define SHT_SYMTAB 2
#define SHT_STRTAB 3 #define SHT_STRTAB 3
#define SHT_DYNSYM 11 #define SHT_DYNSYM 11
...@@ -405,6 +412,20 @@ struct elf_syminfo_data ...@@ -405,6 +412,20 @@ struct elf_syminfo_data
size_t count; 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 /* Compute the CRC-32 of BUF/LEN. This uses the CRC used for
.gnu_debuglink files. */ .gnu_debuglink files. */
...@@ -569,7 +590,8 @@ elf_initialize_syminfo (struct backtrace_state *state, ...@@ -569,7 +590,8 @@ elf_initialize_syminfo (struct backtrace_state *state,
const unsigned char *symtab_data, size_t symtab_size, const unsigned char *symtab_data, size_t symtab_size,
const unsigned char *strtab, size_t strtab_size, const unsigned char *strtab, size_t strtab_size,
backtrace_error_callback error_callback, 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; size_t sym_count;
const b_elf_sym *sym; const b_elf_sym *sym;
...@@ -620,7 +642,17 @@ elf_initialize_syminfo (struct backtrace_state *state, ...@@ -620,7 +642,17 @@ elf_initialize_syminfo (struct backtrace_state *state,
return 0; return 0;
} }
elf_symbols[j].name = (const char *) strtab + sym->st_name; 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; elf_symbols[j].size = sym->st_size;
++j; ++j;
} }
...@@ -1054,12 +1086,19 @@ elf_zlib_fetch (const unsigned char **ppin, const unsigned char *pinend, ...@@ -1054,12 +1086,19 @@ elf_zlib_fetch (const unsigned char **ppin, const unsigned char *pinend,
return 0; 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. */ /* We've ensured that PIN is aligned. */
next = *(const uint32_t *)pin; next = *(const uint32_t *)pin;
#if __BYTE_ORDER == __ORDER_BIG_ENDIAN #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
next = __builtin_bswap32 (next); next = __builtin_bswap32 (next);
#endif #endif
#else
next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);
#endif
val |= (uint64_t)next << bits; val |= (uint64_t)next << bits;
bits += 32; bits += 32;
...@@ -2637,6 +2676,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, ...@@ -2637,6 +2676,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
int debug_view_valid; int debug_view_valid;
unsigned int using_debug_view; unsigned int using_debug_view;
uint16_t *zdebug_table; uint16_t *zdebug_table;
struct elf_ppc64_opd_data opd_data, *opd;
if (!debuginfo) if (!debuginfo)
{ {
...@@ -2655,6 +2695,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, ...@@ -2655,6 +2695,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
debuglink_name = NULL; debuglink_name = NULL;
debuglink_crc = 0; debuglink_crc = 0;
debug_view_valid = 0; debug_view_valid = 0;
opd = NULL;
if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback, if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback,
data, &ehdr_view)) data, &ehdr_view))
...@@ -2857,6 +2898,23 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, ...@@ -2857,6 +2898,23 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
debuglink_crc = *(const uint32_t*)(debuglink_data + crc_offset); 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) if (symtab_shndx == 0)
...@@ -2898,7 +2956,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, ...@@ -2898,7 +2956,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (!elf_initialize_syminfo (state, base_address, if (!elf_initialize_syminfo (state, base_address,
symtab_view.data, symtab_shdr->sh_size, symtab_view.data, symtab_shdr->sh_size,
strtab_view.data, strtab_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); backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
goto fail; goto fail;
...@@ -2951,6 +3009,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, ...@@ -2951,6 +3009,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
buildid_view_valid = 0; buildid_view_valid = 0;
} }
if (opd)
{
backtrace_release_view (state, &opd->view, error_callback, data);
opd = NULL;
}
if (debuglink_name != NULL) if (debuglink_name != NULL)
{ {
int d; int d;
...@@ -3139,6 +3203,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor, ...@@ -3139,6 +3203,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
backtrace_release_view (state, &buildid_view, error_callback, data); backtrace_release_view (state, &buildid_view, error_callback, data);
if (debug_view_valid) if (debug_view_valid)
backtrace_release_view (state, &debug_view, error_callback, data); backtrace_release_view (state, &debug_view, error_callback, data);
if (opd)
backtrace_release_view (state, &opd->view, error_callback, data);
if (descriptor != -1) if (descriptor != -1)
backtrace_close (descriptor, error_callback, data); backtrace_close (descriptor, error_callback, data);
return 0; return 0;
......
...@@ -760,6 +760,40 @@ xcoff_fileline (struct backtrace_state *state, uintptr_t pc, ...@@ -760,6 +760,40 @@ xcoff_fileline (struct backtrace_state *state, uintptr_t pc,
return callback (data, pc, NULL, 0, NULL); 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 /* Add a new mapping to the vector of line mappings that we are
building. Returns 1 on success, 0 on failure. */ building. Returns 1 on success, 0 on failure. */
...@@ -809,7 +843,6 @@ xcoff_process_linenos (struct backtrace_state *state, uintptr_t base_address, ...@@ -809,7 +843,6 @@ xcoff_process_linenos (struct backtrace_state *state, uintptr_t base_address,
uintptr_t pc; uintptr_t pc;
uint32_t lnno; uint32_t lnno;
int begincl; int begincl;
size_t i;
aux = (const b_xcoff_auxent *) (fsym + 1); aux = (const b_xcoff_auxent *) (fsym + 1);
lnnoptr = aux->x_fcn.x_lnnoptr; lnnoptr = aux->x_fcn.x_lnnoptr;
...@@ -839,15 +872,13 @@ xcoff_process_linenos (struct backtrace_state *state, uintptr_t base_address, ...@@ -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 /* If part of a function other than the beginning comes from an
include file, the line numbers are absolute, rather than include file, the line numbers are absolute, rather than
relative to the beginning of the function. */ relative to the beginning of the function. */
for (i = 0; i < vec->count; ++i) incl = (struct xcoff_incl *) bsearch (&lnnoptr, vec->vec.base,
{ vec->count,
incl = (struct xcoff_incl *) vec->vec.base + i; sizeof (struct xcoff_incl),
if (incl->begin <= lnnoptr && lnnoptr <= incl->end) xcoff_incl_search);
break;
}
if (begincl == -1) if (begincl == -1)
begincl = (i < vec->count); begincl = incl != NULL;
if (i < vec->count) if (incl != NULL)
{ {
filename = incl->filename; filename = incl->filename;
if (begincl == 1) if (begincl == 1)
...@@ -935,6 +966,9 @@ xcoff_initialize_fileline (struct backtrace_state *state, ...@@ -935,6 +966,9 @@ xcoff_initialize_fileline (struct backtrace_state *state,
i += asym->n_numaux; i += asym->n_numaux;
} }
backtrace_qsort (vec.vec.base, vec.count,
sizeof (struct xcoff_incl), xcoff_incl_compare);
filename = NULL; filename = NULL;
fsym = NULL; fsym = NULL;
for (i = 0; i < nsyms; ++i) for (i = 0; i < nsyms; ++i)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment