mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-26 07:54:36 +00:00
Update libbacktrace to ca0de0517.
This commit is contained in:
parent
c36ed4b8b8
commit
fdc3b01054
@ -1,5 +1,5 @@
|
|||||||
/* alloc.c -- Memory allocation without mmap.
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
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,
|
backtrace_error_callback error_callback,
|
||||||
void *data)
|
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);
|
vec->base = rprealloc (vec->base, vec->size);
|
||||||
if (vec->base == NULL)
|
if (vec->base == NULL)
|
||||||
{
|
{
|
||||||
error_callback (data, "realloc", errno);
|
error_callback (data, "realloc", errno);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
vec->alc = 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* backtrace.h -- Public header file for stack backtrace library.
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
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
|
use appropriate atomic operations. If THREADED is zero the state
|
||||||
may only be accessed by one thread at a time. This returns a 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
|
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 (
|
extern struct backtrace_state *backtrace_create_state (
|
||||||
const char *filename, int threaded,
|
const char *filename, int threaded,
|
||||||
|
@ -5,9 +5,11 @@
|
|||||||
# define BACKTRACE_ELF_SIZE 32
|
# define BACKTRACE_ELF_SIZE 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HAVE_DLFCN_H
|
#define HAVE_DLFCN_H 1
|
||||||
#define HAVE_FCNTL
|
#define HAVE_FCNTL 1
|
||||||
#define HAVE_INTTYPES_H
|
#define HAVE_INTTYPES_H 1
|
||||||
#define HAVE_LSTAT
|
#define HAVE_LSTAT 1
|
||||||
#define HAVE_READLINK
|
#define HAVE_READLINK 1
|
||||||
#define HAVE_DL_ITERATE_PHDR
|
#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
@ -1,5 +1,5 @@
|
|||||||
/* elf.c -- Get debug data from an ELF file for backtraces.
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -57,15 +57,13 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
#ifndef __builtin_prefetch
|
#define __builtin_prefetch(p, r, l)
|
||||||
# define __builtin_prefetch(p, r, l)
|
|
||||||
#endif
|
|
||||||
#ifndef unlikely
|
#ifndef unlikely
|
||||||
# define unlikely(x) (x)
|
#define unlikely(x) (x)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifndef unlikely
|
#ifndef unlikely
|
||||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -120,6 +118,29 @@ xreadlink (const char *path ATTRIBUTE_UNUSED, char *buf ATTRIBUTE_UNUSED,
|
|||||||
|
|
||||||
#endif
|
#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
|
/* 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,
|
ELF. We could make this code test and support either possibility,
|
||||||
but there is no point. This code only works for the currently
|
but there is no point. This code only works for the currently
|
||||||
@ -323,41 +344,19 @@ typedef struct
|
|||||||
|
|
||||||
#define ELFCOMPRESS_ZLIB 1
|
#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
|
static const char * const dwarf_section_names[DEBUG_MAX] =
|
||||||
{
|
|
||||||
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] =
|
|
||||||
{
|
{
|
||||||
".debug_info",
|
".debug_info",
|
||||||
".debug_line",
|
".debug_line",
|
||||||
".debug_abbrev",
|
".debug_abbrev",
|
||||||
".debug_ranges",
|
".debug_ranges",
|
||||||
".debug_str",
|
".debug_str",
|
||||||
".zdebug_info",
|
".debug_addr",
|
||||||
".zdebug_line",
|
".debug_str_offsets",
|
||||||
".zdebug_abbrev",
|
".debug_line_str",
|
||||||
".zdebug_ranges",
|
".debug_rnglists"
|
||||||
".zdebug_str"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Information we gather for the sections we care about. */
|
/* Information we gather for the sections we care about. */
|
||||||
@ -659,6 +658,8 @@ static void
|
|||||||
elf_add_syminfo_data (struct backtrace_state *state,
|
elf_add_syminfo_data (struct backtrace_state *state,
|
||||||
struct elf_syminfo_data *edata)
|
struct elf_syminfo_data *edata)
|
||||||
{
|
{
|
||||||
|
if (!state->threaded)
|
||||||
|
{
|
||||||
struct elf_syminfo_data **pp;
|
struct elf_syminfo_data **pp;
|
||||||
|
|
||||||
for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
|
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 = &(*pp)->next)
|
||||||
;
|
;
|
||||||
*pp = edata;
|
*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. */
|
/* 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_syminfo_data *edata;
|
||||||
struct elf_symbol *sym = NULL;
|
struct elf_symbol *sym = NULL;
|
||||||
|
|
||||||
|
if (!state->threaded)
|
||||||
|
{
|
||||||
for (edata = (struct elf_syminfo_data *) state->syminfo_data;
|
for (edata = (struct elf_syminfo_data *) state->syminfo_data;
|
||||||
edata != NULL;
|
edata != NULL;
|
||||||
edata = edata->next)
|
edata = edata->next)
|
||||||
@ -689,6 +717,27 @@ elf_syminfo (struct backtrace_state *state, uintptr_t addr,
|
|||||||
if (sym != NULL)
|
if (sym != NULL)
|
||||||
break;
|
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)
|
if (sym == NULL)
|
||||||
callback (data, addr, NULL, 0, 0);
|
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.
|
/* Open a separate debug info file, using the build ID to find it.
|
||||||
Returns an open file descriptor, or -1.
|
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,
|
backtrace_error_callback error_callback,
|
||||||
void *data)
|
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 size_t prefix_len = strlen (prefix);
|
||||||
const char * const suffix = ".debug";
|
const char * const suffix = ".debug";
|
||||||
const size_t suffix_len = strlen (suffix);
|
const size_t suffix_len = strlen (suffix);
|
||||||
@ -2574,7 +2625,8 @@ static int
|
|||||||
elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
||||||
uintptr_t base_address, backtrace_error_callback error_callback,
|
uintptr_t base_address, backtrace_error_callback error_callback,
|
||||||
void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf,
|
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;
|
struct backtrace_view ehdr_view;
|
||||||
b_elf_ehdr ehdr;
|
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 dynsym_shndx;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct debug_section_info sections[DEBUG_MAX];
|
struct debug_section_info sections[DEBUG_MAX];
|
||||||
|
struct debug_section_info zsections[DEBUG_MAX];
|
||||||
struct backtrace_view symtab_view;
|
struct backtrace_view symtab_view;
|
||||||
int symtab_view_valid;
|
int symtab_view_valid;
|
||||||
struct backtrace_view strtab_view;
|
struct backtrace_view strtab_view;
|
||||||
@ -2606,13 +2659,23 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
int debuglink_view_valid;
|
int debuglink_view_valid;
|
||||||
const char *debuglink_name;
|
const char *debuglink_name;
|
||||||
uint32_t debuglink_crc;
|
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 min_offset;
|
||||||
off_t max_offset;
|
off_t max_offset;
|
||||||
|
off_t debug_size;
|
||||||
struct backtrace_view debug_view;
|
struct backtrace_view debug_view;
|
||||||
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 backtrace_view split_debug_view[DEBUG_MAX];
|
||||||
|
unsigned char split_debug_view_valid[DEBUG_MAX];
|
||||||
struct elf_ppc64_opd_data opd_data, *opd;
|
struct elf_ppc64_opd_data opd_data, *opd;
|
||||||
|
struct dwarf_sections dwarf_sections;
|
||||||
|
struct dwarf_data *fileline_altlink = NULL;
|
||||||
|
|
||||||
if (!debuginfo)
|
if (!debuginfo)
|
||||||
{
|
{
|
||||||
@ -2630,7 +2693,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
debuglink_view_valid = 0;
|
debuglink_view_valid = 0;
|
||||||
debuglink_name = NULL;
|
debuglink_name = NULL;
|
||||||
debuglink_crc = 0;
|
debuglink_crc = 0;
|
||||||
|
debugaltlink_view_valid = 0;
|
||||||
|
debugaltlink_name = NULL;
|
||||||
|
debugaltlink_buildid_data = NULL;
|
||||||
|
debugaltlink_buildid_size = 0;
|
||||||
debug_view_valid = 0;
|
debug_view_valid = 0;
|
||||||
|
memset (&split_debug_view_valid[0], 0, sizeof split_debug_view_valid);
|
||||||
opd = NULL;
|
opd = NULL;
|
||||||
|
|
||||||
if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback,
|
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_size = shstrhdr->sh_size;
|
||||||
shstr_off = shstrhdr->sh_offset;
|
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))
|
error_callback, data, &names_view))
|
||||||
goto fail;
|
goto fail;
|
||||||
names_view_valid = 1;
|
names_view_valid = 1;
|
||||||
@ -2749,6 +2817,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
dynsym_shndx = 0;
|
dynsym_shndx = 0;
|
||||||
|
|
||||||
memset (sections, 0, sizeof sections);
|
memset (sections, 0, sizeof sections);
|
||||||
|
memset (zsections, 0, sizeof zsections);
|
||||||
|
|
||||||
/* Look for the symbol table. */
|
/* Look for the symbol table. */
|
||||||
for (i = 1; i < shnum; ++i)
|
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)
|
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].offset = shdr->sh_offset;
|
||||||
sections[j].size = shdr->sh_size;
|
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
|
/* Read the build ID if present. This could check for any
|
||||||
SHT_NOTE section with the right note name and type, but gdb
|
SHT_NOTE section with the right note name and type, but gdb
|
||||||
looks for a specific section name. */
|
looks for a specific section name. */
|
||||||
if (!debuginfo
|
if ((!debuginfo || with_buildid_data != NULL)
|
||||||
&& !buildid_view_valid
|
&& !buildid_view_valid
|
||||||
&& strcmp (name, ".note.gnu.build-id") == 0)
|
&& 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
|
if (note->type == NT_GNU_BUILD_ID
|
||||||
&& note->namesz == 4
|
&& note->namesz == 4
|
||||||
&& strncmp (note->name, "GNU", 4) == 0
|
&& 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 = ¬e->name[0] + ((note->namesz + 3) & ~ 3);
|
buildid_data = ¬e->name[0] + ((note->namesz + 3) & ~ 3);
|
||||||
buildid_size = note->descsz;
|
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. */
|
/* 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. */
|
/* Read the .opd section on PowerPC64 ELFv1. */
|
||||||
if (ehdr.e_machine == EM_PPC64
|
if (ehdr.e_machine == EM_PPC64
|
||||||
&& (ehdr.e_flags & EF_PPC64_ABI) < 2
|
&& (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. */
|
string table permanently. */
|
||||||
backtrace_release_view (state, &symtab_view, error_callback, data);
|
backtrace_release_view (state, &symtab_view, error_callback, data);
|
||||||
symtab_view_valid = 0;
|
symtab_view_valid = 0;
|
||||||
|
strtab_view_valid = 0;
|
||||||
|
|
||||||
*found_sym = 1;
|
*found_sym = 1;
|
||||||
|
|
||||||
@ -2929,8 +3047,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
if (debuglink_view_valid)
|
if (debuglink_view_valid)
|
||||||
backtrace_release_view (state, &debuglink_view, error_callback,
|
backtrace_release_view (state, &debuglink_view, error_callback,
|
||||||
data);
|
data);
|
||||||
ret = elf_add (state, NULL, d, base_address, error_callback, data,
|
if (debugaltlink_view_valid)
|
||||||
fileline_fn, found_sym, found_dwarf, 0, 1);
|
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)
|
if (ret < 0)
|
||||||
backtrace_close (d, error_callback, data);
|
backtrace_close (d, error_callback, data);
|
||||||
else
|
else
|
||||||
@ -2964,8 +3086,12 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
|
|
||||||
backtrace_release_view (state, &debuglink_view, error_callback,
|
backtrace_release_view (state, &debuglink_view, error_callback,
|
||||||
data);
|
data);
|
||||||
ret = elf_add (state, NULL, d, base_address, error_callback, data,
|
if (debugaltlink_view_valid)
|
||||||
fileline_fn, found_sym, found_dwarf, 0, 1);
|
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)
|
if (ret < 0)
|
||||||
backtrace_close (d, error_callback, data);
|
backtrace_close (d, error_callback, data);
|
||||||
else
|
else
|
||||||
@ -2980,22 +3106,66 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
debuglink_view_valid = 0;
|
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
|
/* 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;
|
min_offset = 0;
|
||||||
max_offset = 0;
|
max_offset = 0;
|
||||||
|
debug_size = 0;
|
||||||
for (i = 0; i < (int) DEBUG_MAX; ++i)
|
for (i = 0; i < (int) DEBUG_MAX; ++i)
|
||||||
{
|
{
|
||||||
off_t end;
|
off_t end;
|
||||||
|
|
||||||
if (sections[i].size == 0)
|
if (sections[i].size != 0)
|
||||||
continue;
|
{
|
||||||
if (min_offset == 0 || sections[i].offset < min_offset)
|
if (min_offset == 0 || sections[i].offset < min_offset)
|
||||||
min_offset = sections[i].offset;
|
min_offset = sections[i].offset;
|
||||||
end = sections[i].offset + sections[i].size;
|
end = sections[i].offset + sections[i].size;
|
||||||
if (end > max_offset)
|
if (end > max_offset)
|
||||||
max_offset = end;
|
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)
|
if (min_offset == 0 || max_offset == 0)
|
||||||
{
|
{
|
||||||
@ -3004,11 +3174,45 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!backtrace_get_view (state, descriptor, min_offset,
|
/* If the total debug section size is large, assume that there are
|
||||||
max_offset - min_offset,
|
gaps between the sections, and read them individually. */
|
||||||
error_callback, data, &debug_view))
|
|
||||||
goto fail;
|
if (max_offset - min_offset < 0x20000000
|
||||||
debug_view_valid = 1;
|
|| 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 = §ions[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. */
|
/* We've read all we need from the executable. */
|
||||||
if (!backtrace_close (descriptor, error_callback, data))
|
if (!backtrace_close (descriptor, error_callback, data))
|
||||||
@ -3016,28 +3220,33 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
descriptor = -1;
|
descriptor = -1;
|
||||||
|
|
||||||
using_debug_view = 0;
|
using_debug_view = 0;
|
||||||
for (i = 0; i < (int) DEBUG_MAX; ++i)
|
if (debug_view_valid)
|
||||||
{
|
{
|
||||||
if (sections[i].size == 0)
|
for (i = 0; i < (int) DEBUG_MAX; ++i)
|
||||||
sections[i].data = NULL;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
sections[i].data = ((const unsigned char *) debug_view.data
|
if (sections[i].size == 0)
|
||||||
+ (sections[i].offset - min_offset));
|
sections[i].data = NULL;
|
||||||
if (i < ZDEBUG_INFO)
|
else
|
||||||
++using_debug_view;
|
{
|
||||||
|
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). */
|
/* Uncompress the old format (--compress-debug-sections=zlib-gnu). */
|
||||||
|
|
||||||
zdebug_table = NULL;
|
zdebug_table = NULL;
|
||||||
for (i = 0; i < ZDEBUG_INFO; ++i)
|
for (i = 0; i < (int) DEBUG_MAX; ++i)
|
||||||
{
|
{
|
||||||
struct debug_section_info *pz;
|
if (sections[i].size == 0 && zsections[i].size > 0)
|
||||||
|
|
||||||
pz = §ions[i + ZDEBUG_INFO - DEBUG_INFO];
|
|
||||||
if (sections[i].size == 0 && pz->size > 0)
|
|
||||||
{
|
{
|
||||||
unsigned char *uncompressed_data;
|
unsigned char *uncompressed_data;
|
||||||
size_t uncompressed_size;
|
size_t uncompressed_size;
|
||||||
@ -3053,19 +3262,27 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
|
|
||||||
uncompressed_data = NULL;
|
uncompressed_data = NULL;
|
||||||
uncompressed_size = 0;
|
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,
|
error_callback, data,
|
||||||
&uncompressed_data, &uncompressed_size))
|
&uncompressed_data, &uncompressed_size))
|
||||||
goto fail;
|
goto fail;
|
||||||
sections[i].data = uncompressed_data;
|
sections[i].data = uncompressed_data;
|
||||||
sections[i].size = uncompressed_size;
|
sections[i].size = uncompressed_size;
|
||||||
sections[i].compressed = 0;
|
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
|
/* Uncompress the official ELF format
|
||||||
(--compress-debug-sections=zlib-gabi). */
|
(--compress-debug-sections=zlib-gabi). */
|
||||||
for (i = 0; i < ZDEBUG_INFO; ++i)
|
for (i = 0; i < (int) DEBUG_MAX; ++i)
|
||||||
{
|
{
|
||||||
unsigned char *uncompressed_data;
|
unsigned char *uncompressed_data;
|
||||||
size_t uncompressed_size;
|
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].size = uncompressed_size;
|
||||||
sections[i].compressed = 0;
|
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)
|
if (zdebug_table != NULL)
|
||||||
@ -3105,19 +3329,17 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
debug_view_valid = 0;
|
debug_view_valid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!backtrace_dwarf_add (state, base_address,
|
for (i = 0; i < (int) DEBUG_MAX; ++i)
|
||||||
sections[DEBUG_INFO].data,
|
{
|
||||||
sections[DEBUG_INFO].size,
|
dwarf_sections.data[i] = sections[i].data;
|
||||||
sections[DEBUG_LINE].data,
|
dwarf_sections.size[i] = sections[i].size;
|
||||||
sections[DEBUG_LINE].size,
|
}
|
||||||
sections[DEBUG_ABBREV].data,
|
|
||||||
sections[DEBUG_ABBREV].size,
|
if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
|
||||||
sections[DEBUG_RANGES].data,
|
|
||||||
sections[DEBUG_RANGES].size,
|
|
||||||
sections[DEBUG_STR].data,
|
|
||||||
sections[DEBUG_STR].size,
|
|
||||||
ehdr.e_ident[EI_DATA] == ELFDATA2MSB,
|
ehdr.e_ident[EI_DATA] == ELFDATA2MSB,
|
||||||
error_callback, data, fileline_fn))
|
fileline_altlink,
|
||||||
|
error_callback, data, fileline_fn,
|
||||||
|
fileline_entry))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
*found_dwarf = 1;
|
*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);
|
backtrace_release_view (state, &strtab_view, error_callback, data);
|
||||||
if (debuglink_view_valid)
|
if (debuglink_view_valid)
|
||||||
backtrace_release_view (state, &debuglink_view, error_callback, data);
|
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)
|
if (buildid_view_valid)
|
||||||
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);
|
||||||
|
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)
|
if (opd)
|
||||||
backtrace_release_view (state, &opd->view, error_callback, data);
|
backtrace_release_view (state, &opd->view, error_callback, data);
|
||||||
if (descriptor != -1)
|
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,
|
if (elf_add (pd->state, filename, descriptor, info->dlpi_addr,
|
||||||
pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
|
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)
|
if (found_dwarf)
|
||||||
{
|
{
|
||||||
@ -3233,7 +3463,8 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
|
|||||||
struct phdr_data pd;
|
struct phdr_data pd;
|
||||||
|
|
||||||
ret = elf_add (state, filename, descriptor, 0, error_callback, data,
|
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)
|
if (!ret)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -3248,12 +3479,26 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
|
|||||||
|
|
||||||
dl_iterate_phdr (phdr_callback, (void *) &pd);
|
dl_iterate_phdr (phdr_callback, (void *) &pd);
|
||||||
|
|
||||||
|
if (!state->threaded)
|
||||||
|
{
|
||||||
if (found_sym)
|
if (found_sym)
|
||||||
state->syminfo_fn = elf_syminfo;
|
state->syminfo_fn = elf_syminfo;
|
||||||
else if (state->syminfo_fn == NULL)
|
else if (state->syminfo_fn == NULL)
|
||||||
state->syminfo_fn = elf_nosyms;
|
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;
|
*fileline_fn = state->fileline_fn;
|
||||||
|
else
|
||||||
|
*fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
|
||||||
|
|
||||||
if (*fileline_fn == NULL || *fileline_fn == elf_nodebug)
|
if (*fileline_fn == NULL || *fileline_fn == elf_nodebug)
|
||||||
*fileline_fn = elf_fileline_fn;
|
*fileline_fn = elf_fileline_fn;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* fileline.c -- Get file and line number information in a backtrace.
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
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/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifdef BSD
|
#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)
|
||||||
# include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
# include <limits.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
# include <mach-o/dyld.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "backtrace.hpp"
|
#include "backtrace.hpp"
|
||||||
#include "internal.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
|
#ifndef HAVE_GETEXECNAME
|
||||||
# define getexecname() NULL
|
#define getexecname() NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace tracy
|
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
|
/* Initialize the fileline information from the executable. Returns 1
|
||||||
on success, 0 on failure. */
|
on success, 0 on failure. */
|
||||||
|
|
||||||
@ -115,7 +140,10 @@ fileline_initialize (struct backtrace_state *state,
|
|||||||
const char *filename;
|
const char *filename;
|
||||||
char buf[64];
|
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)
|
if (failed)
|
||||||
{
|
{
|
||||||
@ -123,7 +151,10 @@ fileline_initialize (struct backtrace_state *state,
|
|||||||
return 0;
|
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)
|
if (fileline_fn != NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -131,7 +162,7 @@ fileline_initialize (struct backtrace_state *state,
|
|||||||
|
|
||||||
descriptor = -1;
|
descriptor = -1;
|
||||||
called_error_callback = 0;
|
called_error_callback = 0;
|
||||||
for (pass = 0; pass < 5; ++pass)
|
for (pass = 0; pass < 7; ++pass)
|
||||||
{
|
{
|
||||||
int does_not_exist;
|
int does_not_exist;
|
||||||
|
|
||||||
@ -154,6 +185,12 @@ fileline_initialize (struct backtrace_state *state,
|
|||||||
(long) getpid ());
|
(long) getpid ());
|
||||||
filename = buf;
|
filename = buf;
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
filename = sysctl_exec_name1 (state, error_callback, data);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
filename = sysctl_exec_name2 (state, error_callback, data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
@ -194,12 +231,23 @@ fileline_initialize (struct backtrace_state *state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (failed)
|
if (failed)
|
||||||
{
|
{
|
||||||
state->fileline_initialization_failed = 1;
|
if (!state->threaded)
|
||||||
return 0;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
52
libbacktrace/filenames.hpp
Normal file
52
libbacktrace/filenames.hpp
Normal 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
|
@ -1,5 +1,5 @@
|
|||||||
/* internal.h -- Internal header file for stack backtrace library.
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -56,6 +56,8 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_SYNC_FUNCTIONS
|
||||||
|
|
||||||
/* Define out the sync functions. These should never be called if
|
/* Define out the sync functions. These should never be called if
|
||||||
they are not available. */
|
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_test_and_set(A, B) (abort(), 0)
|
||||||
#define __sync_lock_release(A) abort()
|
#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
|
/* We have neither the sync nor the atomic functions. These will
|
||||||
never be called. */
|
never be called. */
|
||||||
|
|
||||||
@ -72,6 +105,9 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||||||
#define backtrace_atomic_store_size_t(p, v) abort()
|
#define backtrace_atomic_store_size_t(p, v) abort()
|
||||||
#define backtrace_atomic_store_int(p, v) abort()
|
#define backtrace_atomic_store_int(p, v) abort()
|
||||||
|
|
||||||
|
#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
|
||||||
|
#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -146,7 +182,7 @@ struct backtrace_view
|
|||||||
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the
|
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the
|
||||||
result in *VIEW. Returns 1 on success, 0 on error. */
|
result in *VIEW. Returns 1 on success, 0 on error. */
|
||||||
extern int backtrace_get_view (struct backtrace_state *state, int descriptor,
|
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,
|
backtrace_error_callback error_callback,
|
||||||
void *data, struct backtrace_view *view);
|
void *data, struct backtrace_view *view);
|
||||||
|
|
||||||
@ -224,6 +260,18 @@ extern int backtrace_vector_release (struct backtrace_state *state,
|
|||||||
backtrace_error_callback error_callback,
|
backtrace_error_callback error_callback,
|
||||||
void *data);
|
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
|
/* Read initial debug data from a descriptor, and set the
|
||||||
fileline_data, syminfo_fn, and syminfo_data fields of STATE.
|
fileline_data, syminfo_fn, and syminfo_data fields of STATE.
|
||||||
Return the fileln_fn field in *FILELN_FN--this is done this way so
|
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,
|
void *data,
|
||||||
fileline *fileline_fn);
|
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. */
|
/* Add file/line information for a DWARF module. */
|
||||||
|
|
||||||
extern int backtrace_dwarf_add (struct backtrace_state *state,
|
extern int backtrace_dwarf_add (struct backtrace_state *state,
|
||||||
uintptr_t base_address,
|
uintptr_t base_address,
|
||||||
const unsigned char* dwarf_info,
|
const struct dwarf_sections *dwarf_sections,
|
||||||
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,
|
|
||||||
int is_bigendian,
|
int is_bigendian,
|
||||||
|
struct dwarf_data *fileline_altlink,
|
||||||
backtrace_error_callback error_callback,
|
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
@ -1,5 +1,5 @@
|
|||||||
/* mmapio.c -- File views using mmap.
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -54,7 +54,7 @@ namespace tracy
|
|||||||
|
|
||||||
int
|
int
|
||||||
backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
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,
|
backtrace_error_callback error_callback,
|
||||||
void *data, struct backtrace_view *view)
|
void *data, struct backtrace_view *view)
|
||||||
{
|
{
|
||||||
@ -63,6 +63,12 @@ backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
|||||||
off_t pageoff;
|
off_t pageoff;
|
||||||
void *map;
|
void *map;
|
||||||
|
|
||||||
|
if ((uint64_t) (size_t) size != size)
|
||||||
|
{
|
||||||
|
error_callback (data, "file size too large", 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pagesize = getpagesize ();
|
pagesize = getpagesize ();
|
||||||
inpage = offset % pagesize;
|
inpage = offset % pagesize;
|
||||||
pageoff = offset - inpage;
|
pageoff = offset - inpage;
|
||||||
@ -92,7 +98,13 @@ backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
|||||||
backtrace_error_callback error_callback,
|
backtrace_error_callback error_callback,
|
||||||
void *data)
|
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);
|
error_callback (data, "munmap", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* posix.c -- POSIX file I/O routines for the backtrace library.
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* sort.c -- Sort without allocating memory
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* state.c -- Create the backtrace state.
|
/* 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.
|
Written by Ian Lance Taylor, Google.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
Loading…
Reference in New Issue
Block a user