Update tracy to v0.9

This commit is contained in:
2023-02-18 22:00:05 +02:00
parent 05cb02aa09
commit 5b23a4b318
47 changed files with 7540 additions and 3597 deletions

View File

@@ -53,13 +53,14 @@ struct backtrace_state;
invalid after this function returns.
As a special case, the ERRNUM argument will be passed as -1 if no
debug info can be found for the executable, but the function
requires debug info (e.g., backtrace_full, backtrace_pcinfo). The
MSG in this case will be something along the lines of "no debug
info". Similarly, ERRNUM will be passed as -1 if there is no
symbol table, but the function requires a symbol table (e.g.,
backtrace_syminfo). This may be used as a signal that some other
approach should be tried. */
debug info can be found for the executable, or if the debug info
exists but has an unsupported version, but the function requires
debug info (e.g., backtrace_full, backtrace_pcinfo). The MSG in
this case will be something along the lines of "no debug info".
Similarly, ERRNUM will be passed as -1 if there is no symbol table,
but the function requires a symbol table (e.g., backtrace_syminfo).
This may be used as a signal that some other approach should be
tried. */
typedef void (*backtrace_error_callback) (void *data, const char *msg,
int errnum);

View File

@@ -52,6 +52,7 @@ enum dwarf_tag {
DW_TAG_compile_unit = 0x11,
DW_TAG_inlined_subroutine = 0x1d,
DW_TAG_subprogram = 0x2e,
DW_TAG_skeleton_unit = 0x4a,
};
enum dwarf_form {
@@ -746,13 +747,13 @@ struct dwarf_data
/* Report an error for a DWARF buffer. */
static void
dwarf_buf_error (struct dwarf_buf *buf, const char *msg)
dwarf_buf_error (struct dwarf_buf *buf, const char *msg, int errnum)
{
char b[200];
snprintf (b, sizeof b, "%s in %s at %d",
msg, buf->name, (int) (buf->buf - buf->start));
buf->error_callback (buf->data, b, 0);
buf->error_callback (buf->data, b, errnum);
}
/* Require at least COUNT bytes in BUF. Return 1 if all is well, 0 on
@@ -766,7 +767,7 @@ require (struct dwarf_buf *buf, size_t count)
if (!buf->reported_underflow)
{
dwarf_buf_error (buf, "DWARF underflow");
dwarf_buf_error (buf, "DWARF underflow", 0);
buf->reported_underflow = 1;
}
@@ -928,7 +929,7 @@ read_address (struct dwarf_buf *buf, int addrsize)
case 8:
return read_uint64 (buf);
default:
dwarf_buf_error (buf, "unrecognized address size");
dwarf_buf_error (buf, "unrecognized address size", 0);
return 0;
}
}
@@ -979,7 +980,7 @@ read_uleb128 (struct dwarf_buf *buf)
ret |= ((uint64_t) (b & 0x7f)) << shift;
else if (!overflow)
{
dwarf_buf_error (buf, "LEB128 overflows uint64_t");
dwarf_buf_error (buf, "LEB128 overflows uint64_t", 0);
overflow = 1;
}
shift += 7;
@@ -1014,7 +1015,7 @@ read_sleb128 (struct dwarf_buf *buf)
val |= ((uint64_t) (b & 0x7f)) << shift;
else if (!overflow)
{
dwarf_buf_error (buf, "signed LEB128 overflows uint64_t");
dwarf_buf_error (buf, "signed LEB128 overflows uint64_t", 0);
overflow = 1;
}
shift += 7;
@@ -1154,7 +1155,7 @@ read_attribute (enum dwarf_form form, uint64_t implicit_val,
offset = read_offset (buf, is_dwarf64);
if (offset >= dwarf_sections->size[DEBUG_STR])
{
dwarf_buf_error (buf, "DW_FORM_strp out of range");
dwarf_buf_error (buf, "DW_FORM_strp out of range", 0);
return 0;
}
val->encoding = ATTR_VAL_STRING;
@@ -1169,7 +1170,7 @@ read_attribute (enum dwarf_form form, uint64_t implicit_val,
offset = read_offset (buf, is_dwarf64);
if (offset >= dwarf_sections->size[DEBUG_LINE_STR])
{
dwarf_buf_error (buf, "DW_FORM_line_strp out of range");
dwarf_buf_error (buf, "DW_FORM_line_strp out of range", 0);
return 0;
}
val->encoding = ATTR_VAL_STRING;
@@ -1216,7 +1217,8 @@ read_attribute (enum dwarf_form form, uint64_t implicit_val,
if (form == DW_FORM_implicit_const)
{
dwarf_buf_error (buf,
"DW_FORM_indirect to DW_FORM_implicit_const");
"DW_FORM_indirect to DW_FORM_implicit_const",
0);
return 0;
}
return read_attribute ((enum dwarf_form) form, 0, buf, is_dwarf64,
@@ -1349,7 +1351,7 @@ read_attribute (enum dwarf_form form, uint64_t implicit_val,
}
if (offset >= altlink->dwarf_sections.size[DEBUG_STR])
{
dwarf_buf_error (buf, "DW_FORM_strp_sup out of range");
dwarf_buf_error (buf, "DW_FORM_strp_sup out of range", 0);
return 0;
}
val->encoding = ATTR_VAL_STRING;
@@ -1358,7 +1360,7 @@ read_attribute (enum dwarf_form form, uint64_t implicit_val,
return 1;
}
default:
dwarf_buf_error (buf, "unrecognized DWARF form");
dwarf_buf_error (buf, "unrecognized DWARF form", -1);
return 0;
}
}
@@ -1407,7 +1409,9 @@ resolve_string (const struct dwarf_sections *dwarf_sections, int is_dwarf64,
offset = read_offset (&offset_buf, is_dwarf64);
if (offset >= dwarf_sections->size[DEBUG_STR])
{
dwarf_buf_error (&offset_buf, "DW_FORM_strx offset out of range");
dwarf_buf_error (&offset_buf,
"DW_FORM_strx offset out of range",
0);
return 0;
}
*string = (const char *) dwarf_sections->data[DEBUG_STR] + offset;
@@ -2215,7 +2219,7 @@ add_ranges_from_rnglists (
break;
default:
dwarf_buf_error (&rnglists_buf, "unrecognized DW_RLE value");
dwarf_buf_error (&rnglists_buf, "unrecognized DW_RLE value", -1);
return 0;
}
}
@@ -2322,14 +2326,16 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
break;
case DW_AT_stmt_list:
if (abbrev->tag == DW_TAG_compile_unit
if ((abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_skeleton_unit)
&& (val.encoding == ATTR_VAL_UINT
|| val.encoding == ATTR_VAL_REF_SECTION))
u->lineoff = val.u.uint;
break;
case DW_AT_name:
if (abbrev->tag == DW_TAG_compile_unit)
if (abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_skeleton_unit)
{
name_val = val;
have_name_val = 1;
@@ -2337,7 +2343,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
break;
case DW_AT_comp_dir:
if (abbrev->tag == DW_TAG_compile_unit)
if (abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_skeleton_unit)
{
comp_dir_val = val;
have_comp_dir_val = 1;
@@ -2345,19 +2352,22 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
break;
case DW_AT_str_offsets_base:
if (abbrev->tag == DW_TAG_compile_unit
if ((abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_skeleton_unit)
&& val.encoding == ATTR_VAL_REF_SECTION)
u->str_offsets_base = val.u.uint;
break;
case DW_AT_addr_base:
if (abbrev->tag == DW_TAG_compile_unit
if ((abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_skeleton_unit)
&& val.encoding == ATTR_VAL_REF_SECTION)
u->addr_base = val.u.uint;
break;
case DW_AT_rnglists_base:
if (abbrev->tag == DW_TAG_compile_unit
if ((abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_skeleton_unit)
&& val.encoding == ATTR_VAL_REF_SECTION)
u->rnglists_base = val.u.uint;
break;
@@ -2385,7 +2395,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
}
if (abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_subprogram)
|| abbrev->tag == DW_TAG_subprogram
|| abbrev->tag == DW_TAG_skeleton_unit)
{
if (!add_ranges (state, dwarf_sections, base_address,
is_bigendian, u, pcrange.lowpc, &pcrange,
@@ -2393,9 +2404,10 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
(void *) addrs))
return 0;
/* If we found the PC range in the DW_TAG_compile_unit, we
can stop now. */
if (abbrev->tag == DW_TAG_compile_unit
/* If we found the PC range in the DW_TAG_compile_unit or
DW_TAG_skeleton_unit, we can stop now. */
if ((abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_skeleton_unit)
&& (pcrange.have_ranges
|| (pcrange.have_lowpc && pcrange.have_highpc)))
return 1;
@@ -2482,7 +2494,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
version = read_uint16 (&unit_buf);
if (version < 2 || version > 5)
{
dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
dwarf_buf_error (&unit_buf, "unrecognized DWARF version", -1);
goto fail;
}
@@ -2554,6 +2566,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
u->comp_dir = NULL;
u->abs_filename = NULL;
u->lineoff = 0;
u->str_offsets_base = 0;
u->addr_base = 0;
u->rnglists_base = 0;
/* The actual line number mappings will be read as needed. */
u->lines = NULL;
@@ -2761,7 +2776,8 @@ read_v2_paths (struct backtrace_state *state, struct unit *u,
{
dwarf_buf_error (hdr_buf,
("invalid directory index in "
"line number program header"));
"line number program header"),
0);
return 0;
}
dir_len = strlen (dir);
@@ -2830,7 +2846,8 @@ read_lnct (struct backtrace_state *state, struct dwarf_data *ddata,
{
dwarf_buf_error (hdr_buf,
("invalid directory index in "
"line number program header"));
"line number program header"),
0);
return 0;
}
dir = hdr->dirs[val.u.uint];
@@ -2845,7 +2862,8 @@ read_lnct (struct backtrace_state *state, struct dwarf_data *ddata,
if (path == NULL)
{
dwarf_buf_error (hdr_buf,
"missing file name in line number program header");
"missing file name in line number program header",
0);
return 0;
}
@@ -2972,7 +2990,7 @@ read_line_header (struct backtrace_state *state, struct dwarf_data *ddata,
hdr->version = read_uint16 (line_buf);
if (hdr->version < 2 || hdr->version > 5)
{
dwarf_buf_error (line_buf, "unsupported line number version");
dwarf_buf_error (line_buf, "unsupported line number version", -1);
return 0;
}
@@ -2986,7 +3004,8 @@ read_line_header (struct backtrace_state *state, struct dwarf_data *ddata,
if (read_byte (line_buf) != 0)
{
dwarf_buf_error (line_buf,
"non-zero segment_selector_size not supported");
"non-zero segment_selector_size not supported",
-1);
return 0;
}
}
@@ -3127,7 +3146,8 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
{
dwarf_buf_error (line_buf,
("invalid directory index "
"in line number program"));
"in line number program"),
0);
return 0;
}
dir_len = strlen (dir);
@@ -3185,19 +3205,15 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
uint64_t fileno;
fileno = read_uleb128 (line_buf);
if (fileno == 0)
filename = "";
else
if (fileno >= 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];
dwarf_buf_error (line_buf,
("invalid file number in "
"line number program"),
0);
return 0;
}
filename = hdr->filenames[fileno];
}
break;
case DW_LNS_set_column:
@@ -3428,7 +3444,9 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u,
code = read_uleb128 (&unit_buf);
if (code == 0)
{
dwarf_buf_error (&unit_buf, "invalid abstract origin or specification");
dwarf_buf_error (&unit_buf,
"invalid abstract origin or specification",
0);
return NULL;
}
@@ -3601,7 +3619,8 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
/* The compile unit sets the base address for any address
ranges in the function entries. */
if (abbrev->tag == DW_TAG_compile_unit
if ((abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_skeleton_unit)
&& abbrev->attrs[i].name == DW_AT_low_pc)
{
if (val.encoding == ATTR_VAL_ADDRESS)
@@ -3623,20 +3642,15 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
case DW_AT_call_file:
if (val.encoding == ATTR_VAL_UINT)
{
if (val.u.uint == 0)
function->caller_filename = "";
else
if (val.u.uint >= lhdr->filenames_count)
{
if (val.u.uint >= lhdr->filenames_count)
{
dwarf_buf_error (unit_buf,
("invalid file number in "
"DW_AT_call_file attribute"));
return 0;
}
function->caller_filename =
lhdr->filenames[val.u.uint];
dwarf_buf_error (unit_buf,
("invalid file number in "
"DW_AT_call_file attribute"),
0);
return 0;
}
function->caller_filename = lhdr->filenames[val.u.uint];
}
break;
@@ -3884,7 +3898,7 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
Returns whatever CALLBACK returns, or 0 to keep going. */
static int
report_inlined_functions (uintptr_t pc, struct function *function,
report_inlined_functions (uintptr_t pc, struct function *function, const char* comp_dir,
backtrace_full_callback callback, void *data,
const char **filename, int *lineno)
{
@@ -3938,13 +3952,22 @@ report_inlined_functions (uintptr_t pc, struct function *function,
inlined = match->function;
/* Report any calls inlined into this one. */
ret = report_inlined_functions (pc, inlined, callback, data,
ret = report_inlined_functions (pc, inlined, comp_dir, callback, data,
filename, lineno);
if (ret != 0)
return ret;
/* Report this inlined call. */
ret = callback (data, pc, match->low, *filename, *lineno, inlined->name);
if (*filename[0] != '/' && comp_dir)
{
char buf[1024];
snprintf (buf, 1024, "%s/%s", comp_dir, *filename);
ret = callback (data, pc, match->low, buf, *lineno, inlined->name);
}
else
{
ret = callback (data, pc, match->low, *filename, *lineno, inlined->name);
}
if (ret != 0)
return ret;
@@ -4211,12 +4234,21 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
filename = ln->filename;
lineno = ln->lineno;
ret = report_inlined_functions (pc, function, callback, data,
ret = report_inlined_functions (pc, function, entry->u->comp_dir, callback, data,
&filename, &lineno);
if (ret != 0)
return ret;
return callback (data, pc, fmatch->low, filename, lineno, function->name);
if (filename[0] != '/' && entry->u->comp_dir)
{
char buf[1024];
snprintf (buf, 1024, "%s/%s", entry->u->comp_dir, filename);
return callback (data, pc, fmatch->low, buf, lineno, function->name);
}
else
{
return callback (data, pc, fmatch->low, filename, lineno, function->name);
}
}

View File

@@ -46,6 +46,9 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "backtrace.hpp"
#include "internal.hpp"
#include "../client/TracyFastVector.hpp"
#include "../common/TracyAlloc.hpp"
#ifndef S_ISLNK
#ifndef S_IFLNK
#define S_IFLNK 0120000
@@ -70,6 +73,10 @@ POSSIBILITY OF SUCH DAMAGE. */
namespace tracy
{
#ifdef TRACY_DEBUGINFOD
int GetDebugInfoDescriptor( const char* buildid_data, size_t buildid_size );
#endif
#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN
/* If strnlen is not declared, provide our own version. */
@@ -867,6 +874,7 @@ elf_readlink (struct backtrace_state *state, const char *filename,
static int
elf_open_debugfile_by_buildid (struct backtrace_state *state,
const char *buildid_data, size_t buildid_size,
const char *filename,
backtrace_error_callback error_callback,
void *data)
{
@@ -913,7 +921,14 @@ elf_open_debugfile_by_buildid (struct backtrace_state *state,
That seems kind of pointless to me--why would it have the right
name but not the right build ID?--so skipping the check. */
#ifdef TRACY_DEBUGINFOD
if (ret == -1)
return GetDebugInfoDescriptor( buildid_data, buildid_size, filename );
else
return ret;
#else
return ret;
#endif
}
/* Try to open a file whose name is PREFIX (length PREFIX_LEN)
@@ -1803,7 +1818,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
/* An uncompressed block. */
/* If we've read ahead more than a byte, back up. */
while (bits > 8)
while (bits >= 8)
{
--pin;
bits -= 8;
@@ -4429,7 +4444,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
int d;
d = elf_open_debugfile_by_buildid (state, buildid_data, buildid_size,
error_callback, data);
filename, error_callback, data);
if (d >= 0)
{
int ret;
@@ -4812,12 +4827,34 @@ struct phdr_data
/* Callback passed to dl_iterate_phdr. Load debug info from shared
libraries. */
struct PhdrIterate
{
char* dlpi_name;
ElfW(Addr) dlpi_addr;
};
FastVector<PhdrIterate> s_phdrData(16);
static int
phdr_callback_mock (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
void *pdata)
{
auto ptr = s_phdrData.push_next();
if (info->dlpi_name)
{
size_t sz = strlen (info->dlpi_name) + 1;
ptr->dlpi_name = (char*)tracy_malloc (sz);
memcpy (ptr->dlpi_name, info->dlpi_name, sz);
}
else ptr->dlpi_name = nullptr;
ptr->dlpi_addr = info->dlpi_addr;
return 0;
}
static int
#ifdef __i386__
__attribute__ ((__force_align_arg_pointer__))
#endif
phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
void *pdata)
phdr_callback (struct PhdrIterate *info, void *pdata)
{
struct phdr_data *pd = (struct phdr_data *) pdata;
const char *filename;
@@ -4896,7 +4933,14 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
pd.exe_filename = filename;
pd.exe_descriptor = ret < 0 ? descriptor : -1;
dl_iterate_phdr (phdr_callback, (void *) &pd);
assert (s_phdrData.empty());
dl_iterate_phdr (phdr_callback_mock, nullptr);
for (auto& v : s_phdrData)
{
phdr_callback (&v, (void *) &pd);
tracy_free (v.dlpi_name);
}
s_phdrData.clear();
if (!state->threaded)
{

View File

@@ -1271,7 +1271,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
mff = macho_nodebug;
if (!macho_add (state, name, d, 0, NULL, base_address, 0,
error_callback, data, &mff, &mfs))
return 0;
continue;
if (mff != macho_nodebug)
macho_fileline_fn = mff;
@@ -1292,7 +1292,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
else
{
if (found_sym)
backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
backtrace_atomic_store_pointer (&state->syminfo_fn, &macho_syminfo);
else
(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
macho_nosyms);
@@ -1338,7 +1338,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
else
{
if (found_sym)
backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
backtrace_atomic_store_pointer (&state->syminfo_fn, &macho_syminfo);
else
(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
macho_nosyms);