Update libbacktrace to dedbe13fda.

This commit is contained in:
Bartosz Taudul 2021-01-31 15:15:59 +01:00 committed by Bartosz Taudul
parent a3bfbab6bd
commit 8bacc7a91c
11 changed files with 1975 additions and 313 deletions

View File

@ -1,5 +1,5 @@
/* alloc.c -- Memory allocation without mmap.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 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 @@
/* backtrace.h -- Public header file for stack backtrace library.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 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 @@
/* dwarf.c -- Get file/line information from DWARF for backtraces.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -1389,7 +1389,7 @@ resolve_string (const struct dwarf_sections *dwarf_sections, int is_dwarf64,
offset = val->u.uint * (is_dwarf64 ? 8 : 4) + str_offsets_base;
if (offset + (is_dwarf64 ? 8 : 4)
>= dwarf_sections->size[DEBUG_STR_OFFSETS])
> dwarf_sections->size[DEBUG_STR_OFFSETS])
{
error_callback (data, "DW_FORM_strx value out of range", 0);
return 0;
@ -1433,7 +1433,7 @@ resolve_addr_index (const struct dwarf_sections *dwarf_sections,
struct dwarf_buf addr_buf;
offset = addr_index * addrsize + addr_base;
if (offset + addrsize >= dwarf_sections->size[DEBUG_ADDR])
if (offset + addrsize > dwarf_sections->size[DEBUG_ADDR])
{
error_callback (data, "DW_FORM_addrx value out of range", 0);
return 0;
@ -1500,9 +1500,11 @@ function_addrs_compare (const void *v1, const void *v2)
return strcmp (a1->function->name, a2->function->name);
}
/* Compare a PC against a function_addrs for bsearch. Note that if
there are multiple ranges containing PC, which one will be returned
is unpredictable. We compensate for that in dwarf_fileline. */
/* Compare a PC against a function_addrs for bsearch. We always
allocate an entra entry at the end of the vector, so that this
routine can safely look at the next entry. Note that if there are
multiple ranges containing PC, which one will be returned is
unpredictable. We compensate for that in dwarf_fileline. */
static int
function_addrs_search (const void *vkey, const void *ventry)
@ -1514,7 +1516,7 @@ function_addrs_search (const void *vkey, const void *ventry)
pc = *key;
if (pc < entry->low)
return -1;
else if (pc >= entry->high)
else if (pc > (entry + 1)->low)
return 1;
else
return 0;
@ -1585,9 +1587,11 @@ unit_addrs_compare (const void *v1, const void *v2)
return 0;
}
/* Compare a PC against a unit_addrs for bsearch. Note that if there
are multiple ranges containing PC, which one will be returned is
unpredictable. We compensate for that in dwarf_fileline. */
/* Compare a PC against a unit_addrs for bsearch. We always allocate
an entry entry at the end of the vector, so that this routine can
safely look at the next entry. Note that if there are multiple
ranges containing PC, which one will be returned is unpredictable.
We compensate for that in dwarf_fileline. */
static int
unit_addrs_search (const void *vkey, const void *ventry)
@ -1599,7 +1603,7 @@ unit_addrs_search (const void *vkey, const void *ventry)
pc = *key;
if (pc < entry->low)
return -1;
else if (pc >= entry->high)
else if (pc > (entry + 1)->low)
return 1;
else
return 0;
@ -2427,6 +2431,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
size_t i;
struct unit **pu;
size_t unit_offset = 0;
struct unit_addrs *pa;
memset (&addrs->vec, 0, sizeof addrs->vec);
memset (&unit_vec->vec, 0, sizeof unit_vec->vec);
@ -2567,6 +2572,17 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
if (info.reported_underflow)
goto fail;
/* Add a trailing addrs entry, but don't include it in addrs->count. */
pa = ((struct unit_addrs *)
backtrace_vector_grow (state, sizeof (struct unit_addrs),
error_callback, data, &addrs->vec));
if (pa == NULL)
goto fail;
pa->low = 0;
--pa->low;
pa->high = pa->low;
pa->u = NULL;
unit_vec->vec = units;
unit_vec->count = units_count;
return 1;
@ -2664,9 +2680,10 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
++hdr->dirs_count;
}
hdr->dirs = NULL;
if (hdr->dirs_count != 0)
{
/* The index of the first entry in the list of directories is 1. Index 0 is
used for the current directory of the compilation. To simplify index
handling, we set entry 0 to the compilation unit directory. */
++hdr->dirs_count;
hdr->dirs = ((const char **)
backtrace_alloc (state,
hdr->dirs_count * sizeof (const char *),
@ -2674,9 +2691,9 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
hdr_buf->data));
if (hdr->dirs == NULL)
return 0;
}
i = 0;
hdr->dirs[0] = u->comp_dir;
i = 1;
while (*hdr_buf->buf != '\0')
{
if (hdr_buf->reported_underflow)
@ -2703,6 +2720,10 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
++hdr->filenames_count;
}
/* The index of the first entry in the list of file names is 1. Index 0 is
used for the DW_AT_name of the compilation unit. To simplify index
handling, we set entry 0 to the compilation unit file name. */
++hdr->filenames_count;
hdr->filenames = ((const char **)
backtrace_alloc (state,
hdr->filenames_count * sizeof (char *),
@ -2710,7 +2731,8 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
hdr_buf->data));
if (hdr->filenames == NULL)
return 0;
i = 0;
hdr->filenames[0] = u->filename;
i = 1;
while (*hdr_buf->buf != '\0')
{
const char *filename;
@ -2724,7 +2746,7 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
return 0;
dir_index = read_uleb128 (hdr_buf);
if (IS_ABSOLUTE_PATH (filename)
|| (dir_index == 0 && u->comp_dir == NULL))
|| (dir_index < hdr->dirs_count && hdr->dirs[dir_index] == NULL))
hdr->filenames[i] = filename;
else
{
@ -2733,10 +2755,8 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
size_t filename_len;
char *s;
if (dir_index == 0)
dir = u->comp_dir;
else if (dir_index - 1 < hdr->dirs_count)
dir = hdr->dirs[dir_index - 1];
if (dir_index < hdr->dirs_count)
dir = hdr->dirs[dir_index];
else
{
dwarf_buf_error (hdr_buf,
@ -3024,8 +3044,8 @@ read_line_header (struct backtrace_state *state, struct dwarf_data *ddata,
static int
read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
struct unit *u, const struct line_header *hdr,
struct dwarf_buf *line_buf, struct line_vector *vec)
const struct line_header *hdr, struct dwarf_buf *line_buf,
struct line_vector *vec)
{
uint64_t address;
unsigned int op_index;
@ -3035,8 +3055,8 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
address = 0;
op_index = 0;
if (hdr->filenames_count > 0)
reset_filename = hdr->filenames[0];
if (hdr->filenames_count > 1)
reset_filename = hdr->filenames[1];
else
reset_filename = "";
filename = reset_filename;
@ -3101,10 +3121,8 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
size_t f_len;
char *p;
if (dir_index == 0 && hdr->version < 5)
dir = u->comp_dir;
else if (dir_index - 1 < hdr->dirs_count)
dir = hdr->dirs[dir_index - 1];
if (dir_index < hdr->dirs_count)
dir = hdr->dirs[dir_index];
else
{
dwarf_buf_error (line_buf,
@ -3171,14 +3189,14 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
filename = "";
else
{
if (fileno - 1 >= hdr->filenames_count)
if (fileno >= hdr->filenames_count)
{
dwarf_buf_error (line_buf,
("invalid file number in "
"line number program"));
return 0;
}
filename = hdr->filenames[fileno - 1];
filename = hdr->filenames[fileno];
}
}
break;
@ -3268,7 +3286,7 @@ read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
if (!read_line_header (state, ddata, u, is_dwarf64, &line_buf, hdr))
goto fail;
if (!read_line_program (state, ddata, u, hdr, &line_buf, &vec))
if (!read_line_program (state, ddata, hdr, &line_buf, &vec))
goto fail;
if (line_buf.reported_underflow)
@ -3609,7 +3627,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
function->caller_filename = "";
else
{
if (val.u.uint - 1 >= lhdr->filenames_count)
if (val.u.uint >= lhdr->filenames_count)
{
dwarf_buf_error (unit_buf,
("invalid file number in "
@ -3617,7 +3635,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
return 0;
}
function->caller_filename =
lhdr->filenames[val.u.uint - 1];
lhdr->filenames[val.u.uint];
}
}
break;
@ -3740,8 +3758,23 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
if (fvec.count > 0)
{
struct function_addrs *p;
struct function_addrs *faddrs;
/* Allocate a trailing entry, but don't include it
in fvec.count. */
p = ((struct function_addrs *)
backtrace_vector_grow (state,
sizeof (struct function_addrs),
error_callback, data,
&fvec.vec));
if (p == NULL)
return 0;
p->low = 0;
--p->low;
p->high = p->low;
p->function = NULL;
if (!backtrace_vector_release (state, &fvec.vec,
error_callback, data))
return 0;
@ -3775,6 +3808,7 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
struct function_vector lvec;
struct function_vector *pfvec;
struct dwarf_buf unit_buf;
struct function_addrs *p;
struct function_addrs *addrs;
size_t addrs_count;
@ -3806,6 +3840,18 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
if (pfvec->count == 0)
return;
/* Allocate a trailing entry, but don't include it in
pfvec->count. */
p = ((struct function_addrs *)
backtrace_vector_grow (state, sizeof (struct function_addrs),
error_callback, data, &pfvec->vec));
if (p == NULL)
return;
p->low = 0;
--p->low;
p->high = p->low;
p->function = NULL;
addrs_count = pfvec->count;
if (fvec == NULL)
@ -3842,30 +3888,54 @@ report_inlined_functions (uintptr_t pc, struct function *function,
backtrace_full_callback callback, void *data,
const char **filename, int *lineno)
{
struct function_addrs *function_addrs;
struct function_addrs *p;
struct function_addrs *match;
struct function *inlined;
int ret;
if (function->function_addrs_count == 0)
return 0;
function_addrs = ((struct function_addrs *)
/* Our search isn't safe if pc == -1, as that is the sentinel
value. */
if (pc + 1 == 0)
return 0;
p = ((struct function_addrs *)
bsearch (&pc, function->function_addrs,
function->function_addrs_count,
sizeof (struct function_addrs),
function_addrs_search));
if (function_addrs == NULL)
if (p == NULL)
return 0;
while (((size_t) (function_addrs - function->function_addrs) + 1
< function->function_addrs_count)
&& pc >= (function_addrs + 1)->low
&& pc < (function_addrs + 1)->high)
++function_addrs;
/* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are
sorted by low, so if pc > p->low we are at the end of a range of
function_addrs with the same low value. If pc == p->low walk
forward to the end of the range with that low value. Then walk
backward and use the first range that includes pc. */
while (pc == (p + 1)->low)
++p;
match = NULL;
while (1)
{
if (pc < p->high)
{
match = p;
break;
}
if (p == function->function_addrs)
break;
if ((p - 1)->low < p->low)
break;
--p;
}
if (match == NULL)
return 0;
/* We found an inlined call. */
inlined = function_addrs->function;
inlined = match->function;
/* Report any calls inlined into this one. */
ret = report_inlined_functions (pc, inlined, callback, data,
@ -3874,7 +3944,7 @@ report_inlined_functions (uintptr_t pc, struct function *function,
return ret;
/* Report this inlined call. */
ret = callback (data, pc, function_addrs->low, *filename, *lineno, inlined->name);
ret = callback (data, pc, match->low, *filename, *lineno, inlined->name);
if (ret != 0)
return ret;
@ -3898,11 +3968,13 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
int *found)
{
struct unit_addrs *entry;
int found_entry;
struct unit *u;
int new_data;
struct line *lines;
struct line *ln;
struct function_addrs *function_addrs;
struct function_addrs *p;
struct function_addrs *fmatch;
struct function *function;
const char *filename;
int lineno;
@ -3910,8 +3982,10 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
*found = 1;
/* Find an address range that includes PC. */
entry = (ddata->addrs_count == 0
/* Find an address range that includes PC. Our search isn't safe if
PC == -1, as we use that as a sentinel value, so skip the search
in that case. */
entry = (ddata->addrs_count == 0 || pc + 1 == 0
? NULL
: (struct unit_addrs*)bsearch (&pc, ddata->addrs, ddata->addrs_count,
sizeof (struct unit_addrs), unit_addrs_search));
@ -3922,14 +3996,32 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
return 0;
}
/* If there are multiple ranges that contain PC, use the last one,
in order to produce predictable results. If we assume that all
ranges are properly nested, then the last range will be the
smallest one. */
while ((size_t) (entry - ddata->addrs) + 1 < ddata->addrs_count
&& pc >= (entry + 1)->low
&& pc < (entry + 1)->high)
/* Here pc >= entry->low && pc < (entry + 1)->low. The unit_addrs
are sorted by low, so if pc > p->low we are at the end of a range
of unit_addrs with the same low value. If pc == p->low walk
forward to the end of the range with that low value. Then walk
backward and use the first range that includes pc. */
while (pc == (entry + 1)->low)
++entry;
found_entry = 0;
while (1)
{
if (pc < entry->high)
{
found_entry = 1;
break;
}
if (entry == ddata->addrs)
break;
if ((entry - 1)->low < entry->low)
break;
--entry;
}
if (!found_entry)
{
*found = 0;
return 0;
}
/* We need the lines, lines_count, function_addrs,
function_addrs_count fields of u. If they are not set, we need
@ -3965,6 +4057,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
new_data = 0;
if (lines == NULL)
{
struct function_addrs *function_addrs;
size_t function_addrs_count;
struct line_header lhdr;
size_t count;
@ -4081,24 +4174,39 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
if (entry->u->function_addrs_count == 0)
return callback (data, pc, 0, ln->filename, ln->lineno, NULL);
function_addrs = ((struct function_addrs *)
p = ((struct function_addrs *)
bsearch (&pc, entry->u->function_addrs,
entry->u->function_addrs_count,
sizeof (struct function_addrs),
function_addrs_search));
if (function_addrs == NULL)
if (p == NULL)
return callback (data, pc, 0, ln->filename, ln->lineno, NULL);
/* If there are multiple function ranges that contain PC, use the
last one, in order to produce predictable results. */
/* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are
sorted by low, so if pc > p->low we are at the end of a range of
function_addrs with the same low value. If pc == p->low walk
forward to the end of the range with that low value. Then walk
backward and use the first range that includes pc. */
while (pc == (p + 1)->low)
++p;
fmatch = NULL;
while (1)
{
if (pc < p->high)
{
fmatch = p;
break;
}
if (p == entry->u->function_addrs)
break;
if ((p - 1)->low < p->low)
break;
--p;
}
if (fmatch == NULL)
return callback (data, pc, 0, ln->filename, ln->lineno, NULL);
while (((size_t) (function_addrs - entry->u->function_addrs + 1)
< entry->u->function_addrs_count)
&& pc >= (function_addrs + 1)->low
&& pc < (function_addrs + 1)->high)
++function_addrs;
function = function_addrs->function;
function = fmatch->function;
filename = ln->filename;
lineno = ln->lineno;
@ -4108,7 +4216,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
if (ret != 0)
return ret;
return callback (data, pc, function_addrs->low, filename, lineno, function->name);
return callback (data, pc, fmatch->low, filename, lineno, function->name);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* fileline.c -- Get file and line number information in a backtrace.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -43,28 +43,15 @@ POSSIBILITY OF SUCH DAMAGE. */
#include <sys/sysctl.h>
#endif
#ifdef HAVE_MACH_O_DYLD_H
#include <mach-o/dyld.h>
#endif
#include "backtrace.hpp"
#include "internal.hpp"
#ifndef HAVE_GETEXECNAME
# ifdef __APPLE__
# include <mach-o/dyld.h>
static const char* getexecname()
{
static char execname[PATH_MAX+1];
uint32_t size = sizeof( execname );
if( _NSGetExecutablePath( execname, &size ) == 0 )
{
return execname;
}
else
{
return nullptr;
}
}
# else
#define getexecname() NULL
# endif
#endif
namespace tracy
@ -142,6 +129,35 @@ sysctl_exec_name2 (struct backtrace_state *state,
#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
#ifdef HAVE_MACH_O_DYLD_H
static char *
macho_get_executable_path (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data)
{
uint32_t len;
char *name;
len = 0;
if (_NSGetExecutablePath (NULL, &len) == 0)
return NULL;
name = (char *) backtrace_alloc (state, len, error_callback, data);
if (name == NULL)
return NULL;
if (_NSGetExecutablePath (name, &len) != 0)
{
backtrace_free (state, name, len, error_callback, data);
return NULL;
}
return name;
}
#else /* !defined (HAVE_MACH_O_DYLD_H) */
#define macho_get_executable_path(state, error_callback, data) NULL
#endif /* !defined (HAVE_MACH_O_DYLD_H) */
/* Initialize the fileline information from the executable. Returns 1
on success, 0 on failure. */
@ -179,7 +195,7 @@ fileline_initialize (struct backtrace_state *state,
descriptor = -1;
called_error_callback = 0;
for (pass = 0; pass < 7; ++pass)
for (pass = 0; pass < 8; ++pass)
{
int does_not_exist;
@ -208,6 +224,9 @@ fileline_initialize (struct backtrace_state *state,
case 6:
filename = sysctl_exec_name2 (state, error_callback, data);
break;
case 7:
filename = macho_get_executable_path (state, error_callback, data);
break;
default:
abort ();
}
@ -302,4 +321,31 @@ backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
return 1;
}
/* A backtrace_syminfo_callback that can call into a
backtrace_full_callback, used when we have a symbol table but no
debug info. */
void
backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
const char *symname,
uintptr_t symval ATTRIBUTE_UNUSED,
uintptr_t symsize ATTRIBUTE_UNUSED)
{
struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
bdata->ret = bdata->full_callback (bdata->full_data, pc, 0, NULL, 0, symname);
}
/* An error callback that corresponds to
backtrace_syminfo_to_full_callback. */
void
backtrace_syminfo_to_full_error_callback (void *data, const char *msg,
int errnum)
{
struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
bdata->full_error_callback (bdata->full_data, msg, errnum);
}
}

View File

@ -1,5 +1,5 @@
/* internal.h -- Internal header file for stack backtrace library.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -30,8 +30,8 @@ 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 TRACY_BACKTRACE_INTERNAL_H
#define TRACY_BACKTRACE_INTERNAL_H
#ifndef BACKTRACE_INTERNAL_H
#define BACKTRACE_INTERNAL_H
/* We assume that <sys/types.h> and "backtrace.h" have already been
included. */
@ -56,6 +56,14 @@ POSSIBILITY OF SUCH DAMAGE. */
# endif
#endif
#ifndef ATTRIBUTE_FALLTHROUGH
# if (GCC_VERSION >= 7000)
# define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))
# else
# define ATTRIBUTE_FALLTHROUGH
# endif
#endif
#ifndef HAVE_SYNC_FUNCTIONS
/* Define out the sync functions. These should never be called if
@ -329,6 +337,31 @@ extern int backtrace_dwarf_add (struct backtrace_state *state,
void *data, fileline *fileline_fn,
struct dwarf_data **fileline_entry);
/* A data structure to pass to backtrace_syminfo_to_full. */
struct backtrace_call_full
{
backtrace_full_callback full_callback;
backtrace_error_callback full_error_callback;
void *full_data;
int ret;
};
/* A backtrace_syminfo_callback that can call into a
backtrace_full_callback, used when we have a symbol table but no
debug info. */
extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
const char *symname,
uintptr_t symval,
uintptr_t symsize);
/* An error callback that corresponds to
backtrace_syminfo_to_full_callback. */
extern void backtrace_syminfo_to_full_error_callback (void *, const char *,
int);
/* A test-only hook for elf_uncompress_zdebug. */
extern int backtrace_uncompress_zdebug (struct backtrace_state *,
@ -338,6 +371,15 @@ extern int backtrace_uncompress_zdebug (struct backtrace_state *,
unsigned char **uncompressed,
size_t *uncompressed_size);
/* A test-only hook for elf_uncompress_lzma. */
extern int backtrace_uncompress_lzma (struct backtrace_state *,
const unsigned char *compressed,
size_t compressed_size,
backtrace_error_callback, void *data,
unsigned char **uncompressed,
size_t *uncompressed_size);
}
#endif

View File

@ -1,5 +1,5 @@
/* elf.c -- Get debug data from a Mach-O file for backtraces.
Copyright (C) 2020 Free Software Foundation, Inc.
Copyright (C) 2020-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -78,7 +78,7 @@ struct macho_header_64
struct macho_header_fat
{
uint32_t magic; /* Magic number (MACH_O_MH_MAGIC_FAT) */
uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */
uint32_t nfat_arch; /* Number of components */
};
@ -88,6 +88,8 @@ struct macho_header_fat
#define MACH_O_MH_MAGIC_64 0xfeedfacf
#define MACH_O_MH_MAGIC_FAT 0xcafebabe
#define MACH_O_MH_CIGAM_FAT 0xbebafeca
#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf
#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca
/* Value for the header filetype field. */
@ -108,6 +110,20 @@ struct macho_fat_arch
uint32_t align; /* Alignment of this entry */
};
/* A component of a 64-bit fat file. This is used if the magic field
is MAGIC_FAT_64. This is only used when some file size or file
offset is too large to represent in the 32-bit format. */
struct macho_fat_arch_64
{
uint32_t cputype; /* CPU type */
uint32_t cpusubtype; /* CPU subtype */
uint64_t offset; /* File offset of this entry */
uint64_t size; /* Size of this entry */
uint32_t align; /* Alignment of this entry */
uint32_t reserved; /* Reserved */
};
/* Values for the fat_arch cputype field (and the header cputype
field). */
@ -115,9 +131,11 @@ struct macho_fat_arch
#define MACH_O_CPU_TYPE_X86 7
#define MACH_O_CPU_TYPE_ARM 12
#define MACH_O_CPU_TYPE_PPC 18
#define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)
#define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)
#define MACH_O_CPU_TYPE_PPC64 (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64)
/* The header of a load command. */
@ -743,14 +761,14 @@ static int
macho_add_fat (struct backtrace_state *state, const char *filename,
int descriptor, int swapped, off_t offset,
const unsigned char *match_uuid, uintptr_t base_address,
int skip_symtab, uint32_t nfat_arch,
int skip_symtab, uint32_t nfat_arch, int is_64,
backtrace_error_callback error_callback, void *data,
fileline *fileline_fn, int *found_sym)
{
int arch_view_valid;
unsigned int cputype;
size_t arch_size;
struct backtrace_view arch_view;
size_t archoffset;
unsigned int i;
arch_view_valid = 0;
@ -763,46 +781,69 @@ macho_add_fat (struct backtrace_state *state, const char *filename,
cputype = MACH_O_CPU_TYPE_ARM64;
#elif defined (__arm__)
cputype = MACH_O_CPU_TYPE_ARM;
#elif defined (__ppc__)
cputype = MACH_O_CPU_TYPE_PPC;
#elif defined (__ppc64__)
cputype = MACH_O_CPU_TYPE_PPC64;
#else
error_callback (data, "unknown Mach-O architecture", 0);
goto fail;
#endif
if (is_64)
arch_size = sizeof (struct macho_fat_arch_64);
else
arch_size = sizeof (struct macho_fat_arch);
if (!backtrace_get_view (state, descriptor, offset,
nfat_arch * sizeof (struct macho_fat_arch),
nfat_arch * arch_size,
error_callback, data, &arch_view))
goto fail;
archoffset = 0;
for (i = 0; i < nfat_arch; ++i)
{
struct macho_fat_arch fat_arch;
uint32_t fcputype;
uint64_t foffset;
memcpy (&fat_arch,
((const char *) arch_view.data
+ i * sizeof (struct macho_fat_arch)),
sizeof fat_arch);
if (is_64)
{
struct macho_fat_arch_64 fat_arch_64;
fcputype = fat_arch.cputype;
memcpy (&fat_arch_64,
(const char *) arch_view.data + i * arch_size,
arch_size);
fcputype = fat_arch_64.cputype;
foffset = fat_arch_64.offset;
if (swapped)
{
fcputype = __builtin_bswap32 (fcputype);
foffset = __builtin_bswap64 (foffset);
}
}
else
{
struct macho_fat_arch fat_arch_32;
memcpy (&fat_arch_32,
(const char *) arch_view.data + i * arch_size,
arch_size);
fcputype = fat_arch_32.cputype;
foffset = (uint64_t) fat_arch_32.offset;
if (swapped)
{
fcputype = __builtin_bswap32 (fcputype);
foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset);
}
}
if (fcputype == cputype)
{
uint32_t foffset;
/* FIXME: What about cpusubtype? */
foffset = fat_arch.offset;
if (swapped)
foffset = __builtin_bswap32 (foffset);
backtrace_release_view (state, &arch_view, error_callback, data);
return macho_add (state, filename, descriptor, foffset, match_uuid,
base_address, skip_symtab, error_callback, data,
fileline_fn, found_sym);
}
archoffset += sizeof (struct macho_fat_arch);
}
error_callback (data, "could not find executable in fat file", 0);
@ -871,6 +912,7 @@ macho_add_dsym (struct backtrace_state *state, const char *filename,
dsymsuffixdirlen = strlen (dsymsuffixdir);
dsymlen = (dirnamelen
+ 1
+ basenamelen
+ dsymsuffixdirlen
+ basenamelen
@ -893,7 +935,7 @@ macho_add_dsym (struct backtrace_state *state, const char *filename,
if (diralc != NULL)
{
backtrace_free (state, diralc, dirnamelen, error_callback, data);
backtrace_free (state, diralc, dirnamelen + 1, error_callback, data);
diralc = NULL;
}
@ -983,6 +1025,7 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor,
hdroffset = offset + sizeof (struct macho_header_64);
break;
case MACH_O_MH_MAGIC_FAT:
case MACH_O_MH_MAGIC_FAT_64:
{
struct macho_header_fat fat_header;
@ -990,10 +1033,12 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor,
memcpy (&fat_header, &header, sizeof fat_header);
return macho_add_fat (state, filename, descriptor, 0, hdroffset,
match_uuid, base_address, skip_symtab,
fat_header.nfat_arch, error_callback, data,
fileline_fn, found_sym);
fat_header.nfat_arch,
header.magic == MACH_O_MH_MAGIC_FAT_64,
error_callback, data, fileline_fn, found_sym);
}
case MACH_O_MH_CIGAM_FAT:
case MACH_O_MH_CIGAM_FAT_64:
{
struct macho_header_fat fat_header;
uint32_t nfat_arch;
@ -1003,8 +1048,9 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor,
nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
return macho_add_fat (state, filename, descriptor, 1, hdroffset,
match_uuid, base_address, skip_symtab,
nfat_arch, error_callback, data,
fileline_fn, found_sym);
nfat_arch,
header.magic == MACH_O_MH_CIGAM_FAT_64,
error_callback, data, fileline_fn, found_sym);
}
default:
error_callback (data, "executable file is not in Mach-O format", 0);

View File

@ -1,5 +1,5 @@
/* mmapio.c -- File views using mmap.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@ -40,6 +40,10 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "backtrace.hpp"
#include "internal.hpp"
#ifndef HAVE_DECL_GETPAGESIZE
extern int getpagesize (void);
#endif
#ifndef MAP_FAILED
#define MAP_FAILED ((void *)-1)
#endif
@ -101,10 +105,10 @@ backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
union {
const void *cv;
void *v;
};
} cc;
cv = view->base;
if (munmap (v, view->len) < 0)
cc.cv = view->base;
if (munmap (cc.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-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 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-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 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-2020 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without