mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 17:10:48 +00:00
Added NSException symbolication support using libunwind.
This is used when backtrace() is unavailable.
This commit is contained in:
parent
1915415b48
commit
0eedef5080
5 changed files with 99 additions and 3 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
13
configure
vendored
|
@ -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
|
||||
#--------------------------------------------------------------------
|
||||
|
|
|
@ -2321,6 +2321,8 @@ fi
|
|||
|
||||
AC_CHECK_FUNCS(__builtin_extract_return_address)
|
||||
|
||||
AC_CHECK_HEADERS(unwind.h)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# These headers/functions needed by NSLog.m
|
||||
#--------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue