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
This commit is contained in:
Ian Lance Taylor 2018-04-17 07:04:02 -07:00
parent 177940370e
commit 012b950b37
3 changed files with 146 additions and 24 deletions

View File

@ -32,12 +32,26 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
#include <unistd.h>
#include <sys/types.h>
#if !BACKTRACE_USES_MALLOC
#include <sys/mman.h>
#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;

74
elf.c
View File

@ -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;

52
xcoff.c
View File

@ -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)