mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 08:41:03 +00:00
hould be fix for bug #22514
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@26315 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
68e50feb65
commit
22436d0c17
2 changed files with 65 additions and 79 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2008-03-16 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/NSDebug.m: Trap sigbus if gcc functions to get stack frame
|
||||||
|
info run off the end of the stack.
|
||||||
|
|
||||||
2008-03-16 Richard Frith-Macdonald <rfm@gnu.org>
|
2008-03-16 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/NSArray.m:
|
* Source/NSArray.m:
|
||||||
|
|
139
Source/NSDebug.m
139
Source/NSDebug.m
|
@ -856,8 +856,10 @@ GSDebugMethodMsg(id obj, SEL sel, const char *file, int line, NSString *fmt)
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _NS_FRAME_HACK(a) case a: val = __builtin_frame_address(a + 1); break;
|
#define _NS_FRAME_HACK(a) \
|
||||||
#define _NS_RETURN_HACK(a) case a: val = __builtin_return_address(a + 1); break;
|
case a: env->addr = __builtin_frame_address(a + 1); break;
|
||||||
|
#define _NS_RETURN_HACK(a) \
|
||||||
|
case a: env->addr = __builtin_return_address(a + 1); break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following horrible signal handling code is a workaround for the fact
|
* The following horrible signal handling code is a workaround for the fact
|
||||||
|
@ -877,7 +879,14 @@ GSDebugMethodMsg(id obj, SEL sel, const char *file, int line, NSString *fmt)
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static jmp_buf *
|
typedef struct {
|
||||||
|
jmp_buf buf;
|
||||||
|
void *addr;
|
||||||
|
void (*bus)(int);
|
||||||
|
void (*segv)(int);
|
||||||
|
} jbuf_type;
|
||||||
|
|
||||||
|
static jbuf_type *
|
||||||
jbuf()
|
jbuf()
|
||||||
{
|
{
|
||||||
NSMutableData *d;
|
NSMutableData *d;
|
||||||
|
@ -885,37 +894,30 @@ jbuf()
|
||||||
d = [[[NSThread currentThread] threadDictionary] objectForKey: @"GSjbuf"];
|
d = [[[NSThread currentThread] threadDictionary] objectForKey: @"GSjbuf"];
|
||||||
if (d == nil)
|
if (d == nil)
|
||||||
{
|
{
|
||||||
d = [[NSMutableData alloc] initWithLength:
|
d = [[NSMutableData alloc] initWithLength: sizeof(jbuf_type)];
|
||||||
sizeof(jmp_buf) + sizeof(void(*)(int)) + sizeof(void*)];
|
|
||||||
[[[NSThread currentThread] threadDictionary] setObject: d
|
[[[NSThread currentThread] threadDictionary] setObject: d
|
||||||
forKey: @"GSjbuf"];
|
forKey: @"GSjbuf"];
|
||||||
RELEASE(d);
|
RELEASE(d);
|
||||||
}
|
}
|
||||||
return (jmp_buf*)[d mutableBytes];
|
return (jbuf_type*)[d mutableBytes];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recover(int sig)
|
recover(int sig)
|
||||||
{
|
{
|
||||||
jmp_buf *env = jbuf();
|
longjmp(jbuf()->buf, 1);
|
||||||
|
|
||||||
longjmp(*env, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
NSFrameAddress(int offset)
|
NSFrameAddress(int offset)
|
||||||
{
|
{
|
||||||
jmp_buf *env;
|
jbuf_type *env;
|
||||||
void (*old)(int);
|
|
||||||
void *val;
|
|
||||||
|
|
||||||
env = jbuf();
|
env = jbuf();
|
||||||
if (setjmp(*env) == 0)
|
if (setjmp(env->buf) == 0)
|
||||||
{
|
{
|
||||||
old = signal(SIGSEGV, recover);
|
env->segv = signal(SIGSEGV, recover);
|
||||||
val = (void*)env;
|
env->bus = signal(SIGBUS, recover);
|
||||||
val += sizeof(jmp_buf);
|
|
||||||
memcpy(val, &old, sizeof(old));
|
|
||||||
switch (offset)
|
switch (offset)
|
||||||
{
|
{
|
||||||
_NS_FRAME_HACK(0); _NS_FRAME_HACK(1); _NS_FRAME_HACK(2);
|
_NS_FRAME_HACK(0); _NS_FRAME_HACK(1); _NS_FRAME_HACK(2);
|
||||||
|
@ -952,42 +954,33 @@ NSFrameAddress(int offset)
|
||||||
_NS_FRAME_HACK(93); _NS_FRAME_HACK(94); _NS_FRAME_HACK(95);
|
_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(96); _NS_FRAME_HACK(97); _NS_FRAME_HACK(98);
|
||||||
_NS_FRAME_HACK(99);
|
_NS_FRAME_HACK(99);
|
||||||
default: val = NULL; break;
|
default: env->addr = NULL; break;
|
||||||
}
|
}
|
||||||
signal(SIGSEGV, old);
|
signal(SIGSEGV, env->segv);
|
||||||
|
signal(SIGBUS, env->bus);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = jbuf();
|
signal(SIGSEGV, env->segv);
|
||||||
val += sizeof(jmp_buf);
|
signal(SIGBUS, env->bus);
|
||||||
memcpy(&old, val, sizeof(old));
|
env->addr = NULL;
|
||||||
signal(SIGSEGV, old);
|
|
||||||
val = NULL;
|
|
||||||
}
|
}
|
||||||
return val;
|
return env->addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NSCountFrames(void)
|
unsigned NSCountFrames(void)
|
||||||
{
|
{
|
||||||
jmp_buf *env;
|
jbuf_type *env;
|
||||||
void (*old)(int);
|
|
||||||
void *val;
|
|
||||||
|
|
||||||
env = jbuf();
|
env = jbuf();
|
||||||
if (setjmp(*env) == 0)
|
if (setjmp(env->buf) == 0)
|
||||||
{
|
{
|
||||||
unsigned *loc;
|
env->segv = signal(SIGSEGV, recover);
|
||||||
|
env->bus = signal(SIGBUS, recover);
|
||||||
old = signal(SIGSEGV, recover);
|
env->addr = 0;
|
||||||
val = (void*)env;
|
|
||||||
val += sizeof(jmp_buf);
|
|
||||||
memcpy(val, &old, sizeof(old));
|
|
||||||
val += sizeof(old);
|
|
||||||
loc = (unsigned*)val;
|
|
||||||
*loc = 0;
|
|
||||||
|
|
||||||
#define _NS_COUNT_HACK(X) if (__builtin_frame_address(X + 1) == 0) \
|
#define _NS_COUNT_HACK(X) if (__builtin_frame_address(X + 1) == 0) \
|
||||||
goto done; else *loc = X + 1;
|
goto done; else env->addr = (void*)(X + 1);
|
||||||
|
|
||||||
_NS_COUNT_HACK(0); _NS_COUNT_HACK(1); _NS_COUNT_HACK(2);
|
_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(3); _NS_COUNT_HACK(4); _NS_COUNT_HACK(5);
|
||||||
|
@ -1025,35 +1018,29 @@ unsigned NSCountFrames(void)
|
||||||
_NS_COUNT_HACK(99);
|
_NS_COUNT_HACK(99);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
signal(SIGSEGV, old);
|
signal(SIGSEGV, env->segv);
|
||||||
|
signal(SIGBUS, env->bus);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
env = jbuf();
|
env = jbuf();
|
||||||
val = (void*)env;
|
signal(SIGSEGV, env->segv);
|
||||||
val += sizeof(jmp_buf);
|
signal(SIGBUS, env->bus);
|
||||||
memcpy(&old, val, sizeof(old));
|
|
||||||
signal(SIGSEGV, old);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val = (void*)env + sizeof(jmp_buf) + sizeof(old);
|
return (unsigned)(uintptr_t)env->addr;
|
||||||
return *(unsigned*)val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
NSReturnAddress(int offset)
|
NSReturnAddress(int offset)
|
||||||
{
|
{
|
||||||
jmp_buf *env;
|
jbuf_type *env;
|
||||||
void (*old)(int);
|
|
||||||
void *val;
|
|
||||||
|
|
||||||
env = jbuf();
|
env = jbuf();
|
||||||
if (setjmp(*env) == 0)
|
if (setjmp(env->buf) == 0)
|
||||||
{
|
{
|
||||||
old = signal(SIGSEGV, recover);
|
env->segv = signal(SIGSEGV, recover);
|
||||||
val = (void*)env;
|
env->bus = signal(SIGBUS, recover);
|
||||||
val += sizeof(jmp_buf);
|
|
||||||
memcpy(val, &old, sizeof(old));
|
|
||||||
switch (offset)
|
switch (offset)
|
||||||
{
|
{
|
||||||
_NS_RETURN_HACK(0); _NS_RETURN_HACK(1); _NS_RETURN_HACK(2);
|
_NS_RETURN_HACK(0); _NS_RETURN_HACK(1); _NS_RETURN_HACK(2);
|
||||||
|
@ -1090,20 +1077,20 @@ NSReturnAddress(int offset)
|
||||||
_NS_RETURN_HACK(93); _NS_RETURN_HACK(94); _NS_RETURN_HACK(95);
|
_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(96); _NS_RETURN_HACK(97); _NS_RETURN_HACK(98);
|
||||||
_NS_RETURN_HACK(99);
|
_NS_RETURN_HACK(99);
|
||||||
default: val = NULL; break;
|
default: env->addr = NULL; break;
|
||||||
}
|
}
|
||||||
signal(SIGSEGV, old);
|
signal(SIGSEGV, env->segv);
|
||||||
|
signal(SIGBUS, env->bus);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = jbuf();
|
env = jbuf();
|
||||||
val += sizeof(jmp_buf);
|
signal(SIGSEGV, env->segv);
|
||||||
memcpy(&old, val, sizeof(old));
|
signal(SIGBUS, env->bus);
|
||||||
signal(SIGSEGV, old);
|
env->addr = NULL;
|
||||||
val = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return env->addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray *
|
NSMutableArray *
|
||||||
|
@ -1113,9 +1100,7 @@ GSPrivateStackAddresses(void)
|
||||||
NSMutableArray *stack = [NSMutableArray arrayWithCapacity: n];
|
NSMutableArray *stack = [NSMutableArray arrayWithCapacity: n];
|
||||||
CREATE_AUTORELEASE_POOL(pool);
|
CREATE_AUTORELEASE_POOL(pool);
|
||||||
unsigned i;
|
unsigned i;
|
||||||
jmp_buf *env;
|
jbuf_type *env;
|
||||||
void (*old)(int);
|
|
||||||
void *val;
|
|
||||||
|
|
||||||
/* There should be more frame addresses than return addresses.
|
/* There should be more frame addresses than return addresses.
|
||||||
*/
|
*/
|
||||||
|
@ -1129,12 +1114,10 @@ GSPrivateStackAddresses(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
env = jbuf();
|
env = jbuf();
|
||||||
if (setjmp(*env) == 0)
|
if (setjmp(env->buf) == 0)
|
||||||
{
|
{
|
||||||
old = signal(SIGSEGV, recover);
|
env->segv = signal(SIGSEGV, recover);
|
||||||
val = (void*)env;
|
env->bus = signal(SIGBUS, recover);
|
||||||
val += sizeof(jmp_buf);
|
|
||||||
memcpy(val, &old, sizeof(old));
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
|
@ -1174,23 +1157,21 @@ GSPrivateStackAddresses(void)
|
||||||
_NS_RETURN_HACK(93); _NS_RETURN_HACK(94); _NS_RETURN_HACK(95);
|
_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(96); _NS_RETURN_HACK(97); _NS_RETURN_HACK(98);
|
||||||
_NS_RETURN_HACK(99);
|
_NS_RETURN_HACK(99);
|
||||||
default: val = 0; break;
|
default: env->addr = 0; break;
|
||||||
}
|
}
|
||||||
if (val == 0)
|
if (env->addr == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
[stack addObject: [NSValue valueWithPointer: val]];
|
[stack addObject: [NSValue valueWithPointer: env->addr]];
|
||||||
}
|
}
|
||||||
signal(SIGSEGV, old);
|
signal(SIGSEGV, env->segv);
|
||||||
|
signal(SIGBUS, env->bus);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
env = jbuf();
|
signal(SIGSEGV, env->segv);
|
||||||
val = (void*)env;
|
signal(SIGBUS, env->bus);
|
||||||
val += sizeof(jmp_buf);
|
|
||||||
memcpy(&old, val, sizeof(old));
|
|
||||||
signal(SIGSEGV, old);
|
|
||||||
}
|
}
|
||||||
RELEASE(pool);
|
RELEASE(pool);
|
||||||
return stack;
|
return stack;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue