Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -466,10 +466,11 @@ AC_DEFINE(HAVE_RANDOM, 1, [Whether we have random()]) ]) ]) AC_CHECK_LIB(dl, dlopen, LIBS="$LIBS -ldl") +AC_CHECK_HEADERS(dlfcn.h) AC_ARG_ENABLE(threads, AS_HELP_STRING([--disable-threads], [disable thread support])) AS_IF([test x"$enable_threads" != x"no"], [ case "$host_os" in @@ -748,11 +749,20 @@ AS_IF([test x"$have_processes" = x"yes"], [ AC_SUBST(OFPROCESS_M, "OFProcess.m") AC_DEFINE(OF_HAVE_PROCESSES, 1, [Whether we have processes]) ]) -AC_CHECK_HEADERS(execinfo.h) +AC_MSG_CHECKING(for __builtin_return_address) +AC_TRY_LINK([], [ + __builtin_return_address(0); +], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_BUILTIN_RETURN_ADDRESS, 1, + [Whether we have __builtin_return_address]) +], [ + AC_MSG_RESULT(no) +]) AS_IF([test x"$objc_runtime" = x"Apple runtime"], [ AC_CHECK_HEADER(Foundation/NSObject.h, [ AC_SUBST(FOUNDATION_COMPAT_M, "foundation-compat.m") AC_SUBST(BRIDGE, "bridge") Index: src/OFPlugin.m ================================================================== --- src/OFPlugin.m +++ src/OFPlugin.m @@ -17,12 +17,12 @@ #include "config.h" #include #include -#ifndef _WIN32 -#include +#ifdef HAVE_DLFCN_H +# include #endif #import "OFPlugin.h" #import "OFString.h" Index: src/exceptions/OFException.h ================================================================== --- src/exceptions/OFException.h +++ src/exceptions/OFException.h @@ -14,12 +14,10 @@ * file. */ #import "OFObject.h" -#define OF_EXCEPTION_MAX_BACKTRACE_SIZE 32 - @class OFString; @class OFArray; @class OFMutableArray; /*! @@ -29,13 +27,11 @@ * the OFAllocFailedException. */ @interface OFException: OFObject { Class _inClass; - OFMutableArray *_backtrace; - void *_backtraceBuffer[OF_EXCEPTION_MAX_BACKTRACE_SIZE]; - int _backtraceSize; + void *_returnAddresses[32]; } #ifdef OF_HAVE_PROPERTIES @property (readonly) Class inClass; #endif Index: src/exceptions/OFException.m ================================================================== --- src/exceptions/OFException.m +++ src/exceptions/OFException.m @@ -16,12 +16,12 @@ #include "config.h" #include -#ifdef HAVE_EXECINFO_H -# include +#ifdef HAVE_DLFCN_H +# include #endif #import "OFException.h" #import "OFString.h" #import "OFArray.h" @@ -49,25 +49,60 @@ - initWithClass: (Class)class { self = [super init]; _inClass = class; -#ifdef HAVE_EXECINFO_H - _backtraceSize = backtrace(_backtraceBuffer, - OF_EXCEPTION_MAX_BACKTRACE_SIZE); +#ifdef HAVE_BUILTIN_RETURN_ADDRESS + /* + * We can't use a loop here, as __builtin_return_address() and + * __builtin_frame_address() only allow a constant as parameter. + */ +# define GET_FRAME(i) \ + if (__builtin_frame_address(i + 1) == NULL) \ + goto backtrace_done; \ + if ((_returnAddresses[i] = ( \ + __builtin_return_address(i))) == NULL) \ + goto backtrace_done; + GET_FRAME(0) + GET_FRAME(1) + GET_FRAME(2) + GET_FRAME(3) + GET_FRAME(4) + GET_FRAME(5) + GET_FRAME(6) + GET_FRAME(7) + GET_FRAME(8) + GET_FRAME(9) + GET_FRAME(10) + GET_FRAME(11) + GET_FRAME(12) + GET_FRAME(13) + GET_FRAME(14) + GET_FRAME(15) + GET_FRAME(16) + GET_FRAME(17) + GET_FRAME(18) + GET_FRAME(19) + GET_FRAME(20) + GET_FRAME(21) + GET_FRAME(22) + GET_FRAME(23) + GET_FRAME(24) + GET_FRAME(25) + GET_FRAME(26) + GET_FRAME(27) + GET_FRAME(28) + GET_FRAME(29) + GET_FRAME(30) + GET_FRAME(31) +# undef GET_FRAME +backtrace_done: #endif return self; } -- (void)dealloc -{ - [_backtrace release]; - - [super dealloc]; -} - - (Class)inClass { return _inClass; } @@ -78,43 +113,43 @@ object_getClass(self), _inClass]; } - (OFArray*)backtrace { -#ifdef HAVE_EXECINFO_H - char **symbols; - - if (_backtrace != nil) - return _backtrace; - - if (_backtraceSize < 1) - return nil; - - symbols = backtrace_symbols(_backtraceBuffer, _backtraceSize); - @try { - int i; - - _backtrace = [[OFMutableArray alloc] init]; - - for (i = 0; i < _backtraceSize; i++) { - void *pool = objc_autoreleasePoolPush(); - OFString *symbol; - - symbol = [OFString - stringWithCString: symbols[i] - encoding: OF_STRING_ENCODING_NATIVE]; - [_backtrace addObject: symbol]; - - objc_autoreleasePoolPop(pool); - } - } @finally { - free(symbols); - } - - [_backtrace makeImmutable]; - - return _backtrace; +#ifdef HAVE_BUILTIN_RETURN_ADDRESS + OFMutableArray *backtrace = [OFMutableArray array]; + void *pool = objc_autoreleasePoolPush(); + uint_fast8_t i; + + for (i = 0; i < 32 && _returnAddresses[i] != NULL; i++) { + void *addr = + __builtin_extract_return_addr(_returnAddresses[i]); +# ifdef HAVE_DLFCN_H + Dl_info info; + + if (dladdr(addr, &info)) { + ptrdiff_t offset = (char*)addr - (char*)info.dli_saddr; + + if (info.dli_sname == NULL) + info.dli_sname = "??"; + + [backtrace addObject: + [OFString stringWithFormat: @"%p <%s+%td> at %s", + addr, info.dli_sname, + offset, + info.dli_fname]]; + } else +# endif + [backtrace addObject: + [OFString stringWithFormat: @"%p", addr]]; + } + + objc_autoreleasePoolPop(pool); + + [backtrace makeImmutable]; + + return backtrace; #else return nil; #endif } @end