Fixups for stack handling

This commit is contained in:
Richard Frith-Macdonald 2018-03-27 07:06:17 +01:00
parent 76014b0983
commit ebfe915619
5 changed files with 276 additions and 369 deletions

View file

@ -1,3 +1,13 @@
2018-03-27 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSPrivate.h:
* Source/NSDebug.m:
* Source/NSException.m:
* Source/NSThread.m:
Move stack info code from NSDebug to NSException so its all in one
place and. Make thread call stack addresses method use windows code
as well as libbacktrace.
2018-03-26 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSDebug.m:

View file

@ -450,11 +450,6 @@ typedef NSRange (*GSRSFunc)(id, id, unsigned, NSRange);
GSRSFunc
GSPrivateRangeOfString(NSString *receiver, NSString *target) GS_ATTRIB_PRIVATE;
/* Function to return the current stack return addresses.
*/
NSMutableArray *
GSPrivateStackAddresses(void) GS_ATTRIB_PRIVATE;
/* Function to return the hash value for a small integer (used by NSNumber).
*/
unsigned

View file

@ -755,367 +755,6 @@ GSDebugAllocationListRecordedObjects(Class c)
return answer;
}
#if !defined(HAVE_BUILTIN_EXTRACT_RETURN_ADDRESS)
# define __builtin_extract_return_address(X) X
#endif
#define _NS_FRAME_HACK(a) \
case a: env->addr = __builtin_frame_address(a + 1); break;
#define _NS_RETURN_HACK(a) \
case a: env->addr = (__builtin_frame_address(a + 1) ? \
__builtin_extract_return_address(__builtin_return_address(a + 1)) : 0); break;
/*
* The following horrible signal handling code is a workaround for the fact
* that the __builtin_frame_address() and __builtin_return_address()
* functions are not reliable (at least not on my EM64T based system) and
* will sometimes walk off the stack and access illegal memory locations.
* In order to prevent such an occurrance from crashing the application,
* we use sigsetjmp() and siglongjmp() to ensure that we can recover, and
* we keep the jump buffer in thread-local memory to avoid possible thread
* safety issues.
* Of course this will fail horribly if an exception occurs in one of the
* few methods we use to manage the per-thread jump buffer.
*/
#if defined(HAVE_SYS_SIGNAL_H)
# include <sys/signal.h>
#elif defined(HAVE_SIGNAL_H)
# include <signal.h>
#endif
#if defined(_WIN32)
#ifndef SIGBUS
#define SIGBUS SIGILL
#endif
#endif
/* sigsetjmp may be a function or a macro. The test for the function is
* done at configure time so we can tell here if either is available.
*/
#if !defined(HAVE_SIGSETJMP) && !defined(sigsetjmp)
#define siglongjmp(A,B) longjmp(A,B)
#define sigsetjmp(A,B) setjmp(A)
#define sigjmp_buf jmp_buf
#endif
typedef struct {
sigjmp_buf buf;
void *addr;
void (*bus)(int);
void (*segv)(int);
} jbuf_type;
static jbuf_type *
jbuf()
{
NSMutableData *d;
NSMutableDictionary *dict;
dict = [[NSThread currentThread] threadDictionary];
d = [dict objectForKey: @"GSjbuf"];
if (d == nil)
{
d = [[NSMutableData alloc] initWithLength: sizeof(jbuf_type)];
[dict setObject: d forKey: @"GSjbuf"];
RELEASE(d);
}
return (jbuf_type*)[d mutableBytes];
}
static void
recover(int sig)
{
siglongjmp(jbuf()->buf, 1);
}
void *
NSFrameAddress(NSUInteger offset)
{
jbuf_type *env;
env = jbuf();
if (sigsetjmp(env->buf, 1) == 0)
{
env->segv = signal(SIGSEGV, recover);
env->bus = signal(SIGBUS, recover);
switch (offset)
{
_NS_FRAME_HACK(0); _NS_FRAME_HACK(1); _NS_FRAME_HACK(2);
_NS_FRAME_HACK(3); _NS_FRAME_HACK(4); _NS_FRAME_HACK(5);
_NS_FRAME_HACK(6); _NS_FRAME_HACK(7); _NS_FRAME_HACK(8);
_NS_FRAME_HACK(9); _NS_FRAME_HACK(10); _NS_FRAME_HACK(11);
_NS_FRAME_HACK(12); _NS_FRAME_HACK(13); _NS_FRAME_HACK(14);
_NS_FRAME_HACK(15); _NS_FRAME_HACK(16); _NS_FRAME_HACK(17);
_NS_FRAME_HACK(18); _NS_FRAME_HACK(19); _NS_FRAME_HACK(20);
_NS_FRAME_HACK(21); _NS_FRAME_HACK(22); _NS_FRAME_HACK(23);
_NS_FRAME_HACK(24); _NS_FRAME_HACK(25); _NS_FRAME_HACK(26);
_NS_FRAME_HACK(27); _NS_FRAME_HACK(28); _NS_FRAME_HACK(29);
_NS_FRAME_HACK(30); _NS_FRAME_HACK(31); _NS_FRAME_HACK(32);
_NS_FRAME_HACK(33); _NS_FRAME_HACK(34); _NS_FRAME_HACK(35);
_NS_FRAME_HACK(36); _NS_FRAME_HACK(37); _NS_FRAME_HACK(38);
_NS_FRAME_HACK(39); _NS_FRAME_HACK(40); _NS_FRAME_HACK(41);
_NS_FRAME_HACK(42); _NS_FRAME_HACK(43); _NS_FRAME_HACK(44);
_NS_FRAME_HACK(45); _NS_FRAME_HACK(46); _NS_FRAME_HACK(47);
_NS_FRAME_HACK(48); _NS_FRAME_HACK(49); _NS_FRAME_HACK(50);
_NS_FRAME_HACK(51); _NS_FRAME_HACK(52); _NS_FRAME_HACK(53);
_NS_FRAME_HACK(54); _NS_FRAME_HACK(55); _NS_FRAME_HACK(56);
_NS_FRAME_HACK(57); _NS_FRAME_HACK(58); _NS_FRAME_HACK(59);
_NS_FRAME_HACK(60); _NS_FRAME_HACK(61); _NS_FRAME_HACK(62);
_NS_FRAME_HACK(63); _NS_FRAME_HACK(64); _NS_FRAME_HACK(65);
_NS_FRAME_HACK(66); _NS_FRAME_HACK(67); _NS_FRAME_HACK(68);
_NS_FRAME_HACK(69); _NS_FRAME_HACK(70); _NS_FRAME_HACK(71);
_NS_FRAME_HACK(72); _NS_FRAME_HACK(73); _NS_FRAME_HACK(74);
_NS_FRAME_HACK(75); _NS_FRAME_HACK(76); _NS_FRAME_HACK(77);
_NS_FRAME_HACK(78); _NS_FRAME_HACK(79); _NS_FRAME_HACK(80);
_NS_FRAME_HACK(81); _NS_FRAME_HACK(82); _NS_FRAME_HACK(83);
_NS_FRAME_HACK(84); _NS_FRAME_HACK(85); _NS_FRAME_HACK(86);
_NS_FRAME_HACK(87); _NS_FRAME_HACK(88); _NS_FRAME_HACK(89);
_NS_FRAME_HACK(90); _NS_FRAME_HACK(91); _NS_FRAME_HACK(92);
_NS_FRAME_HACK(93); _NS_FRAME_HACK(94); _NS_FRAME_HACK(95);
_NS_FRAME_HACK(96); _NS_FRAME_HACK(97); _NS_FRAME_HACK(98);
_NS_FRAME_HACK(99);
default: env->addr = NULL; break;
}
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
else
{
env = jbuf();
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
env->addr = NULL;
}
return env->addr;
}
NSUInteger NSCountFrames(void)
{
jbuf_type *env;
env = jbuf();
if (sigsetjmp(env->buf, 1) == 0)
{
env->segv = signal(SIGSEGV, recover);
env->bus = signal(SIGBUS, recover);
env->addr = 0;
#define _NS_COUNT_HACK(X) if (__builtin_frame_address(X + 1) == 0) \
goto done; else env->addr = (void*)(X + 1);
_NS_COUNT_HACK(0); _NS_COUNT_HACK(1); _NS_COUNT_HACK(2);
_NS_COUNT_HACK(3); _NS_COUNT_HACK(4); _NS_COUNT_HACK(5);
_NS_COUNT_HACK(6); _NS_COUNT_HACK(7); _NS_COUNT_HACK(8);
_NS_COUNT_HACK(9); _NS_COUNT_HACK(10); _NS_COUNT_HACK(11);
_NS_COUNT_HACK(12); _NS_COUNT_HACK(13); _NS_COUNT_HACK(14);
_NS_COUNT_HACK(15); _NS_COUNT_HACK(16); _NS_COUNT_HACK(17);
_NS_COUNT_HACK(18); _NS_COUNT_HACK(19); _NS_COUNT_HACK(20);
_NS_COUNT_HACK(21); _NS_COUNT_HACK(22); _NS_COUNT_HACK(23);
_NS_COUNT_HACK(24); _NS_COUNT_HACK(25); _NS_COUNT_HACK(26);
_NS_COUNT_HACK(27); _NS_COUNT_HACK(28); _NS_COUNT_HACK(29);
_NS_COUNT_HACK(30); _NS_COUNT_HACK(31); _NS_COUNT_HACK(32);
_NS_COUNT_HACK(33); _NS_COUNT_HACK(34); _NS_COUNT_HACK(35);
_NS_COUNT_HACK(36); _NS_COUNT_HACK(37); _NS_COUNT_HACK(38);
_NS_COUNT_HACK(39); _NS_COUNT_HACK(40); _NS_COUNT_HACK(41);
_NS_COUNT_HACK(42); _NS_COUNT_HACK(43); _NS_COUNT_HACK(44);
_NS_COUNT_HACK(45); _NS_COUNT_HACK(46); _NS_COUNT_HACK(47);
_NS_COUNT_HACK(48); _NS_COUNT_HACK(49); _NS_COUNT_HACK(50);
_NS_COUNT_HACK(51); _NS_COUNT_HACK(52); _NS_COUNT_HACK(53);
_NS_COUNT_HACK(54); _NS_COUNT_HACK(55); _NS_COUNT_HACK(56);
_NS_COUNT_HACK(57); _NS_COUNT_HACK(58); _NS_COUNT_HACK(59);
_NS_COUNT_HACK(60); _NS_COUNT_HACK(61); _NS_COUNT_HACK(62);
_NS_COUNT_HACK(63); _NS_COUNT_HACK(64); _NS_COUNT_HACK(65);
_NS_COUNT_HACK(66); _NS_COUNT_HACK(67); _NS_COUNT_HACK(68);
_NS_COUNT_HACK(69); _NS_COUNT_HACK(70); _NS_COUNT_HACK(71);
_NS_COUNT_HACK(72); _NS_COUNT_HACK(73); _NS_COUNT_HACK(74);
_NS_COUNT_HACK(75); _NS_COUNT_HACK(76); _NS_COUNT_HACK(77);
_NS_COUNT_HACK(78); _NS_COUNT_HACK(79); _NS_COUNT_HACK(80);
_NS_COUNT_HACK(81); _NS_COUNT_HACK(82); _NS_COUNT_HACK(83);
_NS_COUNT_HACK(84); _NS_COUNT_HACK(85); _NS_COUNT_HACK(86);
_NS_COUNT_HACK(87); _NS_COUNT_HACK(88); _NS_COUNT_HACK(89);
_NS_COUNT_HACK(90); _NS_COUNT_HACK(91); _NS_COUNT_HACK(92);
_NS_COUNT_HACK(93); _NS_COUNT_HACK(94); _NS_COUNT_HACK(95);
_NS_COUNT_HACK(96); _NS_COUNT_HACK(97); _NS_COUNT_HACK(98);
_NS_COUNT_HACK(99);
done:
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
else
{
env = jbuf();
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
return (uintptr_t)env->addr;
}
void *
NSReturnAddress(NSUInteger offset)
{
jbuf_type *env;
env = jbuf();
if (sigsetjmp(env->buf, 1) == 0)
{
env->segv = signal(SIGSEGV, recover);
env->bus = signal(SIGBUS, recover);
switch (offset)
{
_NS_RETURN_HACK(0); _NS_RETURN_HACK(1); _NS_RETURN_HACK(2);
_NS_RETURN_HACK(3); _NS_RETURN_HACK(4); _NS_RETURN_HACK(5);
_NS_RETURN_HACK(6); _NS_RETURN_HACK(7); _NS_RETURN_HACK(8);
_NS_RETURN_HACK(9); _NS_RETURN_HACK(10); _NS_RETURN_HACK(11);
_NS_RETURN_HACK(12); _NS_RETURN_HACK(13); _NS_RETURN_HACK(14);
_NS_RETURN_HACK(15); _NS_RETURN_HACK(16); _NS_RETURN_HACK(17);
_NS_RETURN_HACK(18); _NS_RETURN_HACK(19); _NS_RETURN_HACK(20);
_NS_RETURN_HACK(21); _NS_RETURN_HACK(22); _NS_RETURN_HACK(23);
_NS_RETURN_HACK(24); _NS_RETURN_HACK(25); _NS_RETURN_HACK(26);
_NS_RETURN_HACK(27); _NS_RETURN_HACK(28); _NS_RETURN_HACK(29);
_NS_RETURN_HACK(30); _NS_RETURN_HACK(31); _NS_RETURN_HACK(32);
_NS_RETURN_HACK(33); _NS_RETURN_HACK(34); _NS_RETURN_HACK(35);
_NS_RETURN_HACK(36); _NS_RETURN_HACK(37); _NS_RETURN_HACK(38);
_NS_RETURN_HACK(39); _NS_RETURN_HACK(40); _NS_RETURN_HACK(41);
_NS_RETURN_HACK(42); _NS_RETURN_HACK(43); _NS_RETURN_HACK(44);
_NS_RETURN_HACK(45); _NS_RETURN_HACK(46); _NS_RETURN_HACK(47);
_NS_RETURN_HACK(48); _NS_RETURN_HACK(49); _NS_RETURN_HACK(50);
_NS_RETURN_HACK(51); _NS_RETURN_HACK(52); _NS_RETURN_HACK(53);
_NS_RETURN_HACK(54); _NS_RETURN_HACK(55); _NS_RETURN_HACK(56);
_NS_RETURN_HACK(57); _NS_RETURN_HACK(58); _NS_RETURN_HACK(59);
_NS_RETURN_HACK(60); _NS_RETURN_HACK(61); _NS_RETURN_HACK(62);
_NS_RETURN_HACK(63); _NS_RETURN_HACK(64); _NS_RETURN_HACK(65);
_NS_RETURN_HACK(66); _NS_RETURN_HACK(67); _NS_RETURN_HACK(68);
_NS_RETURN_HACK(69); _NS_RETURN_HACK(70); _NS_RETURN_HACK(71);
_NS_RETURN_HACK(72); _NS_RETURN_HACK(73); _NS_RETURN_HACK(74);
_NS_RETURN_HACK(75); _NS_RETURN_HACK(76); _NS_RETURN_HACK(77);
_NS_RETURN_HACK(78); _NS_RETURN_HACK(79); _NS_RETURN_HACK(80);
_NS_RETURN_HACK(81); _NS_RETURN_HACK(82); _NS_RETURN_HACK(83);
_NS_RETURN_HACK(84); _NS_RETURN_HACK(85); _NS_RETURN_HACK(86);
_NS_RETURN_HACK(87); _NS_RETURN_HACK(88); _NS_RETURN_HACK(89);
_NS_RETURN_HACK(90); _NS_RETURN_HACK(91); _NS_RETURN_HACK(92);
_NS_RETURN_HACK(93); _NS_RETURN_HACK(94); _NS_RETURN_HACK(95);
_NS_RETURN_HACK(96); _NS_RETURN_HACK(97); _NS_RETURN_HACK(98);
_NS_RETURN_HACK(99);
default: env->addr = NULL; break;
}
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
else
{
env = jbuf();
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
env->addr = NULL;
}
return env->addr;
}
NSMutableArray *
GSPrivateStackAddresses(void)
{
NSMutableArray *stack;
NSAutoreleasePool *pool;
#if HAVE_BACKTRACE
void *addresses[1024];
int n = backtrace(addresses, 1024);
int i;
stack = [NSMutableArray arrayWithCapacity: n];
pool = [NSAutoreleasePool new];
for (i = 0; i < n; i++)
{
[stack addObject: [NSValue valueWithPointer: addresses[i]]];
}
#else
unsigned n = NSCountFrames();
unsigned i;
jbuf_type *env;
stack = [NSMutableArray arrayWithCapacity: n];
pool = [NSAutoreleasePool new];
/* There should be more frame addresses than return addresses.
*/
if (n > 0)
{
n--;
}
if (n > 0)
{
n--;
}
env = jbuf();
if (sigsetjmp(env->buf, 1) == 0)
{
env->segv = signal(SIGSEGV, recover);
env->bus = signal(SIGBUS, recover);
for (i = 0; i < n; i++)
{
switch (i)
{
_NS_RETURN_HACK(0); _NS_RETURN_HACK(1); _NS_RETURN_HACK(2);
_NS_RETURN_HACK(3); _NS_RETURN_HACK(4); _NS_RETURN_HACK(5);
_NS_RETURN_HACK(6); _NS_RETURN_HACK(7); _NS_RETURN_HACK(8);
_NS_RETURN_HACK(9); _NS_RETURN_HACK(10); _NS_RETURN_HACK(11);
_NS_RETURN_HACK(12); _NS_RETURN_HACK(13); _NS_RETURN_HACK(14);
_NS_RETURN_HACK(15); _NS_RETURN_HACK(16); _NS_RETURN_HACK(17);
_NS_RETURN_HACK(18); _NS_RETURN_HACK(19); _NS_RETURN_HACK(20);
_NS_RETURN_HACK(21); _NS_RETURN_HACK(22); _NS_RETURN_HACK(23);
_NS_RETURN_HACK(24); _NS_RETURN_HACK(25); _NS_RETURN_HACK(26);
_NS_RETURN_HACK(27); _NS_RETURN_HACK(28); _NS_RETURN_HACK(29);
_NS_RETURN_HACK(30); _NS_RETURN_HACK(31); _NS_RETURN_HACK(32);
_NS_RETURN_HACK(33); _NS_RETURN_HACK(34); _NS_RETURN_HACK(35);
_NS_RETURN_HACK(36); _NS_RETURN_HACK(37); _NS_RETURN_HACK(38);
_NS_RETURN_HACK(39); _NS_RETURN_HACK(40); _NS_RETURN_HACK(41);
_NS_RETURN_HACK(42); _NS_RETURN_HACK(43); _NS_RETURN_HACK(44);
_NS_RETURN_HACK(45); _NS_RETURN_HACK(46); _NS_RETURN_HACK(47);
_NS_RETURN_HACK(48); _NS_RETURN_HACK(49); _NS_RETURN_HACK(50);
_NS_RETURN_HACK(51); _NS_RETURN_HACK(52); _NS_RETURN_HACK(53);
_NS_RETURN_HACK(54); _NS_RETURN_HACK(55); _NS_RETURN_HACK(56);
_NS_RETURN_HACK(57); _NS_RETURN_HACK(58); _NS_RETURN_HACK(59);
_NS_RETURN_HACK(60); _NS_RETURN_HACK(61); _NS_RETURN_HACK(62);
_NS_RETURN_HACK(63); _NS_RETURN_HACK(64); _NS_RETURN_HACK(65);
_NS_RETURN_HACK(66); _NS_RETURN_HACK(67); _NS_RETURN_HACK(68);
_NS_RETURN_HACK(69); _NS_RETURN_HACK(70); _NS_RETURN_HACK(71);
_NS_RETURN_HACK(72); _NS_RETURN_HACK(73); _NS_RETURN_HACK(74);
_NS_RETURN_HACK(75); _NS_RETURN_HACK(76); _NS_RETURN_HACK(77);
_NS_RETURN_HACK(78); _NS_RETURN_HACK(79); _NS_RETURN_HACK(80);
_NS_RETURN_HACK(81); _NS_RETURN_HACK(82); _NS_RETURN_HACK(83);
_NS_RETURN_HACK(84); _NS_RETURN_HACK(85); _NS_RETURN_HACK(86);
_NS_RETURN_HACK(87); _NS_RETURN_HACK(88); _NS_RETURN_HACK(89);
_NS_RETURN_HACK(90); _NS_RETURN_HACK(91); _NS_RETURN_HACK(92);
_NS_RETURN_HACK(93); _NS_RETURN_HACK(94); _NS_RETURN_HACK(95);
_NS_RETURN_HACK(96); _NS_RETURN_HACK(97); _NS_RETURN_HACK(98);
_NS_RETURN_HACK(99);
default: env->addr = 0; break;
}
if (env->addr == 0)
{
break;
}
[stack addObject: [NSValue valueWithPointer: env->addr]];
}
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
else
{
env = jbuf();
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
#endif
[pool drain];
return stack;
}
const char *
_NSPrintForDebugger(id object)

View file

@ -583,6 +583,268 @@ static NSRecursiveLock *traceLock = nil;
#endif
#if !defined(HAVE_BUILTIN_EXTRACT_RETURN_ADDRESS)
# define __builtin_extract_return_address(X) X
#endif
#define _NS_FRAME_HACK(a) \
case a: env->addr = __builtin_frame_address(a + 1); break;
#define _NS_RETURN_HACK(a) \
case a: env->addr = (__builtin_frame_address(a + 1) ? \
__builtin_extract_return_address(__builtin_return_address(a + 1)) : 0); break;
/*
* The following horrible signal handling code is a workaround for the fact
* that the __builtin_frame_address() and __builtin_return_address()
* functions are not reliable (at least not on my EM64T based system) and
* will sometimes walk off the stack and access illegal memory locations.
* In order to prevent such an occurrance from crashing the application,
* we use sigsetjmp() and siglongjmp() to ensure that we can recover, and
* we keep the jump buffer in thread-local memory to avoid possible thread
* safety issues.
* Of course this will fail horribly if an exception occurs in one of the
* few methods we use to manage the per-thread jump buffer.
*/
#if defined(HAVE_SYS_SIGNAL_H)
# include <sys/signal.h>
#elif defined(HAVE_SIGNAL_H)
# include <signal.h>
#endif
#if defined(_WIN32)
#ifndef SIGBUS
#define SIGBUS SIGILL
#endif
#endif
/* sigsetjmp may be a function or a macro. The test for the function is
* done at configure time so we can tell here if either is available.
*/
#if !defined(HAVE_SIGSETJMP) && !defined(sigsetjmp)
#define siglongjmp(A,B) longjmp(A,B)
#define sigsetjmp(A,B) setjmp(A)
#define sigjmp_buf jmp_buf
#endif
typedef struct {
sigjmp_buf buf;
void *addr;
void (*bus)(int);
void (*segv)(int);
} jbuf_type;
static jbuf_type *
jbuf()
{
NSMutableData *d;
NSMutableDictionary *dict;
dict = [[NSThread currentThread] threadDictionary];
d = [dict objectForKey: @"GSjbuf"];
if (d == nil)
{
d = [[NSMutableData alloc] initWithLength: sizeof(jbuf_type)];
[dict setObject: d forKey: @"GSjbuf"];
RELEASE(d);
}
return (jbuf_type*)[d mutableBytes];
}
static void
recover(int sig)
{
siglongjmp(jbuf()->buf, 1);
}
void *
NSFrameAddress(NSUInteger offset)
{
jbuf_type *env;
env = jbuf();
if (sigsetjmp(env->buf, 1) == 0)
{
env->segv = signal(SIGSEGV, recover);
env->bus = signal(SIGBUS, recover);
switch (offset)
{
_NS_FRAME_HACK(0); _NS_FRAME_HACK(1); _NS_FRAME_HACK(2);
_NS_FRAME_HACK(3); _NS_FRAME_HACK(4); _NS_FRAME_HACK(5);
_NS_FRAME_HACK(6); _NS_FRAME_HACK(7); _NS_FRAME_HACK(8);
_NS_FRAME_HACK(9); _NS_FRAME_HACK(10); _NS_FRAME_HACK(11);
_NS_FRAME_HACK(12); _NS_FRAME_HACK(13); _NS_FRAME_HACK(14);
_NS_FRAME_HACK(15); _NS_FRAME_HACK(16); _NS_FRAME_HACK(17);
_NS_FRAME_HACK(18); _NS_FRAME_HACK(19); _NS_FRAME_HACK(20);
_NS_FRAME_HACK(21); _NS_FRAME_HACK(22); _NS_FRAME_HACK(23);
_NS_FRAME_HACK(24); _NS_FRAME_HACK(25); _NS_FRAME_HACK(26);
_NS_FRAME_HACK(27); _NS_FRAME_HACK(28); _NS_FRAME_HACK(29);
_NS_FRAME_HACK(30); _NS_FRAME_HACK(31); _NS_FRAME_HACK(32);
_NS_FRAME_HACK(33); _NS_FRAME_HACK(34); _NS_FRAME_HACK(35);
_NS_FRAME_HACK(36); _NS_FRAME_HACK(37); _NS_FRAME_HACK(38);
_NS_FRAME_HACK(39); _NS_FRAME_HACK(40); _NS_FRAME_HACK(41);
_NS_FRAME_HACK(42); _NS_FRAME_HACK(43); _NS_FRAME_HACK(44);
_NS_FRAME_HACK(45); _NS_FRAME_HACK(46); _NS_FRAME_HACK(47);
_NS_FRAME_HACK(48); _NS_FRAME_HACK(49); _NS_FRAME_HACK(50);
_NS_FRAME_HACK(51); _NS_FRAME_HACK(52); _NS_FRAME_HACK(53);
_NS_FRAME_HACK(54); _NS_FRAME_HACK(55); _NS_FRAME_HACK(56);
_NS_FRAME_HACK(57); _NS_FRAME_HACK(58); _NS_FRAME_HACK(59);
_NS_FRAME_HACK(60); _NS_FRAME_HACK(61); _NS_FRAME_HACK(62);
_NS_FRAME_HACK(63); _NS_FRAME_HACK(64); _NS_FRAME_HACK(65);
_NS_FRAME_HACK(66); _NS_FRAME_HACK(67); _NS_FRAME_HACK(68);
_NS_FRAME_HACK(69); _NS_FRAME_HACK(70); _NS_FRAME_HACK(71);
_NS_FRAME_HACK(72); _NS_FRAME_HACK(73); _NS_FRAME_HACK(74);
_NS_FRAME_HACK(75); _NS_FRAME_HACK(76); _NS_FRAME_HACK(77);
_NS_FRAME_HACK(78); _NS_FRAME_HACK(79); _NS_FRAME_HACK(80);
_NS_FRAME_HACK(81); _NS_FRAME_HACK(82); _NS_FRAME_HACK(83);
_NS_FRAME_HACK(84); _NS_FRAME_HACK(85); _NS_FRAME_HACK(86);
_NS_FRAME_HACK(87); _NS_FRAME_HACK(88); _NS_FRAME_HACK(89);
_NS_FRAME_HACK(90); _NS_FRAME_HACK(91); _NS_FRAME_HACK(92);
_NS_FRAME_HACK(93); _NS_FRAME_HACK(94); _NS_FRAME_HACK(95);
_NS_FRAME_HACK(96); _NS_FRAME_HACK(97); _NS_FRAME_HACK(98);
_NS_FRAME_HACK(99);
default: env->addr = NULL; break;
}
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
else
{
env = jbuf();
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
env->addr = NULL;
}
return env->addr;
}
NSUInteger NSCountFrames(void)
{
jbuf_type *env;
env = jbuf();
if (sigsetjmp(env->buf, 1) == 0)
{
env->segv = signal(SIGSEGV, recover);
env->bus = signal(SIGBUS, recover);
env->addr = 0;
#define _NS_COUNT_HACK(X) if (__builtin_frame_address(X + 1) == 0) \
goto done; else env->addr = (void*)(X + 1);
_NS_COUNT_HACK(0); _NS_COUNT_HACK(1); _NS_COUNT_HACK(2);
_NS_COUNT_HACK(3); _NS_COUNT_HACK(4); _NS_COUNT_HACK(5);
_NS_COUNT_HACK(6); _NS_COUNT_HACK(7); _NS_COUNT_HACK(8);
_NS_COUNT_HACK(9); _NS_COUNT_HACK(10); _NS_COUNT_HACK(11);
_NS_COUNT_HACK(12); _NS_COUNT_HACK(13); _NS_COUNT_HACK(14);
_NS_COUNT_HACK(15); _NS_COUNT_HACK(16); _NS_COUNT_HACK(17);
_NS_COUNT_HACK(18); _NS_COUNT_HACK(19); _NS_COUNT_HACK(20);
_NS_COUNT_HACK(21); _NS_COUNT_HACK(22); _NS_COUNT_HACK(23);
_NS_COUNT_HACK(24); _NS_COUNT_HACK(25); _NS_COUNT_HACK(26);
_NS_COUNT_HACK(27); _NS_COUNT_HACK(28); _NS_COUNT_HACK(29);
_NS_COUNT_HACK(30); _NS_COUNT_HACK(31); _NS_COUNT_HACK(32);
_NS_COUNT_HACK(33); _NS_COUNT_HACK(34); _NS_COUNT_HACK(35);
_NS_COUNT_HACK(36); _NS_COUNT_HACK(37); _NS_COUNT_HACK(38);
_NS_COUNT_HACK(39); _NS_COUNT_HACK(40); _NS_COUNT_HACK(41);
_NS_COUNT_HACK(42); _NS_COUNT_HACK(43); _NS_COUNT_HACK(44);
_NS_COUNT_HACK(45); _NS_COUNT_HACK(46); _NS_COUNT_HACK(47);
_NS_COUNT_HACK(48); _NS_COUNT_HACK(49); _NS_COUNT_HACK(50);
_NS_COUNT_HACK(51); _NS_COUNT_HACK(52); _NS_COUNT_HACK(53);
_NS_COUNT_HACK(54); _NS_COUNT_HACK(55); _NS_COUNT_HACK(56);
_NS_COUNT_HACK(57); _NS_COUNT_HACK(58); _NS_COUNT_HACK(59);
_NS_COUNT_HACK(60); _NS_COUNT_HACK(61); _NS_COUNT_HACK(62);
_NS_COUNT_HACK(63); _NS_COUNT_HACK(64); _NS_COUNT_HACK(65);
_NS_COUNT_HACK(66); _NS_COUNT_HACK(67); _NS_COUNT_HACK(68);
_NS_COUNT_HACK(69); _NS_COUNT_HACK(70); _NS_COUNT_HACK(71);
_NS_COUNT_HACK(72); _NS_COUNT_HACK(73); _NS_COUNT_HACK(74);
_NS_COUNT_HACK(75); _NS_COUNT_HACK(76); _NS_COUNT_HACK(77);
_NS_COUNT_HACK(78); _NS_COUNT_HACK(79); _NS_COUNT_HACK(80);
_NS_COUNT_HACK(81); _NS_COUNT_HACK(82); _NS_COUNT_HACK(83);
_NS_COUNT_HACK(84); _NS_COUNT_HACK(85); _NS_COUNT_HACK(86);
_NS_COUNT_HACK(87); _NS_COUNT_HACK(88); _NS_COUNT_HACK(89);
_NS_COUNT_HACK(90); _NS_COUNT_HACK(91); _NS_COUNT_HACK(92);
_NS_COUNT_HACK(93); _NS_COUNT_HACK(94); _NS_COUNT_HACK(95);
_NS_COUNT_HACK(96); _NS_COUNT_HACK(97); _NS_COUNT_HACK(98);
_NS_COUNT_HACK(99);
done:
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
else
{
env = jbuf();
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
return (uintptr_t)env->addr;
}
void *
NSReturnAddress(NSUInteger offset)
{
jbuf_type *env;
env = jbuf();
if (sigsetjmp(env->buf, 1) == 0)
{
env->segv = signal(SIGSEGV, recover);
env->bus = signal(SIGBUS, recover);
switch (offset)
{
_NS_RETURN_HACK(0); _NS_RETURN_HACK(1); _NS_RETURN_HACK(2);
_NS_RETURN_HACK(3); _NS_RETURN_HACK(4); _NS_RETURN_HACK(5);
_NS_RETURN_HACK(6); _NS_RETURN_HACK(7); _NS_RETURN_HACK(8);
_NS_RETURN_HACK(9); _NS_RETURN_HACK(10); _NS_RETURN_HACK(11);
_NS_RETURN_HACK(12); _NS_RETURN_HACK(13); _NS_RETURN_HACK(14);
_NS_RETURN_HACK(15); _NS_RETURN_HACK(16); _NS_RETURN_HACK(17);
_NS_RETURN_HACK(18); _NS_RETURN_HACK(19); _NS_RETURN_HACK(20);
_NS_RETURN_HACK(21); _NS_RETURN_HACK(22); _NS_RETURN_HACK(23);
_NS_RETURN_HACK(24); _NS_RETURN_HACK(25); _NS_RETURN_HACK(26);
_NS_RETURN_HACK(27); _NS_RETURN_HACK(28); _NS_RETURN_HACK(29);
_NS_RETURN_HACK(30); _NS_RETURN_HACK(31); _NS_RETURN_HACK(32);
_NS_RETURN_HACK(33); _NS_RETURN_HACK(34); _NS_RETURN_HACK(35);
_NS_RETURN_HACK(36); _NS_RETURN_HACK(37); _NS_RETURN_HACK(38);
_NS_RETURN_HACK(39); _NS_RETURN_HACK(40); _NS_RETURN_HACK(41);
_NS_RETURN_HACK(42); _NS_RETURN_HACK(43); _NS_RETURN_HACK(44);
_NS_RETURN_HACK(45); _NS_RETURN_HACK(46); _NS_RETURN_HACK(47);
_NS_RETURN_HACK(48); _NS_RETURN_HACK(49); _NS_RETURN_HACK(50);
_NS_RETURN_HACK(51); _NS_RETURN_HACK(52); _NS_RETURN_HACK(53);
_NS_RETURN_HACK(54); _NS_RETURN_HACK(55); _NS_RETURN_HACK(56);
_NS_RETURN_HACK(57); _NS_RETURN_HACK(58); _NS_RETURN_HACK(59);
_NS_RETURN_HACK(60); _NS_RETURN_HACK(61); _NS_RETURN_HACK(62);
_NS_RETURN_HACK(63); _NS_RETURN_HACK(64); _NS_RETURN_HACK(65);
_NS_RETURN_HACK(66); _NS_RETURN_HACK(67); _NS_RETURN_HACK(68);
_NS_RETURN_HACK(69); _NS_RETURN_HACK(70); _NS_RETURN_HACK(71);
_NS_RETURN_HACK(72); _NS_RETURN_HACK(73); _NS_RETURN_HACK(74);
_NS_RETURN_HACK(75); _NS_RETURN_HACK(76); _NS_RETURN_HACK(77);
_NS_RETURN_HACK(78); _NS_RETURN_HACK(79); _NS_RETURN_HACK(80);
_NS_RETURN_HACK(81); _NS_RETURN_HACK(82); _NS_RETURN_HACK(83);
_NS_RETURN_HACK(84); _NS_RETURN_HACK(85); _NS_RETURN_HACK(86);
_NS_RETURN_HACK(87); _NS_RETURN_HACK(88); _NS_RETURN_HACK(89);
_NS_RETURN_HACK(90); _NS_RETURN_HACK(91); _NS_RETURN_HACK(92);
_NS_RETURN_HACK(93); _NS_RETURN_HACK(94); _NS_RETURN_HACK(95);
_NS_RETURN_HACK(96); _NS_RETURN_HACK(97); _NS_RETURN_HACK(98);
_NS_RETURN_HACK(99);
default: env->addr = NULL; break;
}
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
}
else
{
env = jbuf();
signal(SIGSEGV, env->segv);
signal(SIGBUS, env->bus);
env->addr = NULL;
}
return env->addr;
}
@implementation GSStackTrace : NSObject
/** Offset from the top of the stack (when we generate a trace) to the

View file

@ -825,9 +825,10 @@ unregisterActiveThread(NSThread *thread)
+ (NSArray*) callStackReturnAddresses
{
NSMutableArray *stack = GSPrivateStackAddresses();
return stack;
GSStackTrace *stack = [GSStackTrace new];
NSArray *addrs = RETAIN([stack addresses]);
RELEASE(stack);
return AUTORELEASE(addrs);
}
+ (BOOL) _createThreadForCurrentPthread