mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-22 22:44:34 +00:00
Update libbacktrace to dedbe13fda.
This commit is contained in:
parent
a3bfbab6bd
commit
8bacc7a91c
@ -1,5 +1,5 @@
|
|||||||
/* alloc.c -- Memory allocation without mmap.
|
/* 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.
|
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 @@
|
|||||||
/* backtrace.h -- Public header file for stack backtrace library.
|
/* 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.
|
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 @@
|
|||||||
/* dwarf.c -- Get file/line information from DWARF for backtraces.
|
/* 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.
|
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
|
||||||
@ -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;
|
offset = val->u.uint * (is_dwarf64 ? 8 : 4) + str_offsets_base;
|
||||||
if (offset + (is_dwarf64 ? 8 : 4)
|
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);
|
error_callback (data, "DW_FORM_strx value out of range", 0);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1433,7 +1433,7 @@ resolve_addr_index (const struct dwarf_sections *dwarf_sections,
|
|||||||
struct dwarf_buf addr_buf;
|
struct dwarf_buf addr_buf;
|
||||||
|
|
||||||
offset = addr_index * addrsize + addr_base;
|
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);
|
error_callback (data, "DW_FORM_addrx value out of range", 0);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1500,9 +1500,11 @@ function_addrs_compare (const void *v1, const void *v2)
|
|||||||
return strcmp (a1->function->name, a2->function->name);
|
return strcmp (a1->function->name, a2->function->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare a PC against a function_addrs for bsearch. Note that if
|
/* Compare a PC against a function_addrs for bsearch. We always
|
||||||
there are multiple ranges containing PC, which one will be returned
|
allocate an entra entry at the end of the vector, so that this
|
||||||
is unpredictable. We compensate for that in dwarf_fileline. */
|
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
|
static int
|
||||||
function_addrs_search (const void *vkey, const void *ventry)
|
function_addrs_search (const void *vkey, const void *ventry)
|
||||||
@ -1514,7 +1516,7 @@ function_addrs_search (const void *vkey, const void *ventry)
|
|||||||
pc = *key;
|
pc = *key;
|
||||||
if (pc < entry->low)
|
if (pc < entry->low)
|
||||||
return -1;
|
return -1;
|
||||||
else if (pc >= entry->high)
|
else if (pc > (entry + 1)->low)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
@ -1585,9 +1587,11 @@ unit_addrs_compare (const void *v1, const void *v2)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare a PC against a unit_addrs for bsearch. Note that if there
|
/* Compare a PC against a unit_addrs for bsearch. We always allocate
|
||||||
are multiple ranges containing PC, which one will be returned is
|
an entry entry at the end of the vector, so that this routine can
|
||||||
unpredictable. We compensate for that in dwarf_fileline. */
|
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
|
static int
|
||||||
unit_addrs_search (const void *vkey, const void *ventry)
|
unit_addrs_search (const void *vkey, const void *ventry)
|
||||||
@ -1599,7 +1603,7 @@ unit_addrs_search (const void *vkey, const void *ventry)
|
|||||||
pc = *key;
|
pc = *key;
|
||||||
if (pc < entry->low)
|
if (pc < entry->low)
|
||||||
return -1;
|
return -1;
|
||||||
else if (pc >= entry->high)
|
else if (pc > (entry + 1)->low)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
@ -2427,6 +2431,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
|
|||||||
size_t i;
|
size_t i;
|
||||||
struct unit **pu;
|
struct unit **pu;
|
||||||
size_t unit_offset = 0;
|
size_t unit_offset = 0;
|
||||||
|
struct unit_addrs *pa;
|
||||||
|
|
||||||
memset (&addrs->vec, 0, sizeof addrs->vec);
|
memset (&addrs->vec, 0, sizeof addrs->vec);
|
||||||
memset (&unit_vec->vec, 0, sizeof unit_vec->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)
|
if (info.reported_underflow)
|
||||||
goto fail;
|
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->vec = units;
|
||||||
unit_vec->count = units_count;
|
unit_vec->count = units_count;
|
||||||
return 1;
|
return 1;
|
||||||
@ -2664,9 +2680,10 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
|
|||||||
++hdr->dirs_count;
|
++hdr->dirs_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr->dirs = NULL;
|
/* The index of the first entry in the list of directories is 1. Index 0 is
|
||||||
if (hdr->dirs_count != 0)
|
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 **)
|
hdr->dirs = ((const char **)
|
||||||
backtrace_alloc (state,
|
backtrace_alloc (state,
|
||||||
hdr->dirs_count * sizeof (const char *),
|
hdr->dirs_count * sizeof (const char *),
|
||||||
@ -2674,9 +2691,9 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
|
|||||||
hdr_buf->data));
|
hdr_buf->data));
|
||||||
if (hdr->dirs == NULL)
|
if (hdr->dirs == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
hdr->dirs[0] = u->comp_dir;
|
||||||
|
i = 1;
|
||||||
while (*hdr_buf->buf != '\0')
|
while (*hdr_buf->buf != '\0')
|
||||||
{
|
{
|
||||||
if (hdr_buf->reported_underflow)
|
if (hdr_buf->reported_underflow)
|
||||||
@ -2703,6 +2720,10 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
|
|||||||
++hdr->filenames_count;
|
++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 **)
|
hdr->filenames = ((const char **)
|
||||||
backtrace_alloc (state,
|
backtrace_alloc (state,
|
||||||
hdr->filenames_count * sizeof (char *),
|
hdr->filenames_count * sizeof (char *),
|
||||||
@ -2710,7 +2731,8 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
|
|||||||
hdr_buf->data));
|
hdr_buf->data));
|
||||||
if (hdr->filenames == NULL)
|
if (hdr->filenames == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
i = 0;
|
hdr->filenames[0] = u->filename;
|
||||||
|
i = 1;
|
||||||
while (*hdr_buf->buf != '\0')
|
while (*hdr_buf->buf != '\0')
|
||||||
{
|
{
|
||||||
const char *filename;
|
const char *filename;
|
||||||
@ -2724,7 +2746,7 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
|
|||||||
return 0;
|
return 0;
|
||||||
dir_index = read_uleb128 (hdr_buf);
|
dir_index = read_uleb128 (hdr_buf);
|
||||||
if (IS_ABSOLUTE_PATH (filename)
|
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;
|
hdr->filenames[i] = filename;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2733,10 +2755,8 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
|
|||||||
size_t filename_len;
|
size_t filename_len;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
if (dir_index == 0)
|
if (dir_index < hdr->dirs_count)
|
||||||
dir = u->comp_dir;
|
dir = hdr->dirs[dir_index];
|
||||||
else if (dir_index - 1 < hdr->dirs_count)
|
|
||||||
dir = hdr->dirs[dir_index - 1];
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dwarf_buf_error (hdr_buf,
|
dwarf_buf_error (hdr_buf,
|
||||||
@ -3024,8 +3044,8 @@ read_line_header (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
|
read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
|
||||||
struct unit *u, const struct line_header *hdr,
|
const struct line_header *hdr, struct dwarf_buf *line_buf,
|
||||||
struct dwarf_buf *line_buf, struct line_vector *vec)
|
struct line_vector *vec)
|
||||||
{
|
{
|
||||||
uint64_t address;
|
uint64_t address;
|
||||||
unsigned int op_index;
|
unsigned int op_index;
|
||||||
@ -3035,8 +3055,8 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
|
|
||||||
address = 0;
|
address = 0;
|
||||||
op_index = 0;
|
op_index = 0;
|
||||||
if (hdr->filenames_count > 0)
|
if (hdr->filenames_count > 1)
|
||||||
reset_filename = hdr->filenames[0];
|
reset_filename = hdr->filenames[1];
|
||||||
else
|
else
|
||||||
reset_filename = "";
|
reset_filename = "";
|
||||||
filename = reset_filename;
|
filename = reset_filename;
|
||||||
@ -3101,10 +3121,8 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
size_t f_len;
|
size_t f_len;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (dir_index == 0 && hdr->version < 5)
|
if (dir_index < hdr->dirs_count)
|
||||||
dir = u->comp_dir;
|
dir = hdr->dirs[dir_index];
|
||||||
else if (dir_index - 1 < hdr->dirs_count)
|
|
||||||
dir = hdr->dirs[dir_index - 1];
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dwarf_buf_error (line_buf,
|
dwarf_buf_error (line_buf,
|
||||||
@ -3171,14 +3189,14 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
filename = "";
|
filename = "";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (fileno - 1 >= hdr->filenames_count)
|
if (fileno >= hdr->filenames_count)
|
||||||
{
|
{
|
||||||
dwarf_buf_error (line_buf,
|
dwarf_buf_error (line_buf,
|
||||||
("invalid file number in "
|
("invalid file number in "
|
||||||
"line number program"));
|
"line number program"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
filename = hdr->filenames[fileno - 1];
|
filename = hdr->filenames[fileno];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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))
|
if (!read_line_header (state, ddata, u, is_dwarf64, &line_buf, hdr))
|
||||||
goto fail;
|
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;
|
goto fail;
|
||||||
|
|
||||||
if (line_buf.reported_underflow)
|
if (line_buf.reported_underflow)
|
||||||
@ -3609,7 +3627,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
function->caller_filename = "";
|
function->caller_filename = "";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (val.u.uint - 1 >= lhdr->filenames_count)
|
if (val.u.uint >= lhdr->filenames_count)
|
||||||
{
|
{
|
||||||
dwarf_buf_error (unit_buf,
|
dwarf_buf_error (unit_buf,
|
||||||
("invalid file number in "
|
("invalid file number in "
|
||||||
@ -3617,7 +3635,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
function->caller_filename =
|
function->caller_filename =
|
||||||
lhdr->filenames[val.u.uint - 1];
|
lhdr->filenames[val.u.uint];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3740,8 +3758,23 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
|
|
||||||
if (fvec.count > 0)
|
if (fvec.count > 0)
|
||||||
{
|
{
|
||||||
|
struct function_addrs *p;
|
||||||
struct function_addrs *faddrs;
|
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,
|
if (!backtrace_vector_release (state, &fvec.vec,
|
||||||
error_callback, data))
|
error_callback, data))
|
||||||
return 0;
|
return 0;
|
||||||
@ -3775,6 +3808,7 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
struct function_vector lvec;
|
struct function_vector lvec;
|
||||||
struct function_vector *pfvec;
|
struct function_vector *pfvec;
|
||||||
struct dwarf_buf unit_buf;
|
struct dwarf_buf unit_buf;
|
||||||
|
struct function_addrs *p;
|
||||||
struct function_addrs *addrs;
|
struct function_addrs *addrs;
|
||||||
size_t addrs_count;
|
size_t addrs_count;
|
||||||
|
|
||||||
@ -3806,6 +3840,18 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
if (pfvec->count == 0)
|
if (pfvec->count == 0)
|
||||||
return;
|
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;
|
addrs_count = pfvec->count;
|
||||||
|
|
||||||
if (fvec == NULL)
|
if (fvec == NULL)
|
||||||
@ -3842,30 +3888,54 @@ report_inlined_functions (uintptr_t pc, struct function *function,
|
|||||||
backtrace_full_callback callback, void *data,
|
backtrace_full_callback callback, void *data,
|
||||||
const char **filename, int *lineno)
|
const char **filename, int *lineno)
|
||||||
{
|
{
|
||||||
struct function_addrs *function_addrs;
|
struct function_addrs *p;
|
||||||
|
struct function_addrs *match;
|
||||||
struct function *inlined;
|
struct function *inlined;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (function->function_addrs_count == 0)
|
if (function->function_addrs_count == 0)
|
||||||
return 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,
|
bsearch (&pc, function->function_addrs,
|
||||||
function->function_addrs_count,
|
function->function_addrs_count,
|
||||||
sizeof (struct function_addrs),
|
sizeof (struct function_addrs),
|
||||||
function_addrs_search));
|
function_addrs_search));
|
||||||
if (function_addrs == NULL)
|
if (p == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (((size_t) (function_addrs - function->function_addrs) + 1
|
/* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are
|
||||||
< function->function_addrs_count)
|
sorted by low, so if pc > p->low we are at the end of a range of
|
||||||
&& pc >= (function_addrs + 1)->low
|
function_addrs with the same low value. If pc == p->low walk
|
||||||
&& pc < (function_addrs + 1)->high)
|
forward to the end of the range with that low value. Then walk
|
||||||
++function_addrs;
|
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. */
|
/* We found an inlined call. */
|
||||||
|
|
||||||
inlined = function_addrs->function;
|
inlined = match->function;
|
||||||
|
|
||||||
/* Report any calls inlined into this one. */
|
/* Report any calls inlined into this one. */
|
||||||
ret = report_inlined_functions (pc, inlined, callback, data,
|
ret = report_inlined_functions (pc, inlined, callback, data,
|
||||||
@ -3874,7 +3944,7 @@ report_inlined_functions (uintptr_t pc, struct function *function,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Report this inlined call. */
|
/* 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)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -3898,11 +3968,13 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
int *found)
|
int *found)
|
||||||
{
|
{
|
||||||
struct unit_addrs *entry;
|
struct unit_addrs *entry;
|
||||||
|
int found_entry;
|
||||||
struct unit *u;
|
struct unit *u;
|
||||||
int new_data;
|
int new_data;
|
||||||
struct line *lines;
|
struct line *lines;
|
||||||
struct line *ln;
|
struct line *ln;
|
||||||
struct function_addrs *function_addrs;
|
struct function_addrs *p;
|
||||||
|
struct function_addrs *fmatch;
|
||||||
struct function *function;
|
struct function *function;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
int lineno;
|
int lineno;
|
||||||
@ -3910,8 +3982,10 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
|
|
||||||
*found = 1;
|
*found = 1;
|
||||||
|
|
||||||
/* Find an address range that includes PC. */
|
/* Find an address range that includes PC. Our search isn't safe if
|
||||||
entry = (ddata->addrs_count == 0
|
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
|
? NULL
|
||||||
: (struct unit_addrs*)bsearch (&pc, ddata->addrs, ddata->addrs_count,
|
: (struct unit_addrs*)bsearch (&pc, ddata->addrs, ddata->addrs_count,
|
||||||
sizeof (struct unit_addrs), unit_addrs_search));
|
sizeof (struct unit_addrs), unit_addrs_search));
|
||||||
@ -3922,14 +3996,32 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there are multiple ranges that contain PC, use the last one,
|
/* Here pc >= entry->low && pc < (entry + 1)->low. The unit_addrs
|
||||||
in order to produce predictable results. If we assume that all
|
are sorted by low, so if pc > p->low we are at the end of a range
|
||||||
ranges are properly nested, then the last range will be the
|
of unit_addrs with the same low value. If pc == p->low walk
|
||||||
smallest one. */
|
forward to the end of the range with that low value. Then walk
|
||||||
while ((size_t) (entry - ddata->addrs) + 1 < ddata->addrs_count
|
backward and use the first range that includes pc. */
|
||||||
&& pc >= (entry + 1)->low
|
while (pc == (entry + 1)->low)
|
||||||
&& pc < (entry + 1)->high)
|
|
||||||
++entry;
|
++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,
|
/* We need the lines, lines_count, function_addrs,
|
||||||
function_addrs_count fields of u. If they are not set, we need
|
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;
|
new_data = 0;
|
||||||
if (lines == NULL)
|
if (lines == NULL)
|
||||||
{
|
{
|
||||||
|
struct function_addrs *function_addrs;
|
||||||
size_t function_addrs_count;
|
size_t function_addrs_count;
|
||||||
struct line_header lhdr;
|
struct line_header lhdr;
|
||||||
size_t count;
|
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)
|
if (entry->u->function_addrs_count == 0)
|
||||||
return callback (data, pc, 0, ln->filename, ln->lineno, NULL);
|
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,
|
bsearch (&pc, entry->u->function_addrs,
|
||||||
entry->u->function_addrs_count,
|
entry->u->function_addrs_count,
|
||||||
sizeof (struct function_addrs),
|
sizeof (struct function_addrs),
|
||||||
function_addrs_search));
|
function_addrs_search));
|
||||||
if (function_addrs == NULL)
|
if (p == NULL)
|
||||||
return callback (data, pc, 0, ln->filename, ln->lineno, NULL);
|
return callback (data, pc, 0, ln->filename, ln->lineno, NULL);
|
||||||
|
|
||||||
/* If there are multiple function ranges that contain PC, use the
|
/* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are
|
||||||
last one, in order to produce predictable results. */
|
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)
|
function = fmatch->function;
|
||||||
< entry->u->function_addrs_count)
|
|
||||||
&& pc >= (function_addrs + 1)->low
|
|
||||||
&& pc < (function_addrs + 1)->high)
|
|
||||||
++function_addrs;
|
|
||||||
|
|
||||||
function = function_addrs->function;
|
|
||||||
|
|
||||||
filename = ln->filename;
|
filename = ln->filename;
|
||||||
lineno = ln->lineno;
|
lineno = ln->lineno;
|
||||||
@ -4108,7 +4216,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return callback (data, pc, function_addrs->low, filename, lineno, function->name);
|
return callback (data, pc, fmatch->low, filename, lineno, function->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1742
libbacktrace/elf.cpp
1742
libbacktrace/elf.cpp
File diff suppressed because it is too large
Load Diff
@ -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-2020 Free Software Foundation, Inc.
|
Copyright (C) 2012-2021 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
|
||||||
@ -43,28 +43,15 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_MACH_O_DYLD_H
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "backtrace.hpp"
|
#include "backtrace.hpp"
|
||||||
#include "internal.hpp"
|
#include "internal.hpp"
|
||||||
|
|
||||||
#ifndef HAVE_GETEXECNAME
|
#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
|
#define getexecname() NULL
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
@ -142,6 +129,35 @@ sysctl_exec_name2 (struct backtrace_state *state,
|
|||||||
|
|
||||||
#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
|
#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
|
/* Initialize the fileline information from the executable. Returns 1
|
||||||
on success, 0 on failure. */
|
on success, 0 on failure. */
|
||||||
|
|
||||||
@ -179,7 +195,7 @@ fileline_initialize (struct backtrace_state *state,
|
|||||||
|
|
||||||
descriptor = -1;
|
descriptor = -1;
|
||||||
called_error_callback = 0;
|
called_error_callback = 0;
|
||||||
for (pass = 0; pass < 7; ++pass)
|
for (pass = 0; pass < 8; ++pass)
|
||||||
{
|
{
|
||||||
int does_not_exist;
|
int does_not_exist;
|
||||||
|
|
||||||
@ -208,6 +224,9 @@ fileline_initialize (struct backtrace_state *state,
|
|||||||
case 6:
|
case 6:
|
||||||
filename = sysctl_exec_name2 (state, error_callback, data);
|
filename = sysctl_exec_name2 (state, error_callback, data);
|
||||||
break;
|
break;
|
||||||
|
case 7:
|
||||||
|
filename = macho_get_executable_path (state, error_callback, data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
@ -302,4 +321,31 @@ backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
|
|||||||
return 1;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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-2020 Free Software Foundation, Inc.
|
Copyright (C) 2012-2021 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
|
||||||
@ -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
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE. */
|
POSSIBILITY OF SUCH DAMAGE. */
|
||||||
|
|
||||||
#ifndef TRACY_BACKTRACE_INTERNAL_H
|
#ifndef BACKTRACE_INTERNAL_H
|
||||||
#define TRACY_BACKTRACE_INTERNAL_H
|
#define BACKTRACE_INTERNAL_H
|
||||||
|
|
||||||
/* We assume that <sys/types.h> and "backtrace.h" have already been
|
/* We assume that <sys/types.h> and "backtrace.h" have already been
|
||||||
included. */
|
included. */
|
||||||
@ -56,6 +56,14 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ATTRIBUTE_FALLTHROUGH
|
||||||
|
# if (GCC_VERSION >= 7000)
|
||||||
|
# define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))
|
||||||
|
# else
|
||||||
|
# define ATTRIBUTE_FALLTHROUGH
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SYNC_FUNCTIONS
|
#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
|
||||||
@ -329,6 +337,31 @@ extern int backtrace_dwarf_add (struct backtrace_state *state,
|
|||||||
void *data, fileline *fileline_fn,
|
void *data, fileline *fileline_fn,
|
||||||
struct dwarf_data **fileline_entry);
|
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. */
|
/* A test-only hook for elf_uncompress_zdebug. */
|
||||||
|
|
||||||
extern int backtrace_uncompress_zdebug (struct backtrace_state *,
|
extern int backtrace_uncompress_zdebug (struct backtrace_state *,
|
||||||
@ -338,6 +371,15 @@ extern int backtrace_uncompress_zdebug (struct backtrace_state *,
|
|||||||
unsigned char **uncompressed,
|
unsigned char **uncompressed,
|
||||||
size_t *uncompressed_size);
|
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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* elf.c -- Get debug data from a Mach-O file for backtraces.
|
/* 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.
|
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
|
||||||
@ -78,7 +78,7 @@ struct macho_header_64
|
|||||||
|
|
||||||
struct macho_header_fat
|
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 */
|
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_64 0xfeedfacf
|
||||||
#define MACH_O_MH_MAGIC_FAT 0xcafebabe
|
#define MACH_O_MH_MAGIC_FAT 0xcafebabe
|
||||||
#define MACH_O_MH_CIGAM_FAT 0xbebafeca
|
#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. */
|
/* Value for the header filetype field. */
|
||||||
|
|
||||||
@ -108,6 +110,20 @@ struct macho_fat_arch
|
|||||||
uint32_t align; /* Alignment of this entry */
|
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
|
/* Values for the fat_arch cputype field (and the header cputype
|
||||||
field). */
|
field). */
|
||||||
|
|
||||||
@ -115,9 +131,11 @@ struct macho_fat_arch
|
|||||||
|
|
||||||
#define MACH_O_CPU_TYPE_X86 7
|
#define MACH_O_CPU_TYPE_X86 7
|
||||||
#define MACH_O_CPU_TYPE_ARM 12
|
#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_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_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. */
|
/* The header of a load command. */
|
||||||
|
|
||||||
@ -743,14 +761,14 @@ static int
|
|||||||
macho_add_fat (struct backtrace_state *state, const char *filename,
|
macho_add_fat (struct backtrace_state *state, const char *filename,
|
||||||
int descriptor, int swapped, off_t offset,
|
int descriptor, int swapped, off_t offset,
|
||||||
const unsigned char *match_uuid, uintptr_t base_address,
|
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,
|
backtrace_error_callback error_callback, void *data,
|
||||||
fileline *fileline_fn, int *found_sym)
|
fileline *fileline_fn, int *found_sym)
|
||||||
{
|
{
|
||||||
int arch_view_valid;
|
int arch_view_valid;
|
||||||
unsigned int cputype;
|
unsigned int cputype;
|
||||||
|
size_t arch_size;
|
||||||
struct backtrace_view arch_view;
|
struct backtrace_view arch_view;
|
||||||
size_t archoffset;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
arch_view_valid = 0;
|
arch_view_valid = 0;
|
||||||
@ -763,46 +781,69 @@ macho_add_fat (struct backtrace_state *state, const char *filename,
|
|||||||
cputype = MACH_O_CPU_TYPE_ARM64;
|
cputype = MACH_O_CPU_TYPE_ARM64;
|
||||||
#elif defined (__arm__)
|
#elif defined (__arm__)
|
||||||
cputype = MACH_O_CPU_TYPE_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
|
#else
|
||||||
error_callback (data, "unknown Mach-O architecture", 0);
|
error_callback (data, "unknown Mach-O architecture", 0);
|
||||||
goto fail;
|
goto fail;
|
||||||
#endif
|
#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,
|
if (!backtrace_get_view (state, descriptor, offset,
|
||||||
nfat_arch * sizeof (struct macho_fat_arch),
|
nfat_arch * arch_size,
|
||||||
error_callback, data, &arch_view))
|
error_callback, data, &arch_view))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
archoffset = 0;
|
|
||||||
for (i = 0; i < nfat_arch; ++i)
|
for (i = 0; i < nfat_arch; ++i)
|
||||||
{
|
{
|
||||||
struct macho_fat_arch fat_arch;
|
|
||||||
uint32_t fcputype;
|
uint32_t fcputype;
|
||||||
|
uint64_t foffset;
|
||||||
|
|
||||||
memcpy (&fat_arch,
|
if (is_64)
|
||||||
((const char *) arch_view.data
|
{
|
||||||
+ i * sizeof (struct macho_fat_arch)),
|
struct macho_fat_arch_64 fat_arch_64;
|
||||||
sizeof fat_arch);
|
|
||||||
|
|
||||||
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)
|
if (swapped)
|
||||||
|
{
|
||||||
fcputype = __builtin_bswap32 (fcputype);
|
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)
|
if (fcputype == cputype)
|
||||||
{
|
{
|
||||||
uint32_t foffset;
|
|
||||||
|
|
||||||
/* FIXME: What about cpusubtype? */
|
/* FIXME: What about cpusubtype? */
|
||||||
foffset = fat_arch.offset;
|
|
||||||
if (swapped)
|
|
||||||
foffset = __builtin_bswap32 (foffset);
|
|
||||||
backtrace_release_view (state, &arch_view, error_callback, data);
|
backtrace_release_view (state, &arch_view, error_callback, data);
|
||||||
return macho_add (state, filename, descriptor, foffset, match_uuid,
|
return macho_add (state, filename, descriptor, foffset, match_uuid,
|
||||||
base_address, skip_symtab, error_callback, data,
|
base_address, skip_symtab, error_callback, data,
|
||||||
fileline_fn, found_sym);
|
fileline_fn, found_sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
archoffset += sizeof (struct macho_fat_arch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_callback (data, "could not find executable in fat file", 0);
|
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);
|
dsymsuffixdirlen = strlen (dsymsuffixdir);
|
||||||
|
|
||||||
dsymlen = (dirnamelen
|
dsymlen = (dirnamelen
|
||||||
|
+ 1
|
||||||
+ basenamelen
|
+ basenamelen
|
||||||
+ dsymsuffixdirlen
|
+ dsymsuffixdirlen
|
||||||
+ basenamelen
|
+ basenamelen
|
||||||
@ -893,7 +935,7 @@ macho_add_dsym (struct backtrace_state *state, const char *filename,
|
|||||||
|
|
||||||
if (diralc != NULL)
|
if (diralc != NULL)
|
||||||
{
|
{
|
||||||
backtrace_free (state, diralc, dirnamelen, error_callback, data);
|
backtrace_free (state, diralc, dirnamelen + 1, error_callback, data);
|
||||||
diralc = NULL;
|
diralc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,6 +1025,7 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor,
|
|||||||
hdroffset = offset + sizeof (struct macho_header_64);
|
hdroffset = offset + sizeof (struct macho_header_64);
|
||||||
break;
|
break;
|
||||||
case MACH_O_MH_MAGIC_FAT:
|
case MACH_O_MH_MAGIC_FAT:
|
||||||
|
case MACH_O_MH_MAGIC_FAT_64:
|
||||||
{
|
{
|
||||||
struct macho_header_fat fat_header;
|
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);
|
memcpy (&fat_header, &header, sizeof fat_header);
|
||||||
return macho_add_fat (state, filename, descriptor, 0, hdroffset,
|
return macho_add_fat (state, filename, descriptor, 0, hdroffset,
|
||||||
match_uuid, base_address, skip_symtab,
|
match_uuid, base_address, skip_symtab,
|
||||||
fat_header.nfat_arch, error_callback, data,
|
fat_header.nfat_arch,
|
||||||
fileline_fn, found_sym);
|
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:
|
||||||
|
case MACH_O_MH_CIGAM_FAT_64:
|
||||||
{
|
{
|
||||||
struct macho_header_fat fat_header;
|
struct macho_header_fat fat_header;
|
||||||
uint32_t nfat_arch;
|
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);
|
nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
|
||||||
return macho_add_fat (state, filename, descriptor, 1, hdroffset,
|
return macho_add_fat (state, filename, descriptor, 1, hdroffset,
|
||||||
match_uuid, base_address, skip_symtab,
|
match_uuid, base_address, skip_symtab,
|
||||||
nfat_arch, error_callback, data,
|
nfat_arch,
|
||||||
fileline_fn, found_sym);
|
header.magic == MACH_O_MH_CIGAM_FAT_64,
|
||||||
|
error_callback, data, fileline_fn, found_sym);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
error_callback (data, "executable file is not in Mach-O format", 0);
|
error_callback (data, "executable file is not in Mach-O format", 0);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* mmapio.c -- File views using mmap.
|
/* 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.
|
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
|
||||||
@ -40,6 +40,10 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||||||
#include "backtrace.hpp"
|
#include "backtrace.hpp"
|
||||||
#include "internal.hpp"
|
#include "internal.hpp"
|
||||||
|
|
||||||
|
#ifndef HAVE_DECL_GETPAGESIZE
|
||||||
|
extern int getpagesize (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MAP_FAILED
|
#ifndef MAP_FAILED
|
||||||
#define MAP_FAILED ((void *)-1)
|
#define MAP_FAILED ((void *)-1)
|
||||||
#endif
|
#endif
|
||||||
@ -101,10 +105,10 @@ backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
|||||||
union {
|
union {
|
||||||
const void *cv;
|
const void *cv;
|
||||||
void *v;
|
void *v;
|
||||||
};
|
} cc;
|
||||||
|
|
||||||
cv = view->base;
|
cc.cv = view->base;
|
||||||
if (munmap (v, view->len) < 0)
|
if (munmap (cc.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-2020 Free Software Foundation, Inc.
|
Copyright (C) 2012-2021 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-2020 Free Software Foundation, Inc.
|
Copyright (C) 2012-2021 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-2020 Free Software Foundation, Inc.
|
Copyright (C) 2012-2021 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