summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Schleifer <js@webkeks.org>2013-05-25 13:37:05 +0200
committerJonathan Schleifer <js@webkeks.org>2013-05-25 13:40:28 +0200
commit537e08baf51378246b750d35d3372e2603f5115c (patch)
tree023725efde6e7c5a11c0933fe2875cac6e8d668e
parentffb9a2e3aa10f74a7b7cae5ce57dc9fffcf8f815 (diff)
Switch back to backtrace().
The reason is that __builtin_frame_address(n) for n > 0 seems to just crash on most platforms when -fomit-stack-pointer is specified, which seems to be the default for many platforms on -O2. The documentation says that __builtin_frame_address() should return NULL in case it can't get the frame, but it seems to crash instead. Therefore, this commit reverts to using backtrace() from execinfo.h, if available. However, as __builtin_frame_address() seems to always work on PPC (even with -fomit-frame-pointer) and seems to be the only way to get a backtrace on the Wii, this is still used if backtrace() is unavailable and __ppc__ defined.
-rw-r--r--configure.ac28
-rw-r--r--src/exceptions/OFException.h3
-rw-r--r--src/exceptions/OFException.m49
3 files changed, 62 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac
index 4e378882..9863e0a5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -751,15 +751,27 @@ AS_IF([test x"$have_processes" = x"yes"], [
AC_DEFINE(OF_HAVE_PROCESSES, 1, [Whether we have processes])
])
-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_DEFUN([CHECK_BUILTIN_RETURN_ADDRESS], [
+ AC_MSG_CHECKING(for __builtin_return_address)
+ AC_TRY_LINK([], [
+ __builtin_return_address(1);
+ ], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BUILTIN_RETURN_ADDRESS, 1,
+ [Whether we have __builtin_return_address])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
+AC_CHECK_HEADER(execinfo.h, [
+ AC_DEFINE(HAVE_EXECINFO_H, 1, [Whether we have execinfo.h])
+ AC_CHECK_FUNC(backtrace, [
+ AC_DEFINE(HAVE_BACKTRACE, 1, [Whether we have backtrace()])
+ ], [
+ CHECK_BUILTIN_RETURN_ADDRESS
+ ])
], [
- AC_MSG_RESULT(no)
+ CHECK_BUILTIN_RETURN_ADDRESS
])
AS_IF([test x"$objc_runtime" = x"Apple runtime"], [
diff --git a/src/exceptions/OFException.h b/src/exceptions/OFException.h
index 32b8a848..81ae287e 100644
--- a/src/exceptions/OFException.h
+++ b/src/exceptions/OFException.h
@@ -29,7 +29,8 @@
@interface OFException: OFObject
{
Class _inClass;
- void *_returnAddresses[32];
+ void *_backtrace[32];
+ int _backtraceSize;
}
#ifdef OF_HAVE_PROPERTIES
diff --git a/src/exceptions/OFException.m b/src/exceptions/OFException.m
index e350bbea..4dbaf6a3 100644
--- a/src/exceptions/OFException.m
+++ b/src/exceptions/OFException.m
@@ -18,6 +18,9 @@
#include <stdlib.h>
+#ifdef HAVE_EXECINFO_H
+# include <execinfo.h>
+#endif
#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif
@@ -51,16 +54,17 @@
self = [super init];
_inClass = class;
-#ifdef HAVE_BUILTIN_RETURN_ADDRESS
+#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE)
+ _backtraceSize = backtrace(_backtrace, 32);
+#elif defined(HAVE_BUILTIN_RETURN_ADDRESS) && defined(__ppc__)
/*
* 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) \
+# define GET_FRAME(i) \
+ if (__builtin_frame_address(i + 1) == NULL) \
+ goto backtrace_done; \
+ if ((_backtrace[i] = (__builtin_return_address(i))) == NULL) \
goto backtrace_done;
GET_FRAME(0)
GET_FRAME(1)
@@ -115,14 +119,41 @@ backtrace_done:
- (OFArray*)backtrace
{
-#ifdef HAVE_BUILTIN_RETURN_ADDRESS
+#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE)
+ OFMutableArray *backtrace = [OFMutableArray array];
+ void *pool = objc_autoreleasePoolPush();
+ char **symbols;
+
+ if (_backtraceSize < 0)
+ return nil;
+
+ symbols = backtrace_symbols(_backtrace, _backtraceSize);
+ @try {
+ int i;
+
+ for (i = 0; i < _backtraceSize; i++) {
+ OFString *symbol = [OFString
+ stringWithCString: symbols[i]
+ encoding: OF_STRING_ENCODING_NATIVE];
+ [backtrace addObject: symbol];
+ }
+ } @finally {
+ free(symbols);
+ }
+
+ objc_autoreleasePoolPop(pool);
+
+ [backtrace makeImmutable];
+
+ return backtrace;
+#elif defined(HAVE_BUILTIN_RETURN_ADDRESS) && defined(__ppc__)
OFMutableArray *backtrace = [OFMutableArray array];
void *pool = objc_autoreleasePoolPush();
uint_fast8_t i;
- for (i = 0; i < 32 && _returnAddresses[i] != NULL; i++) {
+ for (i = 0; i < 32 && _backtrace[i] != NULL; i++) {
void *addr =
- __builtin_extract_return_addr(_returnAddresses[i]);
+ __builtin_extract_return_addr(_backtrace[i]);
# ifdef HAVE_DLFCN_H
Dl_info info;