ObjFW  Check-in [f2a8bdf254]

Overview
Comment: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.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: f2a8bdf254c3b166d95554e7f7a0804133fdda0c612c1d1f70e85a73607bfd28
User & Date: js on 2013-05-25 11:40:28
Other Links: manifest | tags
Context
2013-05-26
17:24
OFTCPSocket.h: Explicitly import objfw-defs.h. check-in: 49b741b30e user: js tags: trunk
2013-05-25
11:40
Switch back to backtrace(). check-in: f2a8bdf254 user: js tags: trunk
2013-05-22
21:09
Show a backtrace for uncaught exceptions. check-in: 32230a1615 user: js tags: trunk
Changes

Modified configure.ac from [c6b89e288b] to [fe25322d35].

747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762











763
764
765
766
767
768
769
		;;
esac
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_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")








>
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>







747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
		;;
esac
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_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
	])
], [
	CHECK_BUILTIN_RETURN_ADDRESS
])

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")

Modified src/exceptions/OFException.h from [a50325ba8b] to [3edc7f9b6e].

25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
 *
 * The OFException class is the base class for all exceptions in ObjFW, except
 * the OFAllocFailedException.
 */
@interface OFException: OFObject
{
	Class _inClass;
	void *_returnAddresses[32];

}

#ifdef OF_HAVE_PROPERTIES
@property (readonly) Class inClass;
#endif

/*!







|
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 *
 * The OFException class is the base class for all exceptions in ObjFW, except
 * the OFAllocFailedException.
 */
@interface OFException: OFObject
{
	Class _inClass;
	void *_backtrace[32];
	int _backtraceSize;
}

#ifdef OF_HAVE_PROPERTIES
@property (readonly) Class inClass;
#endif

/*!

Modified src/exceptions/OFException.m from [18d7beaf46] to [fbd2e39b2b].

14
15
16
17
18
19
20



21
22
23
24
25
26
27
 * file.
 */

#include "config.h"

#include <stdlib.h>




#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif

#import "OFException.h"
#import "OFString.h"
#import "OFArray.h"







>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 * file.
 */

#include "config.h"

#include <stdlib.h>

#ifdef HAVE_EXECINFO_H
# include <execinfo.h>
#endif
#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif

#import "OFException.h"
#import "OFString.h"
#import "OFArray.h"
47
48
49
50
51
52
53


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
}

- initWithClass: (Class)class
{
	self = [super init];

	_inClass = class;


#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)







>
>
|




|
|
|
<
|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
}

- initWithClass: (Class)class
{
	self = [super init];

	_inClass = class;
#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 ((_backtrace[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)
111
112
113
114
115
116
117



























118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
	return [OFString stringWithFormat:
	    @"An exception of class %@ occurred in class %@!",
	    object_getClass(self), _inClass];
}

- (OFArray*)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)







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|




|

|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
	return [OFString stringWithFormat:
	    @"An exception of class %@ occurred in class %@!",
	    object_getClass(self), _inClass];
}

- (OFArray*)backtrace
{
#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 && _backtrace[i] != NULL; i++) {
		void *addr =
		    __builtin_extract_return_addr(_backtrace[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)