Skip to content

Commit

Permalink
1) Use a native Windows way to determine the stacktrace; 2) Fix a use…
Browse files Browse the repository at this point in the history
… of uninitialized bytes in pecoff.c; 3) Fix a use of undefined memory in pecoff.c

1) Note: as we target MINGW here, we still want to look up the symbols via
the DWARF method (the native Windows way would be to call the
SymFromAddr() function, but that would require .pdb files which MINGW
does not produce).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

2) This updates the local declaration of `str_size` to always be 4 bytes instead of
platform-dependent as its initialization later on only fills in 4 bytes instead
of all the bytes of `size_t`.
Originally reported as rust-lang/rust#28447 this was fixed in
rust-lang/rust#30908

3) In rust-lang/rust#39468 it was discovered that this could cause a crash in
libbacktrace due to freeing uninitialized memory, and this specific instance was
fixed in rust-lang/rust#39509
  • Loading branch information
johnsonjh committed Oct 18, 2022
1 parent a63d260 commit 5c3b5d4
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 2 deletions.
40 changes: 40 additions & 0 deletions backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,43 @@ unwind (struct _Unwind_Context *context, void *vdata)
return _URC_NO_REASON;
}

#if NATIVE_WIN32_STACKTRACE
static int win32_unwind(struct backtrace_data *bdata)
{
static int initialized;
static USHORT (*RtlCaptureStackBackTrace)(ULONG, ULONG, PVOID*, PULONG);
void *pcs[62];
int i, count;

if (!initialized) {
HMODULE kernel32 =
LoadLibraryExW(L"kernel32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (kernel32)
RtlCaptureStackBackTrace =
(void *)GetProcAddress(kernel32, "RtlCaptureStackBackTrace");
initialized = 1;
if (!RtlCaptureStackBackTrace)
return -1;
}

count = RtlCaptureStackBackTrace(2,
sizeof(pcs) / sizeof(pcs[0]), pcs, NULL);
for (i = 0; i < count; i++) {
uintptr_t pc = (uintptr_t)pcs[i];

if (!bdata->can_alloc)
bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL);
else
bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
bdata->error_callback, bdata->data);
if (bdata->ret != 0)
return _URC_END_OF_STACK;
}

return _URC_NO_REASON;
}
#endif

/* Get a stack backtrace. */

int __attribute__((noinline))
Expand Down Expand Up @@ -124,6 +161,9 @@ backtrace_full (struct backtrace_state *state, int skip,
bdata.can_alloc = 1;
}

#if NATIVE_WIN32_STACKTRACE
if (win32_unwind(&bdata) < 0)
#endif
_Unwind_Backtrace (unwind, &bdata);
return bdata.ret;
}
22 changes: 22 additions & 0 deletions fileline.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,30 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "internal.h"

#ifndef HAVE_GETEXECNAME
#if defined(__WIN32__) && !defined(__MSYS__) && !defined(__CYGWIN__)
/*
* Windows-specific implementation of getexecname();
* MSYS/Cygwin want to fall back to /proc/self/exe instead.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

static inline const char *getexecname(void)
{
static char path[32768]; /* Allow for long paths, i.e. do not use MAX_PATH */

switch (GetModuleFileNameA(NULL, path, sizeof(path))) {
case 0:
case sizeof(path):
return NULL;
}

return path;
}
#else
#define getexecname() NULL
#endif
#endif

#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)

Expand Down
6 changes: 6 additions & 0 deletions internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ POSSIBILITY OF SUCH DAMAGE. */
# endif
#endif

#if defined(__WIN32__) && !defined(__MSYS__) && !defined(__CYGWIN__)
#define NATIVE_WIN32_STACKTRACE 1
#else
#define NATIVE_WIN32_STACKTRACE 0
#endif

#ifndef HAVE_SYNC_FUNCTIONS

/* Define out the sync functions. These should never be called if
Expand Down
4 changes: 2 additions & 2 deletions pecoff.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,9 +595,9 @@ coff_add (struct backtrace_state *state, int descriptor,
const b_coff_section_header *sects;
struct backtrace_view str_view;
int str_view_valid;
size_t str_size;
uint32_t str_size;
off_t str_off;
struct backtrace_view syms_view;
struct backtrace_view syms_view = {0};
off_t syms_off;
size_t syms_size;
int syms_view_valid;
Expand Down

0 comments on commit 5c3b5d4

Please sign in to comment.