mirror of
https://github.com/gnustep/libs-base.git
synced 2025-06-01 09:02:01 +00:00
Merge pull request #83 from triplef/nsexception-unwind
Added NSException support for libunwind
This commit is contained in:
commit
fc3ae59397
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>
|
2019-11-14 Fred Kiefer <fredkiefer@gmx.de>
|
||||||
|
|
||||||
* Headers/Foundation/NSXPCConnection.h,
|
* Headers/Foundation/NSXPCConnection.h,
|
||||||
|
|
|
@ -737,6 +737,9 @@
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#undef HAVE_UNISTD_H
|
#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. */
|
/* Define to 1 if you have the `usleep' function. */
|
||||||
#undef HAVE_USLEEP
|
#undef HAVE_USLEEP
|
||||||
|
|
||||||
|
|
|
@ -565,6 +565,35 @@ GSListModules()
|
||||||
#endif /* USE_BFD */
|
#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)
|
#if defined(_WIN32) && !defined(USE_BFD)
|
||||||
typedef USHORT (WINAPI *CaptureStackBackTraceType)(ULONG,ULONG,PVOID*,PULONG);
|
typedef USHORT (WINAPI *CaptureStackBackTraceType)(ULONG,ULONG,PVOID*,PULONG);
|
||||||
typedef BOOL (WINAPI *SymInitializeType)(HANDLE,char*,BOOL);
|
typedef BOOL (WINAPI *SymInitializeType)(HANDLE,char*,BOOL);
|
||||||
|
@ -846,7 +875,7 @@ unsigned
|
||||||
GSPrivateReturnAddresses(NSUInteger **returns)
|
GSPrivateReturnAddresses(NSUInteger **returns)
|
||||||
{
|
{
|
||||||
unsigned numReturns;
|
unsigned numReturns;
|
||||||
#if HAVE_BACKTRACE
|
#if defined(HAVE_BACKTRACE)
|
||||||
void *addr[MAXFRAMES*sizeof(void*)];
|
void *addr[MAXFRAMES*sizeof(void*)];
|
||||||
|
|
||||||
numReturns = backtrace(addr, MAXFRAMES);
|
numReturns = backtrace(addr, MAXFRAMES);
|
||||||
|
@ -855,6 +884,18 @@ GSPrivateReturnAddresses(NSUInteger **returns)
|
||||||
*returns = malloc(numReturns * sizeof(void*));
|
*returns = malloc(numReturns * sizeof(void*));
|
||||||
memcpy(*returns, addr, 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)
|
#elif defined(_WIN32) && !defined(USE_BFD)
|
||||||
NSUInteger addr[MAXFRAMES];
|
NSUInteger addr[MAXFRAMES];
|
||||||
|
|
||||||
|
@ -1225,6 +1266,36 @@ GSPrivateReturnAddresses(NSUInteger **returns)
|
||||||
}
|
}
|
||||||
symbols = [[NSArray alloc] initWithObjects: symbolArray count: count];
|
symbols = [[NSArray alloc] initWithObjects: symbolArray count: count];
|
||||||
free(strs);
|
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
|
#else
|
||||||
NSMutableArray *a;
|
NSMutableArray *a;
|
||||||
|
|
||||||
|
@ -1233,8 +1304,8 @@ GSPrivateReturnAddresses(NSUInteger **returns)
|
||||||
{
|
{
|
||||||
NSString *s;
|
NSString *s;
|
||||||
|
|
||||||
s = [[NSString alloc] initWithFormat: @"%@: symbol not available",
|
s = [[NSString alloc] initWithFormat: @"%p: symbol not available",
|
||||||
[a objectAtIndex: i]];
|
[[a objectAtIndex: i] pointerValue]];
|
||||||
[a replaceObjectAtIndex: i withObject: s];
|
[a replaceObjectAtIndex: i withObject: s];
|
||||||
RELEASE(s);
|
RELEASE(s);
|
||||||
}
|
}
|
||||||
|
|
13
configure
vendored
13
configure
vendored
|
@ -9079,6 +9079,19 @@ fi
|
||||||
done
|
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
|
# These headers/functions needed by NSLog.m
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
|
|
|
@ -2321,6 +2321,8 @@ fi
|
||||||
|
|
||||||
AC_CHECK_FUNCS(__builtin_extract_return_address)
|
AC_CHECK_FUNCS(__builtin_extract_return_address)
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS(unwind.h)
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# These headers/functions needed by NSLog.m
|
# These headers/functions needed by NSLog.m
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue