Added NSException symbolication support using libunwind.

This is used when backtrace() is unavailable.
This commit is contained in:
Frederik Seiffert 2019-06-13 17:24:28 +02:00
parent 1915415b48
commit 0eedef5080
5 changed files with 99 additions and 3 deletions

View file

@ -1,3 +1,10 @@
2019-11-15 Frederik Seiffert <frederik@algoriddim.com>
* configure.ac: check for unwind.h
* configure: regenerate
* Source/NSException.m: Added support for backtrace symbolication
using libunwind, which will be used when backtrace() is unavailable.
2019-11-14 Fred Kiefer <fredkiefer@gmx.de>
* Headers/Foundation/NSXPCConnection.h,

View file

@ -737,6 +737,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the <unwind.h> header file. */
#undef HAVE_UNWIND_H
/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP

View file

@ -565,6 +565,35 @@ GSListModules()
#endif /* USE_BFD */
#if defined(HAVE_UNWIND_H) && !defined(HAVE_BACKTRACE)
#include <unwind.h>
#include <dlfcn.h>
struct GSBacktraceState
{
void **current;
void **end;
};
static _Unwind_Reason_Code
GSUnwindCallback(struct _Unwind_Context* context, void* arg)
{
struct GSBacktraceState *state = (struct GSBacktraceState*)arg;
uintptr_t pc = _Unwind_GetIP(context);
if (pc) {
if (state->current == state->end) {
return _URC_END_OF_STACK;
} else {
*state->current++ = (void*)pc;
}
}
return 0; //_URC_OK/_URC_NO_REASON
}
#endif /* HAVE_UNWIND_H && !HAVE_BACKTRACE */
#if defined(_WIN32) && !defined(USE_BFD)
typedef USHORT (WINAPI *CaptureStackBackTraceType)(ULONG,ULONG,PVOID*,PULONG);
typedef BOOL (WINAPI *SymInitializeType)(HANDLE,char*,BOOL);
@ -846,7 +875,7 @@ unsigned
GSPrivateReturnAddresses(NSUInteger **returns)
{
unsigned numReturns;
#if HAVE_BACKTRACE
#if defined(HAVE_BACKTRACE)
void *addr[MAXFRAMES*sizeof(void*)];
numReturns = backtrace(addr, MAXFRAMES);
@ -855,6 +884,18 @@ GSPrivateReturnAddresses(NSUInteger **returns)
*returns = malloc(numReturns * sizeof(void*));
memcpy(*returns, addr, numReturns * sizeof(void*));
}
#elif defined(HAVE_UNWIND_H)
void *addr[MAXFRAMES];
struct GSBacktraceState state = {addr, addr + MAXFRAMES};
_Unwind_Backtrace(GSUnwindCallback, &state);
numReturns = state.current - addr;
if (numReturns > 0)
{
*returns = malloc(numReturns * sizeof(void*));
memcpy(*returns, addr, numReturns * sizeof(void*));
}
#elif defined(_WIN32) && !defined(USE_BFD)
NSUInteger addr[MAXFRAMES];
@ -1225,6 +1266,36 @@ GSPrivateReturnAddresses(NSUInteger **returns)
}
symbols = [[NSArray alloc] initWithObjects: symbolArray count: count];
free(strs);
#elif defined(HAVE_UNWIND_H)
void **ptrs = (void**)&returns[FrameOffset];
NSString **symbolArray;
symbolArray = alloca(count * sizeof(NSString*));
for (i = 0; i < count; i++)
{
const void *addr = ptrs[i];
Dl_info info;
if (dladdr(addr, &info)) {
const char *libname = "unknown";
if (info.dli_fname) {
// strip library path
char *delim = strrchr(info.dli_fname, '/');
libname = delim ? delim + 1 : info.dli_fname;
}
if (info.dli_sname) {
symbolArray[i] = [NSString stringWithFormat:
@"%lu: %p %s %s + %d", (unsigned long)i, addr, libname,
info.dli_sname, (int)(addr - info.dli_saddr)];
} else {
symbolArray[i] = [NSString stringWithFormat:
@"%lu: %p %s unknown", (unsigned long)i, addr, libname];
}
} else {
symbolArray[i] = [NSString stringWithFormat:
@"%lu: %p unknown", (unsigned long)i, addr];
}
}
symbols = [[NSArray alloc] initWithObjects: symbolArray count: count];
#else
NSMutableArray *a;
@ -1233,8 +1304,8 @@ GSPrivateReturnAddresses(NSUInteger **returns)
{
NSString *s;
s = [[NSString alloc] initWithFormat: @"%@: symbol not available",
[a objectAtIndex: i]];
s = [[NSString alloc] initWithFormat: @"%p: symbol not available",
[[a objectAtIndex: i] pointerValue]];
[a replaceObjectAtIndex: i withObject: s];
RELEASE(s);
}

13
configure vendored
View file

@ -9079,6 +9079,19 @@ fi
done
for ac_header in unwind.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "unwind.h" "ac_cv_header_unwind_h" "$ac_includes_default"
if test "x$ac_cv_header_unwind_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UNWIND_H 1
_ACEOF
fi
done
#--------------------------------------------------------------------
# These headers/functions needed by NSLog.m
#--------------------------------------------------------------------

View file

@ -2321,6 +2321,8 @@ fi
AC_CHECK_FUNCS(__builtin_extract_return_address)
AC_CHECK_HEADERS(unwind.h)
#--------------------------------------------------------------------
# These headers/functions needed by NSLog.m
#--------------------------------------------------------------------