mirror of
https://github.com/godotengine/godot.git
synced 2025-01-22 10:32:54 -05:00
parent
c2e4ae782a
commit
51730391c6
17 changed files with 678 additions and 147 deletions
6
thirdparty/README.md
vendored
6
thirdparty/README.md
vendored
|
@ -460,12 +460,14 @@ Files extracted from upstream source:
|
|||
## libbacktrace
|
||||
|
||||
- Upstream: https://github.com/ianlancetaylor/libbacktrace
|
||||
- Version: git (4d2dd0b172f2c9192f83ba93425f868f2a13c553, 2022)
|
||||
- Version: git (1db85642e3fca189cf4e076f840a45d6934b2456, 2024)
|
||||
- License: BSD-3-Clause
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- `*.{c,h}` files for Windows platform
|
||||
- `*.{c,h}` files for Windows platform, i.e. remove the following:
|
||||
* `allocfail.c`, `instrumented_alloc.c`, `*test*.{c,h}`
|
||||
* `elf.c`, `macho.c`, `mmap.c`, `mmapio.c`, `nounwind.c`, `unknown.c`, `xcoff.c`
|
||||
- `LICENSE`
|
||||
|
||||
Important: Some files have Godot-made changes to load big debug symbol files.
|
||||
|
|
2
thirdparty/libbacktrace/alloc.c
vendored
2
thirdparty/libbacktrace/alloc.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* alloc.c -- Memory allocation without mmap.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
2
thirdparty/libbacktrace/atomic.c
vendored
2
thirdparty/libbacktrace/atomic.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* atomic.c -- Support for atomic functions if not present.
|
||||
Copyright (C) 2013-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* backtrace-supported.h.in -- Whether stack backtrace is supported.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
2
thirdparty/libbacktrace/backtrace.c
vendored
2
thirdparty/libbacktrace/backtrace.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* backtrace.c -- Entry point for stack backtrace library.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
2
thirdparty/libbacktrace/backtrace.h
vendored
2
thirdparty/libbacktrace/backtrace.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* backtrace.h -- Public header file for stack backtrace library.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
18
thirdparty/libbacktrace/config.h
vendored
18
thirdparty/libbacktrace/config.h
vendored
|
@ -21,6 +21,10 @@
|
|||
don't. */
|
||||
#define HAVE_DECL_STRNLEN 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `_pgmptr', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL__PGMPTR 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
/* #undef HAVE_DLFCN_H */
|
||||
|
||||
|
@ -48,7 +52,7 @@
|
|||
/* #undef HAVE_KERN_PROC_ARGS */
|
||||
|
||||
/* Define if -llzma is available. */
|
||||
#define HAVE_LIBLZMA 1
|
||||
/* #undef HAVE_LIBLZMA */
|
||||
|
||||
/* Define to 1 if you have the <link.h> header file. */
|
||||
/* #undef HAVE_LINK_H */
|
||||
|
@ -86,6 +90,9 @@
|
|||
/* Define to 1 if you have the <sys/ldr.h> header file. */
|
||||
/* #undef HAVE_SYS_LDR_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/link.h> header file. */
|
||||
/* #undef HAVE_SYS_LINK_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
/* #undef HAVE_SYS_MMAN_H */
|
||||
|
||||
|
@ -95,12 +102,21 @@
|
|||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <tlhelp32.h> header file. */
|
||||
#define HAVE_TLHELP32_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#define HAVE_WINDOWS_H 1
|
||||
|
||||
/* Define if -lz is available. */
|
||||
#define HAVE_ZLIB 1
|
||||
|
||||
/* Define if -lzstd is available. */
|
||||
/* #undef HAVE_ZSTD */
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
|
363
thirdparty/libbacktrace/dwarf.c
vendored
363
thirdparty/libbacktrace/dwarf.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* dwarf.c -- Get file/line information from DWARF for backtraces.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -470,7 +470,7 @@ enum attr_val_encoding
|
|||
/* An address. */
|
||||
ATTR_VAL_ADDRESS,
|
||||
/* An index into the .debug_addr section, whose value is relative to
|
||||
* the DW_AT_addr_base attribute of the compilation unit. */
|
||||
the DW_AT_addr_base attribute of the compilation unit. */
|
||||
ATTR_VAL_ADDRESS_INDEX,
|
||||
/* A unsigned integer. */
|
||||
ATTR_VAL_UINT,
|
||||
|
@ -608,8 +608,8 @@ struct function
|
|||
struct function_addrs
|
||||
{
|
||||
/* Range is LOW <= PC < HIGH. */
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
uintptr_t low;
|
||||
uintptr_t high;
|
||||
/* Function for this address range. */
|
||||
struct function *function;
|
||||
};
|
||||
|
@ -690,8 +690,8 @@ struct unit
|
|||
struct unit_addrs
|
||||
{
|
||||
/* Range is LOW <= PC < HIGH. */
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
uintptr_t low;
|
||||
uintptr_t high;
|
||||
/* Compilation unit for this address range. */
|
||||
struct unit *u;
|
||||
};
|
||||
|
@ -722,8 +722,8 @@ struct dwarf_data
|
|||
struct dwarf_data *next;
|
||||
/* The data for .gnu_debugaltlink. */
|
||||
struct dwarf_data *altlink;
|
||||
/* The base address for this file. */
|
||||
uintptr_t base_address;
|
||||
/* The base address mapping for this file. */
|
||||
struct libbacktrace_base_address base_address;
|
||||
/* A sorted list of address ranges. */
|
||||
struct unit_addrs *addrs;
|
||||
/* Number of address ranges in list. */
|
||||
|
@ -1428,7 +1428,7 @@ resolve_addr_index (const struct dwarf_sections *dwarf_sections,
|
|||
uint64_t addr_base, int addrsize, int is_bigendian,
|
||||
uint64_t addr_index,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
uint64_t *address)
|
||||
uintptr_t *address)
|
||||
{
|
||||
uint64_t offset;
|
||||
struct dwarf_buf addr_buf;
|
||||
|
@ -1449,7 +1449,7 @@ resolve_addr_index (const struct dwarf_sections *dwarf_sections,
|
|||
addr_buf.data = data;
|
||||
addr_buf.reported_underflow = 0;
|
||||
|
||||
*address = read_address (&addr_buf, addrsize);
|
||||
*address = (uintptr_t) read_address (&addr_buf, addrsize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1528,7 +1528,7 @@ function_addrs_search (const void *vkey, const void *ventry)
|
|||
|
||||
static int
|
||||
add_unit_addr (struct backtrace_state *state, void *rdata,
|
||||
uint64_t lowpc, uint64_t highpc,
|
||||
uintptr_t lowpc, uintptr_t highpc,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
void *pvec)
|
||||
{
|
||||
|
@ -1610,6 +1610,194 @@ unit_addrs_search (const void *vkey, const void *ventry)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Fill in overlapping ranges as needed. This is a subroutine of
|
||||
resolve_unit_addrs_overlap. */
|
||||
|
||||
static int
|
||||
resolve_unit_addrs_overlap_walk (struct backtrace_state *state,
|
||||
size_t *pfrom, size_t *pto,
|
||||
struct unit_addrs *enclosing,
|
||||
struct unit_addrs_vector *old_vec,
|
||||
backtrace_error_callback error_callback,
|
||||
void *data,
|
||||
struct unit_addrs_vector *new_vec)
|
||||
{
|
||||
struct unit_addrs *old_addrs;
|
||||
size_t old_count;
|
||||
struct unit_addrs *new_addrs;
|
||||
size_t from;
|
||||
size_t to;
|
||||
|
||||
old_addrs = (struct unit_addrs *) old_vec->vec.base;
|
||||
old_count = old_vec->count;
|
||||
new_addrs = (struct unit_addrs *) new_vec->vec.base;
|
||||
|
||||
for (from = *pfrom, to = *pto; from < old_count; from++, to++)
|
||||
{
|
||||
/* If we are in the scope of a larger range that can no longer
|
||||
cover any further ranges, return back to the caller. */
|
||||
|
||||
if (enclosing != NULL
|
||||
&& enclosing->high <= old_addrs[from].low)
|
||||
{
|
||||
*pfrom = from;
|
||||
*pto = to;
|
||||
return 1;
|
||||
}
|
||||
|
||||
new_addrs[to] = old_addrs[from];
|
||||
|
||||
/* If we are in scope of a larger range, fill in any gaps
|
||||
between this entry and the next one.
|
||||
|
||||
There is an extra entry at the end of the vector, so it's
|
||||
always OK to refer to from + 1. */
|
||||
|
||||
if (enclosing != NULL
|
||||
&& enclosing->high > old_addrs[from].high
|
||||
&& old_addrs[from].high < old_addrs[from + 1].low)
|
||||
{
|
||||
void *grew;
|
||||
size_t new_high;
|
||||
|
||||
grew = backtrace_vector_grow (state, sizeof (struct unit_addrs),
|
||||
error_callback, data, &new_vec->vec);
|
||||
if (grew == NULL)
|
||||
return 0;
|
||||
new_addrs = (struct unit_addrs *) new_vec->vec.base;
|
||||
to++;
|
||||
new_addrs[to].low = old_addrs[from].high;
|
||||
new_high = old_addrs[from + 1].low;
|
||||
if (enclosing->high < new_high)
|
||||
new_high = enclosing->high;
|
||||
new_addrs[to].high = new_high;
|
||||
new_addrs[to].u = enclosing->u;
|
||||
}
|
||||
|
||||
/* If this range has a larger scope than the next one, use it to
|
||||
fill in any gaps. */
|
||||
|
||||
if (old_addrs[from].high > old_addrs[from + 1].high)
|
||||
{
|
||||
*pfrom = from + 1;
|
||||
*pto = to + 1;
|
||||
if (!resolve_unit_addrs_overlap_walk (state, pfrom, pto,
|
||||
&old_addrs[from], old_vec,
|
||||
error_callback, data, new_vec))
|
||||
return 0;
|
||||
from = *pfrom;
|
||||
to = *pto;
|
||||
|
||||
/* Undo the increment the loop is about to do. */
|
||||
from--;
|
||||
to--;
|
||||
}
|
||||
}
|
||||
|
||||
if (enclosing == NULL)
|
||||
{
|
||||
struct unit_addrs *pa;
|
||||
|
||||
/* Add trailing entry. */
|
||||
|
||||
pa = ((struct unit_addrs *)
|
||||
backtrace_vector_grow (state, sizeof (struct unit_addrs),
|
||||
error_callback, data, &new_vec->vec));
|
||||
if (pa == NULL)
|
||||
return 0;
|
||||
pa->low = 0;
|
||||
--pa->low;
|
||||
pa->high = pa->low;
|
||||
pa->u = NULL;
|
||||
|
||||
new_vec->count = to;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* It is possible for the unit_addrs list to contain overlaps, as in
|
||||
|
||||
10: low == 10, high == 20, unit 1
|
||||
11: low == 12, high == 15, unit 2
|
||||
12: low == 20, high == 30, unit 1
|
||||
|
||||
In such a case, for pc == 17, a search using units_addr_search will
|
||||
return entry 11. However, pc == 17 doesn't fit in that range. We
|
||||
actually want range 10.
|
||||
|
||||
It seems that in general we might have an arbitrary number of
|
||||
ranges in between 10 and 12.
|
||||
|
||||
To handle this we look for cases where range R1 is followed by
|
||||
range R2 such that R2 is a strict subset of R1. In such cases we
|
||||
insert a new range R3 following R2 that fills in the remainder of
|
||||
the address space covered by R1. That lets a relatively simple
|
||||
search find the correct range.
|
||||
|
||||
These overlaps can occur because of the range merging we do in
|
||||
add_unit_addr. When the linker de-duplicates functions, it can
|
||||
leave behind an address range that refers to the address range of
|
||||
the retained duplicate. If the retained duplicate address range is
|
||||
merged with others, then after sorting we can see overlapping
|
||||
address ranges.
|
||||
|
||||
See https://github.com/ianlancetaylor/libbacktrace/issues/137. */
|
||||
|
||||
static int
|
||||
resolve_unit_addrs_overlap (struct backtrace_state *state,
|
||||
backtrace_error_callback error_callback,
|
||||
void *data, struct unit_addrs_vector *addrs_vec)
|
||||
{
|
||||
struct unit_addrs *addrs;
|
||||
size_t count;
|
||||
int found;
|
||||
struct unit_addrs *entry;
|
||||
size_t i;
|
||||
struct unit_addrs_vector new_vec;
|
||||
void *grew;
|
||||
size_t from;
|
||||
size_t to;
|
||||
|
||||
addrs = (struct unit_addrs *) addrs_vec->vec.base;
|
||||
count = addrs_vec->count;
|
||||
|
||||
if (count == 0)
|
||||
return 1;
|
||||
|
||||
/* Optimistically assume that overlaps are rare. */
|
||||
found = 0;
|
||||
entry = addrs;
|
||||
for (i = 0; i < count - 1; i++)
|
||||
{
|
||||
if (entry->low < (entry + 1)->low
|
||||
&& entry->high > (entry + 1)->high)
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
entry++;
|
||||
}
|
||||
if (!found)
|
||||
return 1;
|
||||
|
||||
memset (&new_vec, 0, sizeof new_vec);
|
||||
grew = backtrace_vector_grow (state,
|
||||
count * sizeof (struct unit_addrs),
|
||||
error_callback, data, &new_vec.vec);
|
||||
if (grew == NULL)
|
||||
return 0;
|
||||
|
||||
from = 0;
|
||||
to = 0;
|
||||
resolve_unit_addrs_overlap_walk (state, &from, &to, NULL, addrs_vec,
|
||||
error_callback, data, &new_vec);
|
||||
backtrace_vector_free (state, &addrs_vec->vec, error_callback, data);
|
||||
*addrs_vec = new_vec;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Sort the line vector by PC. We want a stable sort here to maintain
|
||||
the order of lines for the same PC values. Since the sequence is
|
||||
being sorted in place, their addresses cannot be relied on to
|
||||
|
@ -1864,10 +2052,10 @@ lookup_abbrev (struct abbrevs *abbrevs, uint64_t code,
|
|||
lowpc/highpc is set or ranges is set. */
|
||||
|
||||
struct pcrange {
|
||||
uint64_t lowpc; /* The low PC value. */
|
||||
uintptr_t lowpc; /* The low PC value. */
|
||||
int have_lowpc; /* Whether a low PC value was found. */
|
||||
int lowpc_is_addr_index; /* Whether lowpc is in .debug_addr. */
|
||||
uint64_t highpc; /* The high PC value. */
|
||||
uintptr_t highpc; /* The high PC value. */
|
||||
int have_highpc; /* Whether a high PC value was found. */
|
||||
int highpc_is_relative; /* Whether highpc is relative to lowpc. */
|
||||
int highpc_is_addr_index; /* Whether highpc is in .debug_addr. */
|
||||
|
@ -1887,12 +2075,12 @@ update_pcrange (const struct attr* attr, const struct attr_val* val,
|
|||
case DW_AT_low_pc:
|
||||
if (val->encoding == ATTR_VAL_ADDRESS)
|
||||
{
|
||||
pcrange->lowpc = val->u.uint;
|
||||
pcrange->lowpc = (uintptr_t) val->u.uint;
|
||||
pcrange->have_lowpc = 1;
|
||||
}
|
||||
else if (val->encoding == ATTR_VAL_ADDRESS_INDEX)
|
||||
{
|
||||
pcrange->lowpc = val->u.uint;
|
||||
pcrange->lowpc = (uintptr_t) val->u.uint;
|
||||
pcrange->have_lowpc = 1;
|
||||
pcrange->lowpc_is_addr_index = 1;
|
||||
}
|
||||
|
@ -1901,18 +2089,18 @@ update_pcrange (const struct attr* attr, const struct attr_val* val,
|
|||
case DW_AT_high_pc:
|
||||
if (val->encoding == ATTR_VAL_ADDRESS)
|
||||
{
|
||||
pcrange->highpc = val->u.uint;
|
||||
pcrange->highpc = (uintptr_t) val->u.uint;
|
||||
pcrange->have_highpc = 1;
|
||||
}
|
||||
else if (val->encoding == ATTR_VAL_UINT)
|
||||
{
|
||||
pcrange->highpc = val->u.uint;
|
||||
pcrange->highpc = (uintptr_t) val->u.uint;
|
||||
pcrange->have_highpc = 1;
|
||||
pcrange->highpc_is_relative = 1;
|
||||
}
|
||||
else if (val->encoding == ATTR_VAL_ADDRESS_INDEX)
|
||||
{
|
||||
pcrange->highpc = val->u.uint;
|
||||
pcrange->highpc = (uintptr_t) val->u.uint;
|
||||
pcrange->have_highpc = 1;
|
||||
pcrange->highpc_is_addr_index = 1;
|
||||
}
|
||||
|
@ -1944,19 +2132,20 @@ update_pcrange (const struct attr* attr, const struct attr_val* val,
|
|||
static int
|
||||
add_low_high_range (struct backtrace_state *state,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
uintptr_t base_address, int is_bigendian,
|
||||
struct unit *u, const struct pcrange *pcrange,
|
||||
struct libbacktrace_base_address base_address,
|
||||
int is_bigendian, struct unit *u,
|
||||
const struct pcrange *pcrange,
|
||||
int (*add_range) (struct backtrace_state *state,
|
||||
void *rdata, uint64_t lowpc,
|
||||
uint64_t highpc,
|
||||
void *rdata, uintptr_t lowpc,
|
||||
uintptr_t highpc,
|
||||
backtrace_error_callback error_callback,
|
||||
void *data, void *vec),
|
||||
void *rdata,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
void *vec)
|
||||
{
|
||||
uint64_t lowpc;
|
||||
uint64_t highpc;
|
||||
uintptr_t lowpc;
|
||||
uintptr_t highpc;
|
||||
|
||||
lowpc = pcrange->lowpc;
|
||||
if (pcrange->lowpc_is_addr_index)
|
||||
|
@ -1980,8 +2169,8 @@ add_low_high_range (struct backtrace_state *state,
|
|||
|
||||
/* Add in the base address of the module when recording PC values,
|
||||
so that we can look up the PC directly. */
|
||||
lowpc += base_address;
|
||||
highpc += base_address;
|
||||
lowpc = libbacktrace_add_base (lowpc, base_address);
|
||||
highpc = libbacktrace_add_base (highpc, base_address);
|
||||
|
||||
return add_range (state, rdata, lowpc, highpc, error_callback, data, vec);
|
||||
}
|
||||
|
@ -1993,11 +2182,11 @@ static int
|
|||
add_ranges_from_ranges (
|
||||
struct backtrace_state *state,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
uintptr_t base_address, int is_bigendian,
|
||||
struct unit *u, uint64_t base,
|
||||
struct libbacktrace_base_address base_address, int is_bigendian,
|
||||
struct unit *u, uintptr_t base,
|
||||
const struct pcrange *pcrange,
|
||||
int (*add_range) (struct backtrace_state *state, void *rdata,
|
||||
uint64_t lowpc, uint64_t highpc,
|
||||
uintptr_t lowpc, uintptr_t highpc,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
void *vec),
|
||||
void *rdata,
|
||||
|
@ -2036,13 +2225,14 @@ add_ranges_from_ranges (
|
|||
break;
|
||||
|
||||
if (is_highest_address (low, u->addrsize))
|
||||
base = high;
|
||||
base = (uintptr_t) high;
|
||||
else
|
||||
{
|
||||
if (!add_range (state, rdata,
|
||||
low + base + base_address,
|
||||
high + base + base_address,
|
||||
error_callback, data, vec))
|
||||
uintptr_t rl, rh;
|
||||
|
||||
rl = libbacktrace_add_base ((uintptr_t) low + base, base_address);
|
||||
rh = libbacktrace_add_base ((uintptr_t) high + base, base_address);
|
||||
if (!add_range (state, rdata, rl, rh, error_callback, data, vec))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -2060,11 +2250,11 @@ static int
|
|||
add_ranges_from_rnglists (
|
||||
struct backtrace_state *state,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
uintptr_t base_address, int is_bigendian,
|
||||
struct unit *u, uint64_t base,
|
||||
struct libbacktrace_base_address base_address, int is_bigendian,
|
||||
struct unit *u, uintptr_t base,
|
||||
const struct pcrange *pcrange,
|
||||
int (*add_range) (struct backtrace_state *state, void *rdata,
|
||||
uint64_t lowpc, uint64_t highpc,
|
||||
uintptr_t lowpc, uintptr_t highpc,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
void *vec),
|
||||
void *rdata,
|
||||
|
@ -2130,8 +2320,8 @@ add_ranges_from_rnglists (
|
|||
case DW_RLE_startx_endx:
|
||||
{
|
||||
uint64_t index;
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
uintptr_t low;
|
||||
uintptr_t high;
|
||||
|
||||
index = read_uleb128 (&rnglists_buf);
|
||||
if (!resolve_addr_index (dwarf_sections, u->addr_base,
|
||||
|
@ -2143,9 +2333,10 @@ add_ranges_from_rnglists (
|
|||
u->addrsize, is_bigendian, index,
|
||||
error_callback, data, &high))
|
||||
return 0;
|
||||
if (!add_range (state, rdata, low + base_address,
|
||||
high + base_address, error_callback, data,
|
||||
vec))
|
||||
if (!add_range (state, rdata,
|
||||
libbacktrace_add_base (low, base_address),
|
||||
libbacktrace_add_base (high, base_address),
|
||||
error_callback, data, vec))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
@ -2153,8 +2344,8 @@ add_ranges_from_rnglists (
|
|||
case DW_RLE_startx_length:
|
||||
{
|
||||
uint64_t index;
|
||||
uint64_t low;
|
||||
uint64_t length;
|
||||
uintptr_t low;
|
||||
uintptr_t length;
|
||||
|
||||
index = read_uleb128 (&rnglists_buf);
|
||||
if (!resolve_addr_index (dwarf_sections, u->addr_base,
|
||||
|
@ -2162,7 +2353,7 @@ add_ranges_from_rnglists (
|
|||
error_callback, data, &low))
|
||||
return 0;
|
||||
length = read_uleb128 (&rnglists_buf);
|
||||
low += base_address;
|
||||
low = libbacktrace_add_base (low, base_address);
|
||||
if (!add_range (state, rdata, low, low + length,
|
||||
error_callback, data, vec))
|
||||
return 0;
|
||||
|
@ -2176,39 +2367,41 @@ add_ranges_from_rnglists (
|
|||
|
||||
low = read_uleb128 (&rnglists_buf);
|
||||
high = read_uleb128 (&rnglists_buf);
|
||||
if (!add_range (state, rdata, low + base + base_address,
|
||||
high + base + base_address,
|
||||
if (!add_range (state, rdata,
|
||||
libbacktrace_add_base (low + base, base_address),
|
||||
libbacktrace_add_base (high + base, base_address),
|
||||
error_callback, data, vec))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_RLE_base_address:
|
||||
base = read_address (&rnglists_buf, u->addrsize);
|
||||
base = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
|
||||
break;
|
||||
|
||||
case DW_RLE_start_end:
|
||||
{
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
uintptr_t low;
|
||||
uintptr_t high;
|
||||
|
||||
low = read_address (&rnglists_buf, u->addrsize);
|
||||
high = read_address (&rnglists_buf, u->addrsize);
|
||||
if (!add_range (state, rdata, low + base_address,
|
||||
high + base_address, error_callback, data,
|
||||
vec))
|
||||
low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
|
||||
high = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
|
||||
if (!add_range (state, rdata,
|
||||
libbacktrace_add_base (low, base_address),
|
||||
libbacktrace_add_base (high, base_address),
|
||||
error_callback, data, vec))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_RLE_start_length:
|
||||
{
|
||||
uint64_t low;
|
||||
uint64_t length;
|
||||
uintptr_t low;
|
||||
uintptr_t length;
|
||||
|
||||
low = read_address (&rnglists_buf, u->addrsize);
|
||||
length = read_uleb128 (&rnglists_buf);
|
||||
low += base_address;
|
||||
low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
|
||||
length = (uintptr_t) read_uleb128 (&rnglists_buf);
|
||||
low = libbacktrace_add_base (low, base_address);
|
||||
if (!add_range (state, rdata, low, low + length,
|
||||
error_callback, data, vec))
|
||||
return 0;
|
||||
|
@ -2236,10 +2429,10 @@ add_ranges_from_rnglists (
|
|||
static int
|
||||
add_ranges (struct backtrace_state *state,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
uintptr_t base_address, int is_bigendian,
|
||||
struct unit *u, uint64_t base, const struct pcrange *pcrange,
|
||||
struct libbacktrace_base_address base_address, int is_bigendian,
|
||||
struct unit *u, uintptr_t base, const struct pcrange *pcrange,
|
||||
int (*add_range) (struct backtrace_state *state, void *rdata,
|
||||
uint64_t lowpc, uint64_t highpc,
|
||||
uintptr_t lowpc, uintptr_t highpc,
|
||||
backtrace_error_callback error_callback,
|
||||
void *data, void *vec),
|
||||
void *rdata,
|
||||
|
@ -2272,7 +2465,8 @@ add_ranges (struct backtrace_state *state,
|
|||
read, 0 if there is some error. */
|
||||
|
||||
static int
|
||||
find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
|
||||
find_address_ranges (struct backtrace_state *state,
|
||||
struct libbacktrace_base_address base_address,
|
||||
struct dwarf_buf *unit_buf,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
int is_bigendian, struct dwarf_data *altlink,
|
||||
|
@ -2427,7 +2621,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
|
|||
on success, 0 on failure. */
|
||||
|
||||
static int
|
||||
build_address_map (struct backtrace_state *state, uintptr_t base_address,
|
||||
build_address_map (struct backtrace_state *state,
|
||||
struct libbacktrace_base_address base_address,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
int is_bigendian, struct dwarf_data *altlink,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
|
@ -2646,7 +2841,7 @@ add_line (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||
|
||||
/* Add in the base address here, so that we can look up the PC
|
||||
directly. */
|
||||
ln->pc = pc + ddata->base_address;
|
||||
ln->pc = libbacktrace_add_base (pc, ddata->base_address);
|
||||
|
||||
ln->filename = filename;
|
||||
ln->lineno = lineno;
|
||||
|
@ -3307,7 +3502,7 @@ read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||
|
||||
if (vec.count == 0)
|
||||
{
|
||||
/* This is not a failure in the sense of a generating an error,
|
||||
/* This is not a failure in the sense of generating an error,
|
||||
but it is a failure in that sense that we have no useful
|
||||
information. */
|
||||
goto fail;
|
||||
|
@ -3517,7 +3712,7 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u,
|
|||
|
||||
static int
|
||||
add_function_range (struct backtrace_state *state, void *rdata,
|
||||
uint64_t lowpc, uint64_t highpc,
|
||||
uintptr_t lowpc, uintptr_t highpc,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
void *pvec)
|
||||
{
|
||||
|
@ -3557,7 +3752,7 @@ add_function_range (struct backtrace_state *state, void *rdata,
|
|||
|
||||
static int
|
||||
read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
|
||||
struct unit *u, uint64_t base, struct dwarf_buf *unit_buf,
|
||||
struct unit *u, uintptr_t base, struct dwarf_buf *unit_buf,
|
||||
const struct line_header *lhdr,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
struct function_vector *vec_function,
|
||||
|
@ -3621,7 +3816,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
|
|||
&& abbrev->attrs[i].name == DW_AT_low_pc)
|
||||
{
|
||||
if (val.encoding == ATTR_VAL_ADDRESS)
|
||||
base = val.u.uint;
|
||||
base = (uintptr_t) val.u.uint;
|
||||
else if (val.encoding == ATTR_VAL_ADDRESS_INDEX)
|
||||
{
|
||||
if (!resolve_addr_index (&ddata->dwarf_sections,
|
||||
|
@ -4285,7 +4480,7 @@ dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
|
|||
|
||||
static struct dwarf_data *
|
||||
build_dwarf_data (struct backtrace_state *state,
|
||||
uintptr_t base_address,
|
||||
struct libbacktrace_base_address base_address,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
int is_bigendian,
|
||||
struct dwarf_data *altlink,
|
||||
|
@ -4293,11 +4488,7 @@ build_dwarf_data (struct backtrace_state *state,
|
|||
void *data)
|
||||
{
|
||||
struct unit_addrs_vector addrs_vec;
|
||||
struct unit_addrs *addrs;
|
||||
size_t addrs_count;
|
||||
struct unit_vector units_vec;
|
||||
struct unit **units;
|
||||
size_t units_count;
|
||||
struct dwarf_data *fdata;
|
||||
|
||||
if (!build_address_map (state, base_address, dwarf_sections, is_bigendian,
|
||||
|
@ -4309,12 +4500,12 @@ build_dwarf_data (struct backtrace_state *state,
|
|||
return NULL;
|
||||
if (!backtrace_vector_release (state, &units_vec.vec, error_callback, data))
|
||||
return NULL;
|
||||
addrs = (struct unit_addrs *) addrs_vec.vec.base;
|
||||
units = (struct unit **) units_vec.vec.base;
|
||||
addrs_count = addrs_vec.count;
|
||||
units_count = units_vec.count;
|
||||
backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
|
||||
unit_addrs_compare);
|
||||
|
||||
backtrace_qsort ((struct unit_addrs *) addrs_vec.vec.base, addrs_vec.count,
|
||||
sizeof (struct unit_addrs), unit_addrs_compare);
|
||||
if (!resolve_unit_addrs_overlap (state, error_callback, data, &addrs_vec))
|
||||
return NULL;
|
||||
|
||||
/* No qsort for units required, already sorted. */
|
||||
|
||||
fdata = ((struct dwarf_data *)
|
||||
|
@ -4326,10 +4517,10 @@ build_dwarf_data (struct backtrace_state *state,
|
|||
fdata->next = NULL;
|
||||
fdata->altlink = altlink;
|
||||
fdata->base_address = base_address;
|
||||
fdata->addrs = addrs;
|
||||
fdata->addrs_count = addrs_count;
|
||||
fdata->units = units;
|
||||
fdata->units_count = units_count;
|
||||
fdata->addrs = (struct unit_addrs *) addrs_vec.vec.base;
|
||||
fdata->addrs_count = addrs_vec.count;
|
||||
fdata->units = (struct unit **) units_vec.vec.base;
|
||||
fdata->units_count = units_vec.count;
|
||||
fdata->dwarf_sections = *dwarf_sections;
|
||||
fdata->is_bigendian = is_bigendian;
|
||||
memset (&fdata->fvec, 0, sizeof fdata->fvec);
|
||||
|
@ -4343,7 +4534,7 @@ build_dwarf_data (struct backtrace_state *state,
|
|||
|
||||
int
|
||||
backtrace_dwarf_add (struct backtrace_state *state,
|
||||
uintptr_t base_address,
|
||||
struct libbacktrace_base_address base_address,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
int is_bigendian,
|
||||
struct dwarf_data *fileline_altlink,
|
||||
|
|
77
thirdparty/libbacktrace/fileline.c
vendored
77
thirdparty/libbacktrace/fileline.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* fileline.c -- Get file and line number information in a backtrace.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -47,6 +47,18 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "backtrace.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
@ -155,6 +167,47 @@ macho_get_executable_path (struct backtrace_state *state,
|
|||
|
||||
#endif /* !defined (HAVE_MACH_O_DYLD_H) */
|
||||
|
||||
#if HAVE_DECL__PGMPTR
|
||||
|
||||
#define windows_executable_filename() _pgmptr
|
||||
|
||||
#else /* !HAVE_DECL__PGMPTR */
|
||||
|
||||
#define windows_executable_filename() NULL
|
||||
|
||||
#endif /* !HAVE_DECL__PGMPTR */
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
|
||||
#define FILENAME_BUF_SIZE (MAX_PATH)
|
||||
|
||||
static char *
|
||||
windows_get_executable_path (char *buf, backtrace_error_callback error_callback,
|
||||
void *data)
|
||||
{
|
||||
size_t got;
|
||||
int error;
|
||||
|
||||
got = GetModuleFileNameA (NULL, buf, FILENAME_BUF_SIZE - 1);
|
||||
error = GetLastError ();
|
||||
if (got == 0
|
||||
|| (got == FILENAME_BUF_SIZE - 1 && error == ERROR_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
error_callback (data,
|
||||
"could not get the filename of the current executable",
|
||||
error);
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
#else /* !defined (HAVE_WINDOWS_H) */
|
||||
|
||||
#define windows_get_executable_path(buf, error_callback, data) NULL
|
||||
#define FILENAME_BUF_SIZE 64
|
||||
|
||||
#endif /* !defined (HAVE_WINDOWS_H) */
|
||||
|
||||
/* Initialize the fileline information from the executable. Returns 1
|
||||
on success, 0 on failure. */
|
||||
|
||||
|
@ -168,7 +221,7 @@ fileline_initialize (struct backtrace_state *state,
|
|||
int called_error_callback;
|
||||
int descriptor;
|
||||
const char *filename;
|
||||
char buf[64];
|
||||
char buf[FILENAME_BUF_SIZE];
|
||||
|
||||
if (!state->threaded)
|
||||
failed = state->fileline_initialization_failed;
|
||||
|
@ -192,7 +245,7 @@ fileline_initialize (struct backtrace_state *state,
|
|||
|
||||
descriptor = -1;
|
||||
called_error_callback = 0;
|
||||
for (pass = 0; pass < 8; ++pass)
|
||||
for (pass = 0; pass < 10; ++pass)
|
||||
{
|
||||
int does_not_exist;
|
||||
|
||||
|
@ -205,25 +258,33 @@ fileline_initialize (struct backtrace_state *state,
|
|||
filename = getexecname ();
|
||||
break;
|
||||
case 2:
|
||||
filename = "/proc/self/exe";
|
||||
/* Test this before /proc/self/exe, as the latter exists but points
|
||||
to the wine binary (and thus doesn't work). */
|
||||
filename = windows_executable_filename ();
|
||||
break;
|
||||
case 3:
|
||||
filename = "/proc/curproc/file";
|
||||
filename = "/proc/self/exe";
|
||||
break;
|
||||
case 4:
|
||||
filename = "/proc/curproc/file";
|
||||
break;
|
||||
case 5:
|
||||
snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out",
|
||||
(long) getpid ());
|
||||
filename = buf;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
filename = sysctl_exec_name1 (state, error_callback, data);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
filename = sysctl_exec_name2 (state, error_callback, data);
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
filename = macho_get_executable_path (state, error_callback, data);
|
||||
break;
|
||||
case 9:
|
||||
filename = windows_get_executable_path (buf, error_callback, data);
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
|
52
thirdparty/libbacktrace/internal.h
vendored
52
thirdparty/libbacktrace/internal.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* internal.h -- Internal header file for stack backtrace library.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -56,6 +56,11 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __has_attribute
|
||||
# if __has_attribute(fallthrough)
|
||||
# define ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough))
|
||||
# endif
|
||||
#endif
|
||||
#ifndef ATTRIBUTE_FALLTHROUGH
|
||||
# if (GCC_VERSION >= 7000)
|
||||
# define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))
|
||||
|
@ -323,10 +328,44 @@ struct dwarf_sections
|
|||
|
||||
struct dwarf_data;
|
||||
|
||||
/* The load address mapping. */
|
||||
|
||||
#if defined(__FDPIC__) && defined(HAVE_DL_ITERATE_PHDR) && (defined(HAVE_LINK_H) || defined(HAVE_SYS_LINK_H))
|
||||
|
||||
#ifdef HAVE_LINK_H
|
||||
#include <link.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_LINK_H
|
||||
#include <sys/link.h>
|
||||
#endif
|
||||
|
||||
#define libbacktrace_using_fdpic() (1)
|
||||
|
||||
struct libbacktrace_base_address
|
||||
{
|
||||
struct elf32_fdpic_loadaddr m;
|
||||
};
|
||||
|
||||
#define libbacktrace_add_base(pc, base) \
|
||||
((uintptr_t) (__RELOC_POINTER ((pc), (base).m)))
|
||||
|
||||
#else /* not _FDPIC__ */
|
||||
|
||||
#define libbacktrace_using_fdpic() (0)
|
||||
|
||||
struct libbacktrace_base_address
|
||||
{
|
||||
uintptr_t m;
|
||||
};
|
||||
|
||||
#define libbacktrace_add_base(pc, base) ((pc) + (base).m)
|
||||
|
||||
#endif /* not _FDPIC__ */
|
||||
|
||||
/* Add file/line information for a DWARF module. */
|
||||
|
||||
extern int backtrace_dwarf_add (struct backtrace_state *state,
|
||||
uintptr_t base_address,
|
||||
struct libbacktrace_base_address base_address,
|
||||
const struct dwarf_sections *dwarf_sections,
|
||||
int is_bigendian,
|
||||
struct dwarf_data *fileline_altlink,
|
||||
|
@ -368,6 +407,15 @@ extern int backtrace_uncompress_zdebug (struct backtrace_state *,
|
|||
unsigned char **uncompressed,
|
||||
size_t *uncompressed_size);
|
||||
|
||||
/* A test-only hook for elf_zstd_decompress. */
|
||||
|
||||
extern int backtrace_uncompress_zstd (struct backtrace_state *,
|
||||
const unsigned char *compressed,
|
||||
size_t compressed_size,
|
||||
backtrace_error_callback, void *data,
|
||||
unsigned char *uncompressed,
|
||||
size_t uncompressed_size);
|
||||
|
||||
/* A test-only hook for elf_uncompress_lzma. */
|
||||
|
||||
extern int backtrace_uncompress_lzma (struct backtrace_state *,
|
||||
|
|
228
thirdparty/libbacktrace/pecoff.c
vendored
228
thirdparty/libbacktrace/pecoff.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
|
||||
Copyright (C) 2015-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2015-2024 Free Software Foundation, Inc.
|
||||
Adapted from elf.c by Tristan Gingold, AdaCore.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -39,6 +39,58 @@ POSSIBILITY OF SUCH DAMAGE. */
|
|||
#include "backtrace.h"
|
||||
#include "internal.h"
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef HAVE_TLHELP32_H
|
||||
#include <tlhelp32.h>
|
||||
|
||||
#ifdef UNICODE
|
||||
/* If UNICODE is defined, all the symbols are replaced by a macro to use the
|
||||
wide variant. But we need the ansi variant, so undef the macros. */
|
||||
#undef MODULEENTRY32
|
||||
#undef Module32First
|
||||
#undef Module32Next
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_ARM_)
|
||||
#define NTAPI
|
||||
#else
|
||||
#define NTAPI __stdcall
|
||||
#endif
|
||||
|
||||
/* This is a simplified (but binary compatible) version of what Microsoft
|
||||
defines in their documentation. */
|
||||
struct dll_notification_data
|
||||
{
|
||||
ULONG reserved;
|
||||
/* The name as UNICODE_STRING struct. */
|
||||
PVOID full_dll_name;
|
||||
PVOID base_dll_name;
|
||||
PVOID dll_base;
|
||||
ULONG size_of_image;
|
||||
};
|
||||
|
||||
#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
|
||||
|
||||
typedef LONG NTSTATUS;
|
||||
typedef VOID (CALLBACK *LDR_DLL_NOTIFICATION)(ULONG,
|
||||
struct dll_notification_data*,
|
||||
PVOID);
|
||||
typedef NTSTATUS (NTAPI *LDR_REGISTER_FUNCTION)(ULONG,
|
||||
LDR_DLL_NOTIFICATION, PVOID,
|
||||
PVOID*);
|
||||
#endif
|
||||
|
||||
/* Coff file header. */
|
||||
|
||||
typedef struct {
|
||||
|
@ -188,7 +240,7 @@ coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
|||
backtrace_full_callback callback ATTRIBUTE_UNUSED,
|
||||
backtrace_error_callback error_callback, void *data)
|
||||
{
|
||||
error_callback (data, "no debug info in PE/COFF executable", -1);
|
||||
error_callback (data, "no debug info in PE/COFF executable (make sure to compile with -g)", -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -330,10 +382,11 @@ coff_is_function_symbol (const b_coff_internal_symbol *isym)
|
|||
|
||||
static int
|
||||
coff_initialize_syminfo (struct backtrace_state *state,
|
||||
uintptr_t base_address, int is_64,
|
||||
const b_coff_section_header *sects, size_t sects_num,
|
||||
const b_coff_external_symbol *syms, size_t syms_size,
|
||||
const unsigned char *strtab, size_t strtab_size,
|
||||
struct libbacktrace_base_address base_address,
|
||||
int is_64, const b_coff_section_header *sects,
|
||||
size_t sects_num, const b_coff_external_symbol *syms,
|
||||
size_t syms_size, const unsigned char *strtab,
|
||||
size_t strtab_size,
|
||||
backtrace_error_callback error_callback,
|
||||
void *data, struct coff_syminfo_data *sdata)
|
||||
{
|
||||
|
@ -438,9 +491,10 @@ coff_initialize_syminfo (struct backtrace_state *state,
|
|||
secnum = coff_read2 (asym->section_number);
|
||||
|
||||
coff_sym->name = name;
|
||||
coff_sym->address = (coff_read4 (asym->value)
|
||||
+ sects[secnum - 1].virtual_address
|
||||
+ base_address);
|
||||
coff_sym->address =
|
||||
libbacktrace_add_base ((coff_read4 (asym->value)
|
||||
+ sects[secnum - 1].virtual_address),
|
||||
base_address);
|
||||
coff_sym++;
|
||||
}
|
||||
|
||||
|
@ -580,7 +634,8 @@ coff_syminfo (struct backtrace_state *state, uintptr_t addr,
|
|||
static int
|
||||
coff_add (struct backtrace_state *state, int descriptor,
|
||||
backtrace_error_callback error_callback, void *data,
|
||||
fileline *fileline_fn, int *found_sym, int *found_dwarf)
|
||||
fileline *fileline_fn, int *found_sym, int *found_dwarf,
|
||||
uintptr_t module_handle ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct backtrace_view fhdr_view;
|
||||
off_t fhdr_off;
|
||||
|
@ -609,7 +664,8 @@ coff_add (struct backtrace_state *state, int descriptor,
|
|||
struct backtrace_view debug_view;
|
||||
int debug_view_valid;
|
||||
int is_64;
|
||||
uintptr_t image_base;
|
||||
struct libbacktrace_base_address image_base;
|
||||
struct libbacktrace_base_address base_address;
|
||||
struct dwarf_sections dwarf_sections;
|
||||
|
||||
*found_sym = 0;
|
||||
|
@ -648,7 +704,7 @@ coff_add (struct backtrace_state *state, int descriptor,
|
|||
magic_ok = memcmp (magic, "PE\0", 4) == 0;
|
||||
fhdr_off += 4;
|
||||
|
||||
memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
|
||||
memcpy (&fhdr, (const unsigned char *) fhdr_view.data + 4, sizeof fhdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -682,16 +738,17 @@ coff_add (struct backtrace_state *state, int descriptor,
|
|||
sects_view_valid = 1;
|
||||
opt_hdr = (const b_coff_optional_header *) sects_view.data;
|
||||
sects = (const b_coff_section_header *)
|
||||
(sects_view.data + fhdr.size_of_optional_header);
|
||||
((const unsigned char *) sects_view.data + fhdr.size_of_optional_header);
|
||||
|
||||
is_64 = 0;
|
||||
memset (&image_base, 0, sizeof image_base);
|
||||
if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
|
||||
{
|
||||
if (opt_hdr->magic == PE_MAGIC)
|
||||
image_base = opt_hdr->u.pe.image_base;
|
||||
image_base.m = opt_hdr->u.pe.image_base;
|
||||
else if (opt_hdr->magic == PEP_MAGIC)
|
||||
{
|
||||
image_base = opt_hdr->u.pep.image_base;
|
||||
image_base.m = opt_hdr->u.pep.image_base;
|
||||
is_64 = 1;
|
||||
}
|
||||
else
|
||||
|
@ -700,8 +757,6 @@ coff_add (struct backtrace_state *state, int descriptor,
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
image_base = 0;
|
||||
|
||||
/* Read the symbol table and the string table. */
|
||||
|
||||
|
@ -726,7 +781,8 @@ coff_add (struct backtrace_state *state, int descriptor,
|
|||
goto fail;
|
||||
syms_view_valid = 1;
|
||||
|
||||
str_size = coff_read4 (syms_view.data + syms_size);
|
||||
str_size = coff_read4 ((const unsigned char *) syms_view.data
|
||||
+ syms_size);
|
||||
|
||||
str_off = syms_off + syms_size;
|
||||
|
||||
|
@ -856,7 +912,12 @@ coff_add (struct backtrace_state *state, int descriptor,
|
|||
+ (sections[i].offset - min_offset));
|
||||
}
|
||||
|
||||
if (!backtrace_dwarf_add (state, /* base_address */ 0, &dwarf_sections,
|
||||
memset (&base_address, 0, sizeof base_address);
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
base_address.m = module_handle - image_base.m;
|
||||
#endif
|
||||
|
||||
if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
|
||||
0, /* FIXME: is_bigendian */
|
||||
NULL, /* altlink */
|
||||
error_callback, data, fileline_fn,
|
||||
|
@ -881,6 +942,53 @@ coff_add (struct backtrace_state *state, int descriptor,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
struct dll_notification_context
|
||||
{
|
||||
struct backtrace_state *state;
|
||||
backtrace_error_callback error_callback;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static VOID CALLBACK
|
||||
dll_notification (ULONG reason,
|
||||
struct dll_notification_data *notification_data,
|
||||
PVOID context)
|
||||
{
|
||||
char module_name[MAX_PATH];
|
||||
int descriptor;
|
||||
struct dll_notification_context* dll_context =
|
||||
(struct dll_notification_context*) context;
|
||||
struct backtrace_state *state = dll_context->state;
|
||||
void *data = dll_context->data;
|
||||
backtrace_error_callback error_callback = dll_context->data;
|
||||
fileline fileline;
|
||||
int found_sym;
|
||||
int found_dwarf;
|
||||
HMODULE module_handle;
|
||||
|
||||
if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED)
|
||||
return;
|
||||
|
||||
if (!GetModuleHandleExW ((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
||||
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
|
||||
(wchar_t*) notification_data->dll_base,
|
||||
&module_handle))
|
||||
return;
|
||||
|
||||
if (!GetModuleFileNameA ((HMODULE) module_handle, module_name, MAX_PATH - 1))
|
||||
return;
|
||||
|
||||
descriptor = backtrace_open (module_name, error_callback, data, NULL);
|
||||
|
||||
if (descriptor < 0)
|
||||
return;
|
||||
|
||||
coff_add (state, descriptor, error_callback, data, &fileline, &found_sym,
|
||||
&found_dwarf, (uintptr_t) module_handle);
|
||||
}
|
||||
#endif /* defined(HAVE_WINDOWS_H) */
|
||||
|
||||
/* Initialize the backtrace data we need from an ELF executable. At
|
||||
the ELF level, all we need to do is find the debug info
|
||||
sections. */
|
||||
|
@ -895,12 +1003,92 @@ backtrace_initialize (struct backtrace_state *state,
|
|||
int found_sym;
|
||||
int found_dwarf;
|
||||
fileline coff_fileline_fn;
|
||||
uintptr_t module_handle = 0;
|
||||
#ifdef HAVE_TLHELP32_H
|
||||
fileline module_fileline_fn;
|
||||
int module_found_sym;
|
||||
HANDLE snapshot;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
HMODULE nt_dll_handle;
|
||||
|
||||
module_handle = (uintptr_t) GetModuleHandle (NULL);
|
||||
#endif
|
||||
|
||||
ret = coff_add (state, descriptor, error_callback, data,
|
||||
&coff_fileline_fn, &found_sym, &found_dwarf);
|
||||
&coff_fileline_fn, &found_sym, &found_dwarf, module_handle);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_TLHELP32_H
|
||||
do
|
||||
{
|
||||
snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
|
||||
}
|
||||
while (snapshot == INVALID_HANDLE_VALUE
|
||||
&& GetLastError () == ERROR_BAD_LENGTH);
|
||||
|
||||
if (snapshot != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
MODULEENTRY32 entry;
|
||||
BOOL ok;
|
||||
entry.dwSize = sizeof (MODULEENTRY32);
|
||||
|
||||
for (ok = Module32First (snapshot, &entry); ok; ok = Module32Next (snapshot, &entry))
|
||||
{
|
||||
if (strcmp (filename, entry.szExePath) == 0)
|
||||
continue;
|
||||
|
||||
module_handle = (uintptr_t) entry.hModule;
|
||||
if (module_handle == 0)
|
||||
continue;
|
||||
|
||||
descriptor = backtrace_open (entry.szExePath, error_callback, data,
|
||||
NULL);
|
||||
if (descriptor < 0)
|
||||
continue;
|
||||
|
||||
coff_add (state, descriptor, error_callback, data,
|
||||
&module_fileline_fn, &module_found_sym, &found_dwarf,
|
||||
module_handle);
|
||||
if (module_found_sym)
|
||||
found_sym = 1;
|
||||
}
|
||||
|
||||
CloseHandle (snapshot);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
nt_dll_handle = GetModuleHandleW (L"ntdll.dll");
|
||||
if (nt_dll_handle)
|
||||
{
|
||||
LDR_REGISTER_FUNCTION register_func;
|
||||
const char register_name[] = "LdrRegisterDllNotification";
|
||||
register_func = (void*) GetProcAddress (nt_dll_handle,
|
||||
register_name);
|
||||
|
||||
if (register_func)
|
||||
{
|
||||
PVOID cookie;
|
||||
struct dll_notification_context *context
|
||||
= backtrace_alloc (state,
|
||||
sizeof (struct dll_notification_context),
|
||||
error_callback, data);
|
||||
|
||||
if (context)
|
||||
{
|
||||
context->state = state;
|
||||
context->data = data;
|
||||
context->error_callback = error_callback;
|
||||
|
||||
register_func (0, &dll_notification, context, &cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* defined(HAVE_WINDOWS_H) */
|
||||
|
||||
if (!state->threaded)
|
||||
{
|
||||
if (found_sym)
|
||||
|
|
2
thirdparty/libbacktrace/posix.c
vendored
2
thirdparty/libbacktrace/posix.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* posix.c -- POSIX file I/O routines for the backtrace library.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
59
thirdparty/libbacktrace/print.c
vendored
59
thirdparty/libbacktrace/print.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* print.c -- Print the current backtrace.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -47,22 +47,6 @@ struct print_data
|
|||
FILE *f;
|
||||
};
|
||||
|
||||
/* Print one level of a backtrace. */
|
||||
|
||||
static int
|
||||
print_callback (void *data, uintptr_t pc, const char *filename, int lineno,
|
||||
const char *function)
|
||||
{
|
||||
struct print_data *pdata = (struct print_data *) data;
|
||||
|
||||
fprintf (pdata->f, "0x%lx %s\n\t%s:%d\n",
|
||||
(unsigned long) pc,
|
||||
function == NULL ? "???" : function,
|
||||
filename == NULL ? "???" : filename,
|
||||
lineno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Print errors to stderr. */
|
||||
|
||||
static void
|
||||
|
@ -78,6 +62,47 @@ error_callback (void *data, const char *msg, int errnum)
|
|||
fputc ('\n', stderr);
|
||||
}
|
||||
|
||||
/* Print one level of a backtrace if we couldn't get a file or function name.
|
||||
Use syminfo to try to get a symbol name. */
|
||||
|
||||
static void print_syminfo_callback (void *data, uintptr_t pc,
|
||||
const char *symname, uintptr_t symval,
|
||||
uintptr_t symsize ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct print_data *pdata = (struct print_data *) data;
|
||||
|
||||
if (symname == NULL)
|
||||
fprintf (pdata->f, "0x%lx ???\n\t???:0\n", (unsigned long) pc);
|
||||
else
|
||||
fprintf (pdata->f, "0x%lx ???\n\t%s+0x%lx:0\n",
|
||||
(unsigned long) pc,
|
||||
symname,
|
||||
(unsigned long) (pc - symval));
|
||||
}
|
||||
|
||||
/* Print one level of a backtrace. */
|
||||
|
||||
static int
|
||||
print_callback (void *data, uintptr_t pc, const char *filename, int lineno,
|
||||
const char *function)
|
||||
{
|
||||
struct print_data *pdata = (struct print_data *) data;
|
||||
|
||||
if (function == NULL && filename == NULL)
|
||||
{
|
||||
backtrace_syminfo (pdata->state, pc, print_syminfo_callback,
|
||||
error_callback, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf (pdata->f, "0x%lx %s\n\t%s:%d\n",
|
||||
(unsigned long) pc,
|
||||
function == NULL ? "???" : function,
|
||||
filename == NULL ? "???" : filename,
|
||||
lineno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Print a backtrace. */
|
||||
|
||||
void __attribute__((noinline))
|
||||
|
|
2
thirdparty/libbacktrace/read.c
vendored
2
thirdparty/libbacktrace/read.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* read.c -- File views without mmap.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
2
thirdparty/libbacktrace/simple.c
vendored
2
thirdparty/libbacktrace/simple.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* simple.c -- The backtrace_simple function.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
2
thirdparty/libbacktrace/sort.c
vendored
2
thirdparty/libbacktrace/sort.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* sort.c -- Sort without allocating memory
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
2
thirdparty/libbacktrace/state.c
vendored
2
thirdparty/libbacktrace/state.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* state.c -- Create the backtrace state.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
Loading…
Reference in a new issue