Update libbacktrace to ca0de0517.

This commit is contained in:
Bartosz Taudul 2020-03-01 12:55:32 +01:00
parent c36ed4b8b8
commit fdc3b01054
13 changed files with 3627 additions and 2057 deletions

View File

@ -1,5 +1,5 @@
/* alloc.c -- Memory allocation without mmap.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -150,13 +150,24 @@ backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback,
void *data)
{
vec->alc = 0;
if (vec->size == 0)
{
/* As of C17, realloc with size 0 is marked as an obsolescent feature, use
free instead. */
rpfree (vec->base);
vec->base = NULL;
return 1;
}
vec->base = rprealloc (vec->base, vec->size);
if (vec->base == NULL)
{
error_callback (data, "realloc", errno);
return 0;
}
vec->alc = 0;
return 1;
}

View File

@ -1,5 +1,5 @@
/* backtrace.h -- Public header file for stack backtrace library.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -74,7 +74,13 @@ typedef void (*backtrace_error_callback) (void *data, const char *msg,
use appropriate atomic operations. If THREADED is zero the state
may only be accessed by one thread at a time. This returns a state
pointer on success, NULL on error. If an error occurs, this will
call the ERROR_CALLBACK routine. */
call the ERROR_CALLBACK routine.
Calling this function allocates resources that cannot be freed.
There is no backtrace_free_state function. The state is used to
cache information that is expensive to recompute. Programs are
expected to call this function at most once and to save the return
value for all later calls to backtrace functions. */
extern struct backtrace_state *backtrace_create_state (
const char *filename, int threaded,

View File

@ -5,9 +5,11 @@
# define BACKTRACE_ELF_SIZE 32
#endif
#define HAVE_DLFCN_H
#define HAVE_FCNTL
#define HAVE_INTTYPES_H
#define HAVE_LSTAT
#define HAVE_READLINK
#define HAVE_DL_ITERATE_PHDR
#define HAVE_DLFCN_H 1
#define HAVE_FCNTL 1
#define HAVE_INTTYPES_H 1
#define HAVE_LSTAT 1
#define HAVE_READLINK 1
#define HAVE_DL_ITERATE_PHDR 1
#define HAVE_ATOMIC_FUNCTIONS 1
#define HAVE_DECL_STRNLEN 1

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* elf.c -- Get debug data from an ELF file for backtraces.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -57,15 +57,13 @@ POSSIBILITY OF SUCH DAMAGE. */
#endif
#ifndef __GNUC__
#ifndef __builtin_prefetch
# define __builtin_prefetch(p, r, l)
#endif
#define __builtin_prefetch(p, r, l)
#ifndef unlikely
# define unlikely(x) (x)
#define unlikely(x) (x)
#endif
#else
#ifndef unlikely
# define unlikely(x) __builtin_expect(!!(x), 0)
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
#endif
@ -120,6 +118,29 @@ xreadlink (const char *path ATTRIBUTE_UNUSED, char *buf ATTRIBUTE_UNUSED,
#endif
#ifndef HAVE_DL_ITERATE_PHDR
/* Dummy version of dl_iterate_phdr for systems that don't have it. */
#define dl_phdr_info x_dl_phdr_info
#define dl_iterate_phdr x_dl_iterate_phdr
struct dl_phdr_info
{
uintptr_t dlpi_addr;
const char *dlpi_name;
};
static int
dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
size_t, void *) ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
return 0;
}
#endif /* ! defined (HAVE_DL_ITERATE_PHDR) */
/* The configure script must tell us whether we are 32-bit or 64-bit
ELF. We could make this code test and support either possibility,
but there is no point. This code only works for the currently
@ -323,41 +344,19 @@ typedef struct
#define ELFCOMPRESS_ZLIB 1
/* An index of ELF sections we care about. */
/* Names of sections, indexed by enum dwarf_section in internal.h. */
enum debug_section
{
DEBUG_INFO,
DEBUG_LINE,
DEBUG_ABBREV,
DEBUG_RANGES,
DEBUG_STR,
/* The old style compressed sections. This list must correspond to
the list of normal debug sections. */
ZDEBUG_INFO,
ZDEBUG_LINE,
ZDEBUG_ABBREV,
ZDEBUG_RANGES,
ZDEBUG_STR,
DEBUG_MAX
};
/* Names of sections, indexed by enum elf_section. */
static const char * const debug_section_names[DEBUG_MAX] =
static const char * const dwarf_section_names[DEBUG_MAX] =
{
".debug_info",
".debug_line",
".debug_abbrev",
".debug_ranges",
".debug_str",
".zdebug_info",
".zdebug_line",
".zdebug_abbrev",
".zdebug_ranges",
".zdebug_str"
".debug_addr",
".debug_str_offsets",
".debug_line_str",
".debug_rnglists"
};
/* Information we gather for the sections we care about. */
@ -659,6 +658,8 @@ static void
elf_add_syminfo_data (struct backtrace_state *state,
struct elf_syminfo_data *edata)
{
if (!state->threaded)
{
struct elf_syminfo_data **pp;
for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
@ -666,6 +667,31 @@ elf_add_syminfo_data (struct backtrace_state *state,
pp = &(*pp)->next)
;
*pp = edata;
}
else
{
while (1)
{
struct elf_syminfo_data **pp;
pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
while (1)
{
struct elf_syminfo_data *p;
p = backtrace_atomic_load_pointer (pp);
if (p == NULL)
break;
pp = &p->next;
}
if (__sync_bool_compare_and_swap (pp, NULL, edata))
break;
}
}
}
/* Return the symbol name and value for an ADDR. */
@ -679,6 +705,8 @@ elf_syminfo (struct backtrace_state *state, uintptr_t addr,
struct elf_syminfo_data *edata;
struct elf_symbol *sym = NULL;
if (!state->threaded)
{
for (edata = (struct elf_syminfo_data *) state->syminfo_data;
edata != NULL;
edata = edata->next)
@ -689,6 +717,27 @@ elf_syminfo (struct backtrace_state *state, uintptr_t addr,
if (sym != NULL)
break;
}
}
else
{
struct elf_syminfo_data **pp;
pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
while (1)
{
edata = backtrace_atomic_load_pointer (pp);
if (edata == NULL)
break;
sym = ((struct elf_symbol *)
bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
pp = &edata->next;
}
}
if (sym == NULL)
callback (data, addr, NULL, 0, 0);
@ -745,6 +794,8 @@ elf_readlink (struct backtrace_state *state, const char *filename,
}
}
#define SYSTEM_BUILD_ID_DIR "/usr/lib/debug/.build-id/"
/* Open a separate debug info file, using the build ID to find it.
Returns an open file descriptor, or -1.
@ -757,7 +808,7 @@ elf_open_debugfile_by_buildid (struct backtrace_state *state,
backtrace_error_callback error_callback,
void *data)
{
const char * const prefix = "/usr/lib/debug/.build-id/";
const char * const prefix = SYSTEM_BUILD_ID_DIR;
const size_t prefix_len = strlen (prefix);
const char * const suffix = ".debug";
const size_t suffix_len = strlen (suffix);
@ -2574,7 +2625,8 @@ static int
elf_add (struct backtrace_state *state, const char *filename, int descriptor,
uintptr_t base_address, backtrace_error_callback error_callback,
void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf,
int exe, int debuginfo)
struct dwarf_data **fileline_entry, int exe, int debuginfo,
const char *with_buildid_data, uint32_t with_buildid_size)
{
struct backtrace_view ehdr_view;
b_elf_ehdr ehdr;
@ -2594,6 +2646,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
unsigned int dynsym_shndx;
unsigned int i;
struct debug_section_info sections[DEBUG_MAX];
struct debug_section_info zsections[DEBUG_MAX];
struct backtrace_view symtab_view;
int symtab_view_valid;
struct backtrace_view strtab_view;
@ -2606,13 +2659,23 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
int debuglink_view_valid;
const char *debuglink_name;
uint32_t debuglink_crc;
struct backtrace_view debugaltlink_view;
int debugaltlink_view_valid;
const char *debugaltlink_name;
const char *debugaltlink_buildid_data;
uint32_t debugaltlink_buildid_size;
off_t min_offset;
off_t max_offset;
off_t debug_size;
struct backtrace_view debug_view;
int debug_view_valid;
unsigned int using_debug_view;
uint16_t *zdebug_table;
struct backtrace_view split_debug_view[DEBUG_MAX];
unsigned char split_debug_view_valid[DEBUG_MAX];
struct elf_ppc64_opd_data opd_data, *opd;
struct dwarf_sections dwarf_sections;
struct dwarf_data *fileline_altlink = NULL;
if (!debuginfo)
{
@ -2630,7 +2693,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
debuglink_view_valid = 0;
debuglink_name = NULL;
debuglink_crc = 0;
debugaltlink_view_valid = 0;
debugaltlink_name = NULL;
debugaltlink_buildid_data = NULL;
debugaltlink_buildid_size = 0;
debug_view_valid = 0;
memset (&split_debug_view_valid[0], 0, sizeof split_debug_view_valid);
opd = NULL;
if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback,
@ -2739,7 +2807,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
shstr_size = shstrhdr->sh_size;
shstr_off = shstrhdr->sh_offset;
if (!backtrace_get_view (state, descriptor, shstr_off, shstr_size,
if (!backtrace_get_view (state, descriptor, shstr_off, shstrhdr->sh_size,
error_callback, data, &names_view))
goto fail;
names_view_valid = 1;
@ -2749,6 +2817,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
dynsym_shndx = 0;
memset (sections, 0, sizeof sections);
memset (zsections, 0, sizeof zsections);
/* Look for the symbol table. */
for (i = 1; i < shnum; ++i)
@ -2776,7 +2845,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
for (j = 0; j < (int) DEBUG_MAX; ++j)
{
if (strcmp (name, debug_section_names[j]) == 0)
if (strcmp (name, dwarf_section_names[j]) == 0)
{
sections[j].offset = shdr->sh_offset;
sections[j].size = shdr->sh_size;
@ -2785,10 +2854,23 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
}
}
if (name[0] == '.' && name[1] == 'z')
{
for (j = 0; j < (int) DEBUG_MAX; ++j)
{
if (strcmp (name + 2, dwarf_section_names[j] + 1) == 0)
{
zsections[j].offset = shdr->sh_offset;
zsections[j].size = shdr->sh_size;
break;
}
}
}
/* Read the build ID if present. This could check for any
SHT_NOTE section with the right note name and type, but gdb
looks for a specific section name. */
if (!debuginfo
if ((!debuginfo || with_buildid_data != NULL)
&& !buildid_view_valid
&& strcmp (name, ".note.gnu.build-id") == 0)
{
@ -2804,11 +2886,20 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (note->type == NT_GNU_BUILD_ID
&& note->namesz == 4
&& strncmp (note->name, "GNU", 4) == 0
&& shdr->sh_size < 12 + ((note->namesz + 3) & ~ 3) + note->descsz)
&& shdr->sh_size <= 12 + ((note->namesz + 3) & ~ 3) + note->descsz)
{
buildid_data = &note->name[0] + ((note->namesz + 3) & ~ 3);
buildid_size = note->descsz;
}
if (with_buildid_size != 0)
{
if (buildid_size != with_buildid_size)
goto fail;
if (memcmp (buildid_data, with_buildid_data, buildid_size) != 0)
goto fail;
}
}
/* Read the debuglink file if present. */
@ -2835,6 +2926,32 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
}
}
if (!debugaltlink_view_valid
&& strcmp (name, ".gnu_debugaltlink") == 0)
{
const char *debugaltlink_data;
size_t debugaltlink_name_len;
if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
shdr->sh_size, error_callback, data,
&debugaltlink_view))
goto fail;
debugaltlink_view_valid = 1;
debugaltlink_data = (const char *) debugaltlink_view.data;
debugaltlink_name = debugaltlink_data;
debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);
if (debugaltlink_name_len < shdr->sh_size)
{
/* Include terminating zero. */
debugaltlink_name_len += 1;
debugaltlink_buildid_data
= debugaltlink_data + debugaltlink_name_len;
debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len;
}
}
/* Read the .opd section on PowerPC64 ELFv1. */
if (ehdr.e_machine == EM_PPC64
&& (ehdr.e_flags & EF_PPC64_ABI) < 2
@ -2902,6 +3019,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
string table permanently. */
backtrace_release_view (state, &symtab_view, error_callback, data);
symtab_view_valid = 0;
strtab_view_valid = 0;
*found_sym = 1;
@ -2929,8 +3047,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (debuglink_view_valid)
backtrace_release_view (state, &debuglink_view, error_callback,
data);
ret = elf_add (state, NULL, d, base_address, error_callback, data,
fileline_fn, found_sym, found_dwarf, 0, 1);
if (debugaltlink_view_valid)
backtrace_release_view (state, &debugaltlink_view, error_callback,
data);
ret = elf_add (state, "", d, base_address, error_callback, data,
fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
0);
if (ret < 0)
backtrace_close (d, error_callback, data);
else
@ -2964,8 +3086,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
backtrace_release_view (state, &debuglink_view, error_callback,
data);
ret = elf_add (state, NULL, d, base_address, error_callback, data,
fileline_fn, found_sym, found_dwarf, 0, 1);
if (debugaltlink_view_valid)
backtrace_release_view (state, &debugaltlink_view, error_callback,
data);
ret = elf_add (state, "", d, base_address, error_callback, data,
fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
0);
if (ret < 0)
backtrace_close (d, error_callback, data);
else
@ -2980,22 +3106,66 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
debuglink_view_valid = 0;
}
if (debugaltlink_name != NULL)
{
int d;
d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
0, error_callback, data);
if (d >= 0)
{
int ret;
ret = elf_add (state, filename, d, base_address, error_callback, data,
fileline_fn, found_sym, found_dwarf, &fileline_altlink,
0, 1, debugaltlink_buildid_data,
debugaltlink_buildid_size);
backtrace_release_view (state, &debugaltlink_view, error_callback,
data);
debugaltlink_view_valid = 0;
if (ret < 0)
{
backtrace_close (d, error_callback, data);
return ret;
}
}
}
if (debugaltlink_view_valid)
{
backtrace_release_view (state, &debugaltlink_view, error_callback, data);
debugaltlink_view_valid = 0;
}
/* Read all the debug sections in a single view, since they are
probably adjacent in the file. We never release this view. */
probably adjacent in the file. If any of sections are
uncompressed, we never release this view. */
min_offset = 0;
max_offset = 0;
debug_size = 0;
for (i = 0; i < (int) DEBUG_MAX; ++i)
{
off_t end;
if (sections[i].size == 0)
continue;
if (min_offset == 0 || sections[i].offset < min_offset)
min_offset = sections[i].offset;
end = sections[i].offset + sections[i].size;
if (end > max_offset)
max_offset = end;
if (sections[i].size != 0)
{
if (min_offset == 0 || sections[i].offset < min_offset)
min_offset = sections[i].offset;
end = sections[i].offset + sections[i].size;
if (end > max_offset)
max_offset = end;
debug_size += sections[i].size;
}
if (zsections[i].size != 0)
{
if (min_offset == 0 || zsections[i].offset < min_offset)
min_offset = zsections[i].offset;
end = zsections[i].offset + zsections[i].size;
if (end > max_offset)
max_offset = end;
debug_size += zsections[i].size;
}
}
if (min_offset == 0 || max_offset == 0)
{
@ -3004,11 +3174,45 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
return 1;
}
if (!backtrace_get_view (state, descriptor, min_offset,
max_offset - min_offset,
error_callback, data, &debug_view))
goto fail;
debug_view_valid = 1;
/* If the total debug section size is large, assume that there are
gaps between the sections, and read them individually. */
if (max_offset - min_offset < 0x20000000
|| max_offset - min_offset < debug_size + 0x10000)
{
if (!backtrace_get_view (state, descriptor, min_offset,
max_offset - min_offset,
error_callback, data, &debug_view))
goto fail;
debug_view_valid = 1;
}
else
{
memset (&split_debug_view[0], 0, sizeof split_debug_view);
for (i = 0; i < (int) DEBUG_MAX; ++i)
{
struct debug_section_info *dsec;
if (sections[i].size != 0)
dsec = &sections[i];
else if (zsections[i].size != 0)
dsec = &zsections[i];
else
continue;
if (!backtrace_get_view (state, descriptor, dsec->offset, dsec->size,
error_callback, data, &split_debug_view[i]))
goto fail;
split_debug_view_valid[i] = 1;
if (sections[i].size != 0)
sections[i].data = ((const unsigned char *)
split_debug_view[i].data);
else
zsections[i].data = ((const unsigned char *)
split_debug_view[i].data);
}
}
/* We've read all we need from the executable. */
if (!backtrace_close (descriptor, error_callback, data))
@ -3016,28 +3220,33 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
descriptor = -1;
using_debug_view = 0;
for (i = 0; i < (int) DEBUG_MAX; ++i)
if (debug_view_valid)
{
if (sections[i].size == 0)
sections[i].data = NULL;
else
for (i = 0; i < (int) DEBUG_MAX; ++i)
{
sections[i].data = ((const unsigned char *) debug_view.data
+ (sections[i].offset - min_offset));
if (i < ZDEBUG_INFO)
++using_debug_view;
if (sections[i].size == 0)
sections[i].data = NULL;
else
{
sections[i].data = ((const unsigned char *) debug_view.data
+ (sections[i].offset - min_offset));
++using_debug_view;
}
if (zsections[i].size == 0)
zsections[i].data = NULL;
else
zsections[i].data = ((const unsigned char *) debug_view.data
+ (zsections[i].offset - min_offset));
}
}
/* Uncompress the old format (--compress-debug-sections=zlib-gnu). */
zdebug_table = NULL;
for (i = 0; i < ZDEBUG_INFO; ++i)
for (i = 0; i < (int) DEBUG_MAX; ++i)
{
struct debug_section_info *pz;
pz = &sections[i + ZDEBUG_INFO - DEBUG_INFO];
if (sections[i].size == 0 && pz->size > 0)
if (sections[i].size == 0 && zsections[i].size > 0)
{
unsigned char *uncompressed_data;
size_t uncompressed_size;
@ -3053,19 +3262,27 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
uncompressed_data = NULL;
uncompressed_size = 0;
if (!elf_uncompress_zdebug (state, pz->data, pz->size, zdebug_table,
if (!elf_uncompress_zdebug (state, zsections[i].data,
zsections[i].size, zdebug_table,
error_callback, data,
&uncompressed_data, &uncompressed_size))
goto fail;
sections[i].data = uncompressed_data;
sections[i].size = uncompressed_size;
sections[i].compressed = 0;
if (split_debug_view_valid[i])
{
backtrace_release_view (state, &split_debug_view[i],
error_callback, data);
split_debug_view_valid[i] = 0;
}
}
}
/* Uncompress the official ELF format
(--compress-debug-sections=zlib-gabi). */
for (i = 0; i < ZDEBUG_INFO; ++i)
for (i = 0; i < (int) DEBUG_MAX; ++i)
{
unsigned char *uncompressed_data;
size_t uncompressed_size;
@ -3092,7 +3309,14 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
sections[i].size = uncompressed_size;
sections[i].compressed = 0;
--using_debug_view;
if (debug_view_valid)
--using_debug_view;
else if (split_debug_view_valid[i])
{
backtrace_release_view (state, &split_debug_view[i],
error_callback, data);
split_debug_view_valid[i] = 0;
}
}
if (zdebug_table != NULL)
@ -3105,19 +3329,17 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
debug_view_valid = 0;
}
if (!backtrace_dwarf_add (state, base_address,
sections[DEBUG_INFO].data,
sections[DEBUG_INFO].size,
sections[DEBUG_LINE].data,
sections[DEBUG_LINE].size,
sections[DEBUG_ABBREV].data,
sections[DEBUG_ABBREV].size,
sections[DEBUG_RANGES].data,
sections[DEBUG_RANGES].size,
sections[DEBUG_STR].data,
sections[DEBUG_STR].size,
for (i = 0; i < (int) DEBUG_MAX; ++i)
{
dwarf_sections.data[i] = sections[i].data;
dwarf_sections.size[i] = sections[i].size;
}
if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
ehdr.e_ident[EI_DATA] == ELFDATA2MSB,
error_callback, data, fileline_fn))
fileline_altlink,
error_callback, data, fileline_fn,
fileline_entry))
goto fail;
*found_dwarf = 1;
@ -3135,10 +3357,18 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
backtrace_release_view (state, &strtab_view, error_callback, data);
if (debuglink_view_valid)
backtrace_release_view (state, &debuglink_view, error_callback, data);
if (debugaltlink_view_valid)
backtrace_release_view (state, &debugaltlink_view, error_callback, data);
if (buildid_view_valid)
backtrace_release_view (state, &buildid_view, error_callback, data);
if (debug_view_valid)
backtrace_release_view (state, &debug_view, error_callback, data);
for (i = 0; i < (int) DEBUG_MAX; ++i)
{
if (split_debug_view_valid[i])
backtrace_release_view (state, &split_debug_view[i],
error_callback, data);
}
if (opd)
backtrace_release_view (state, &opd->view, error_callback, data);
if (descriptor != -1)
@ -3205,7 +3435,7 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
if (elf_add (pd->state, filename, descriptor, info->dlpi_addr,
pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
&found_dwarf, 0, 0))
&found_dwarf, NULL, 0, 0, NULL, 0))
{
if (found_dwarf)
{
@ -3233,7 +3463,8 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
struct phdr_data pd;
ret = elf_add (state, filename, descriptor, 0, error_callback, data,
&elf_fileline_fn, &found_sym, &found_dwarf, 1, 0);
&elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0, NULL,
0);
if (!ret)
return 0;
@ -3248,12 +3479,26 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
dl_iterate_phdr (phdr_callback, (void *) &pd);
if (!state->threaded)
{
if (found_sym)
state->syminfo_fn = elf_syminfo;
else if (state->syminfo_fn == NULL)
state->syminfo_fn = elf_nosyms;
}
else
{
if (found_sym)
backtrace_atomic_store_pointer (&state->syminfo_fn, &elf_syminfo);
else
(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
elf_nosyms);
}
if (!state->threaded)
*fileline_fn = state->fileline_fn;
else
*fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
if (*fileline_fn == NULL || *fileline_fn == elf_nodebug)
*fileline_fn = elf_fileline_fn;

View File

@ -1,5 +1,5 @@
/* fileline.c -- Get file and line number information in a backtrace.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -34,72 +34,97 @@ POSSIBILITY OF SUCH DAMAGE. */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef BSD
# include <sys/sysctl.h>
# include <limits.h>
#endif
#ifdef __APPLE__
# include <mach-o/dyld.h>
#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)
#include <sys/sysctl.h>
#endif
#include "backtrace.hpp"
#include "internal.hpp"
#ifdef BSD
# if !defined HAVE_GETEXECNAME && defined KERN_PROC_PATHNAME
# define HAVE_GETEXECNAME
static char execname[PATH_MAX + 1];
static const char *
getexecname(void)
{
size_t path_len = sizeof(execname);
int mib[] = {
CTL_KERN,
#if defined(__NetBSD__)
KERN_PROC_ARGS,
-1,
KERN_PROC_PATHNAME,
#else
KERN_PROC,
KERN_PROC_PATHNAME,
-1,
#endif
};
u_int miblen = sizeof(mib) / sizeof(mib[0]);
int rc = sysctl(mib, miblen, execname, &path_len, NULL, 0);
return rc ? NULL : execname;
}
# endif
#endif
#if !defined HAVE_GETEXECNAME && defined __APPLE__
# define HAVE_GETEXECNAME
static char execname[PATH_MAX + 1];
static const char *
getexecname(void)
{
uint32_t size = sizeof(execname);
if (_NSGetExecutablePath(execname, &size) == 0)
return execname;
else
return NULL;
}
#endif
#ifndef HAVE_GETEXECNAME
# define getexecname() NULL
#define getexecname() NULL
#endif
namespace tracy
{
#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)
#define sysctl_exec_name1(state, error_callback, data) NULL
#define sysctl_exec_name2(state, error_callback, data) NULL
#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
static char *
sysctl_exec_name (struct backtrace_state *state,
int mib0, int mib1, int mib2, int mib3,
backtrace_error_callback error_callback, void *data)
{
int mib[4];
size_t len;
char *name;
size_t rlen;
mib[0] = mib0;
mib[1] = mib1;
mib[2] = mib2;
mib[3] = mib3;
if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)
return NULL;
name = (char *) backtrace_alloc (state, len, error_callback, data);
if (name == NULL)
return NULL;
rlen = len;
if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)
{
backtrace_free (state, name, len, error_callback, data);
return NULL;
}
return name;
}
#ifdef HAVE_KERN_PROC_ARGS
static char *
sysctl_exec_name1 (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data)
{
/* This variant is used on NetBSD. */
return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,
KERN_PROC_PATHNAME, error_callback, data);
}
#else
#define sysctl_exec_name1(state, error_callback, data) NULL
#endif
#ifdef HAVE_KERN_PROC
static char *
sysctl_exec_name2 (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data)
{
/* This variant is used on FreeBSD. */
return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,
error_callback, data);
}
#else
#define sysctl_exec_name2(state, error_callback, data) NULL
#endif
#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
/* Initialize the fileline information from the executable. Returns 1
on success, 0 on failure. */
@ -115,7 +140,10 @@ fileline_initialize (struct backtrace_state *state,
const char *filename;
char buf[64];
failed = state->fileline_initialization_failed;
if (!state->threaded)
failed = state->fileline_initialization_failed;
else
failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
if (failed)
{
@ -123,7 +151,10 @@ fileline_initialize (struct backtrace_state *state,
return 0;
}
fileline_fn = state->fileline_fn;
if (!state->threaded)
fileline_fn = state->fileline_fn;
else
fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
if (fileline_fn != NULL)
return 1;
@ -131,7 +162,7 @@ fileline_initialize (struct backtrace_state *state,
descriptor = -1;
called_error_callback = 0;
for (pass = 0; pass < 5; ++pass)
for (pass = 0; pass < 7; ++pass)
{
int does_not_exist;
@ -154,6 +185,12 @@ fileline_initialize (struct backtrace_state *state,
(long) getpid ());
filename = buf;
break;
case 5:
filename = sysctl_exec_name1 (state, error_callback, data);
break;
case 6:
filename = sysctl_exec_name2 (state, error_callback, data);
break;
default:
abort ();
}
@ -194,12 +231,23 @@ fileline_initialize (struct backtrace_state *state,
}
if (failed)
{
state->fileline_initialization_failed = 1;
return 0;
}
{
if (!state->threaded)
state->fileline_initialization_failed = 1;
else
backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
return 0;
}
state->fileline_fn = fileline_fn;
if (!state->threaded)
state->fileline_fn = fileline_fn;
else
{
backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
/* Note that if two threads initialize at once, one of the data
sets may be leaked. */
}
return 1;
}

View File

@ -0,0 +1,52 @@
/* btest.c -- Filename header for libbacktrace library
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#ifndef GCC_VERSION
# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#endif
#if (GCC_VERSION < 2007)
# define __attribute__(x)
#endif
#ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif
#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)
# define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
# define HAS_DRIVE_SPEC(f) ((f)[0] != '\0' && (f)[1] == ':')
# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC(f))
#else
# define IS_DIR_SEPARATOR(c) ((c) == '/')
# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]))
#endif

View File

@ -1,5 +1,5 @@
/* internal.h -- Internal header file for stack backtrace library.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -56,6 +56,8 @@ POSSIBILITY OF SUCH DAMAGE. */
# endif
#endif
#ifndef HAVE_SYNC_FUNCTIONS
/* Define out the sync functions. These should never be called if
they are not available. */
@ -63,6 +65,37 @@ POSSIBILITY OF SUCH DAMAGE. */
#define __sync_lock_test_and_set(A, B) (abort(), 0)
#define __sync_lock_release(A) abort()
#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
#ifdef HAVE_ATOMIC_FUNCTIONS
/* We have the atomic builtin functions. */
#define backtrace_atomic_load_pointer(p) \
__atomic_load_n ((p), __ATOMIC_ACQUIRE)
#define backtrace_atomic_load_int(p) \
__atomic_load_n ((p), __ATOMIC_ACQUIRE)
#define backtrace_atomic_store_pointer(p, v) \
__atomic_store_n ((p), (v), __ATOMIC_RELEASE)
#define backtrace_atomic_store_size_t(p, v) \
__atomic_store_n ((p), (v), __ATOMIC_RELEASE)
#define backtrace_atomic_store_int(p, v) \
__atomic_store_n ((p), (v), __ATOMIC_RELEASE)
#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */
#ifdef HAVE_SYNC_FUNCTIONS
/* We have the sync functions but not the atomic functions. Define
the atomic ones in terms of the sync ones. */
extern void *backtrace_atomic_load_pointer (void *);
extern int backtrace_atomic_load_int (int *);
extern void backtrace_atomic_store_pointer (void *, void *);
extern void backtrace_atomic_store_size_t (size_t *, size_t);
extern void backtrace_atomic_store_int (int *, int);
#else /* !defined (HAVE_SYNC_FUNCTIONS) */
/* We have neither the sync nor the atomic functions. These will
never be called. */
@ -72,6 +105,9 @@ POSSIBILITY OF SUCH DAMAGE. */
#define backtrace_atomic_store_size_t(p, v) abort()
#define backtrace_atomic_store_int(p, v) abort()
#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */
namespace tracy
{
@ -146,7 +182,7 @@ struct backtrace_view
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the
result in *VIEW. Returns 1 on success, 0 on error. */
extern int backtrace_get_view (struct backtrace_state *state, int descriptor,
off_t offset, size_t size,
off_t offset, uint64_t size,
backtrace_error_callback error_callback,
void *data, struct backtrace_view *view);
@ -224,6 +260,18 @@ extern int backtrace_vector_release (struct backtrace_state *state,
backtrace_error_callback error_callback,
void *data);
/* Free the space managed by VEC. This will reset VEC. */
static inline void
backtrace_vector_free (struct backtrace_state *state,
struct backtrace_vector *vec,
backtrace_error_callback error_callback, void *data)
{
vec->alc += vec->size;
vec->size = 0;
backtrace_vector_release (state, vec, error_callback, data);
}
/* Read initial debug data from a descriptor, and set the
fileline_data, syminfo_fn, and syminfo_data fields of STATE.
Return the fileln_fn field in *FILELN_FN--this is done this way so
@ -241,23 +289,54 @@ extern int backtrace_initialize (struct backtrace_state *state,
void *data,
fileline *fileline_fn);
/* An enum for the DWARF sections we care about. */
enum dwarf_section
{
DEBUG_INFO,
DEBUG_LINE,
DEBUG_ABBREV,
DEBUG_RANGES,
DEBUG_STR,
DEBUG_ADDR,
DEBUG_STR_OFFSETS,
DEBUG_LINE_STR,
DEBUG_RNGLISTS,
DEBUG_MAX
};
/* Data for the DWARF sections we care about. */
struct dwarf_sections
{
const unsigned char *data[DEBUG_MAX];
size_t size[DEBUG_MAX];
};
/* DWARF data read from a file, used for .gnu_debugaltlink. */
struct dwarf_data;
/* Add file/line information for a DWARF module. */
extern int backtrace_dwarf_add (struct backtrace_state *state,
uintptr_t base_address,
const unsigned char* dwarf_info,
size_t dwarf_info_size,
const unsigned char *dwarf_line,
size_t dwarf_line_size,
const unsigned char *dwarf_abbrev,
size_t dwarf_abbrev_size,
const unsigned char *dwarf_ranges,
size_t dwarf_range_size,
const unsigned char *dwarf_str,
size_t dwarf_str_size,
const struct dwarf_sections *dwarf_sections,
int is_bigendian,
struct dwarf_data *fileline_altlink,
backtrace_error_callback error_callback,
void *data, fileline *fileline_fn);
void *data, fileline *fileline_fn,
struct dwarf_data **fileline_entry);
/* A test-only hook for elf_uncompress_zdebug. */
extern int backtrace_uncompress_zdebug (struct backtrace_state *,
const unsigned char *compressed,
size_t compressed_size,
backtrace_error_callback, void *data,
unsigned char **uncompressed,
size_t *uncompressed_size);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* mmapio.c -- File views using mmap.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -54,7 +54,7 @@ namespace tracy
int
backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
int descriptor, off_t offset, size_t size,
int descriptor, off_t offset, uint64_t size,
backtrace_error_callback error_callback,
void *data, struct backtrace_view *view)
{
@ -63,6 +63,12 @@ backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
off_t pageoff;
void *map;
if ((uint64_t) (size_t) size != size)
{
error_callback (data, "file size too large", 0);
return 0;
}
pagesize = getpagesize ();
inpage = offset % pagesize;
pageoff = offset - inpage;
@ -92,7 +98,13 @@ backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback,
void *data)
{
if (munmap (view->base, view->len) < 0)
union {
const void *cv;
void *v;
};
cv = view->base;
if (munmap (v, view->len) < 0)
error_callback (data, "munmap", errno);
}

View File

@ -1,5 +1,5 @@
/* posix.c -- POSIX file I/O routines for the backtrace library.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/* sort.c -- Sort without allocating memory
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/* state.c -- Create the backtrace state.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without