mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
Stack trace fixups.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@24461 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
ec28efef0b
commit
f9f9d76604
4 changed files with 269 additions and 142 deletions
|
@ -4,6 +4,10 @@
|
||||||
* Headers/Foundation/NSComparisonPredicate.h:
|
* Headers/Foundation/NSComparisonPredicate.h:
|
||||||
* Headers/Foundation/NSExpression.h:
|
* Headers/Foundation/NSExpression.h:
|
||||||
Fixup version macros
|
Fixup version macros
|
||||||
|
* Source/NSDebug.m: Make frame functions safe.
|
||||||
|
* Source/NSException.m: Use non-symbolic stack trace if symbols
|
||||||
|
are not available.
|
||||||
|
* Source/NSIndexSet.m: Add private method for minternal use.
|
||||||
|
|
||||||
2007-01-30 Richard Frith-Macdonald <rfm@gnu.org>
|
2007-01-30 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
|
244
Source/NSDebug.m
244
Source/NSDebug.m
|
@ -854,53 +854,6 @@ GSDebugMethodMsg(id obj, SEL sel, const char *file, int line, NSString *fmt)
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static void *_frameOffsets[100];
|
|
||||||
|
|
||||||
#define _NS_FRAME_HACK(a) case a: return __builtin_frame_address(a + 1)
|
|
||||||
#define _NS_RETURN_HACK(a) case a: return __builtin_return_address(a + 1)
|
|
||||||
|
|
||||||
void *NSFrameAddress(int offset)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned NSCountFrames(void)
|
unsigned NSCountFrames(void)
|
||||||
{
|
{
|
||||||
unsigned x = 0;
|
unsigned x = 0;
|
||||||
|
@ -910,48 +863,167 @@ unsigned NSCountFrames(void)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *NSReturnAddress(int offset)
|
#define _NS_FRAME_HACK(a) case a: val = __builtin_frame_address(a + 1); break;
|
||||||
{
|
#define _NS_RETURN_HACK(a) case a: val = __builtin_return_address(a + 1); break;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
static sigjmp_buf *
|
||||||
|
jbuf()
|
||||||
|
{
|
||||||
|
NSMutableData *d;
|
||||||
|
|
||||||
|
d = [[[NSThread currentThread] threadDictionary] objectForKey: @"GSjbuf"];
|
||||||
|
if (d == nil)
|
||||||
|
{
|
||||||
|
d = [[NSMutableData alloc] initWithLength: sizeof(sigjmp_buf)];
|
||||||
|
[[[NSThread currentThread] threadDictionary] setObject: d
|
||||||
|
forKey: @"GSjbuf"];
|
||||||
|
RELEASE(d);
|
||||||
|
}
|
||||||
|
return (sigjmp_buf*)[d mutableBytes];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
recover(int sig)
|
||||||
|
{
|
||||||
|
sigjmp_buf *env = jbuf();
|
||||||
|
|
||||||
|
siglongjmp(*env, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
NSFrameAddress(int offset)
|
||||||
|
{
|
||||||
|
sigjmp_buf *env;
|
||||||
|
void *val;
|
||||||
|
|
||||||
|
env = jbuf();
|
||||||
|
if (sigsetjmp(*env, 1) == 0)
|
||||||
|
{
|
||||||
|
void (*old)(int);
|
||||||
|
|
||||||
|
old = signal(SIGSEGV, 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: val = NULL; break;
|
||||||
|
}
|
||||||
|
signal(SIGSEGV, old);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = NULL;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
NSReturnAddress(int offset)
|
||||||
|
{
|
||||||
|
sigjmp_buf *env;
|
||||||
|
void *val;
|
||||||
|
|
||||||
|
env = jbuf();
|
||||||
|
if (sigsetjmp(*env, 1) == 0)
|
||||||
|
{
|
||||||
|
void (*old)(int);
|
||||||
|
|
||||||
|
old = signal(SIGSEGV, 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: val = NULL; break;
|
||||||
|
}
|
||||||
|
signal(SIGSEGV, old);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *_NSPrintForDebugger(id object)
|
const char *_NSPrintForDebugger(id object)
|
||||||
{
|
{
|
||||||
if (object && [object respondsToSelector: @selector(description)])
|
if (object && [object respondsToSelector: @selector(description)])
|
||||||
|
|
|
@ -37,26 +37,43 @@
|
||||||
#include "Foundation/NSDictionary.h"
|
#include "Foundation/NSDictionary.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
@interface GSStackTrace : NSObject
|
||||||
|
{
|
||||||
|
NSMutableArray *frames;
|
||||||
|
}
|
||||||
|
+ (GSStackTrace*) currentStack;
|
||||||
|
|
||||||
|
- (NSString*) description;
|
||||||
|
- (NSEnumerator*) enumerator;
|
||||||
|
- (id) frameAt: (unsigned)index;
|
||||||
|
- (unsigned) frameCount;
|
||||||
|
- (NSEnumerator*) reverseEnumerator;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#define STACKSYMBOLS 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn off STACKTRACE if we don't have bfd support for it.
|
* Turn off STACKSYMBOLS if we don't have bfd support for it.
|
||||||
*/
|
*/
|
||||||
#if !(defined(HAVE_BFD_H) && defined(HAVE_LIBBFD) && defined(HAVE_LIBIBERTY))
|
#if !(defined(HAVE_BFD_H) && defined(HAVE_LIBBFD) && defined(HAVE_LIBIBERTY))
|
||||||
#if defined(STACKTRACE)
|
#if defined(STACKSYMBOLS)
|
||||||
#undef STACKTRACE
|
#undef STACKSYMBOLS
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn off STACKTRACE if we don't have DEBUG defined ... if we are not built
|
* Turn off STACKSYMBOLS if we don't have DEBUG defined ... if we are not built
|
||||||
* with DEBUG then we are probably missing stackframe information etc.
|
* with DEBUG then we are probably missing stackframe information etc.
|
||||||
*/
|
*/
|
||||||
#if !(defined(DEBUG))
|
#if !(defined(DEBUG))
|
||||||
#if defined(STACKTRACE)
|
#if defined(STACKSYMBOLS)
|
||||||
#undef STACKTRACE
|
#undef STACKSYMBOLS
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(STACKTRACE)
|
#if defined(STACKSYMBOLS)
|
||||||
|
|
||||||
// GSStackTrace inspired by FYStackTrace.m
|
// GSStackTrace inspired by FYStackTrace.m
|
||||||
// created by Wim Oudshoorn on Mon 11-Apr-2006
|
// created by Wim Oudshoorn on Mon 11-Apr-2006
|
||||||
|
@ -102,28 +119,6 @@
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@interface GSStackTrace : NSObject
|
|
||||||
{
|
|
||||||
NSMutableArray *frames;
|
|
||||||
}
|
|
||||||
+ (GSStackTrace*) currentStack;
|
|
||||||
/*
|
|
||||||
* Add some module information to the stack trace information
|
|
||||||
* only symbols from the current process's file, GNUstep base library,
|
|
||||||
* GNUstep gui library, and any bundles containing code are loaded.
|
|
||||||
* All other symbols should be manually added
|
|
||||||
*/
|
|
||||||
+ (BOOL) loadModule: (NSString *)filename;
|
|
||||||
|
|
||||||
- (NSString*) description;
|
|
||||||
- (NSEnumerator*) enumerator;
|
|
||||||
- (GSFunctionInfo*) frameAt: (unsigned)index;
|
|
||||||
- (unsigned) frameCount;
|
|
||||||
- (NSEnumerator*) reverseEnumerator;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@implementation GSFunctionInfo
|
@implementation GSFunctionInfo
|
||||||
|
@ -373,8 +368,11 @@ static void find_address (bfd *abfd, asection *section,
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
static BOOL LoadModule(NSString *filename);
|
||||||
|
|
||||||
// this method automatically load the current process + GNUstep base & gui.
|
// this method automatically load the current process + GNUstep base & gui.
|
||||||
static NSMutableDictionary *GetStackModules()
|
static NSMutableDictionary *
|
||||||
|
GetStackModules()
|
||||||
{
|
{
|
||||||
static NSMutableDictionary *stackModules = nil;
|
static NSMutableDictionary *stackModules = nil;
|
||||||
|
|
||||||
|
@ -400,29 +398,16 @@ static NSMutableDictionary *GetStackModules()
|
||||||
{
|
{
|
||||||
if ([bundle load] == YES)
|
if ([bundle load] == YES)
|
||||||
{
|
{
|
||||||
[GSStackTrace loadModule: [bundle executablePath]];
|
LoadModule([bundle executablePath]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stackModules;
|
return stackModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation GSStackTrace : NSObject
|
|
||||||
|
|
||||||
static NSNull *null = nil;
|
|
||||||
|
|
||||||
+ (GSStackTrace*) currentStack
|
|
||||||
{
|
|
||||||
return [[[GSStackTrace alloc] init] autorelease];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void) initialize
|
|
||||||
{
|
|
||||||
null = RETAIN([NSNull null]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize stack trace info
|
// initialize stack trace info
|
||||||
+ (BOOL) loadModule: (NSString *)filename
|
static BOOL
|
||||||
|
LoadModule(NSString *filename)
|
||||||
{
|
{
|
||||||
if ([filename length] > 0)
|
if ([filename length] > 0)
|
||||||
{
|
{
|
||||||
|
@ -439,10 +424,10 @@ static NSNull *null = nil;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[modules setObject: null forKey: filename];
|
[modules setObject: [NSNull null] forKey: filename];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ([modules objectForKey: filename] != null)
|
if ([modules objectForKey: filename] != [NSNull null])
|
||||||
{
|
{
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
@ -450,6 +435,16 @@ static NSNull *null = nil;
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* STACKSYMBOLS */
|
||||||
|
|
||||||
|
|
||||||
|
@implementation GSStackTrace : NSObject
|
||||||
|
|
||||||
|
+ (GSStackTrace*) currentStack
|
||||||
|
{
|
||||||
|
return [[[GSStackTrace alloc] init] autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
- (oneway void) dealloc
|
- (oneway void) dealloc
|
||||||
{
|
{
|
||||||
[frames release];
|
[frames release];
|
||||||
|
@ -467,7 +462,7 @@ static NSNull *null = nil;
|
||||||
n = [frames count];
|
n = [frames count];
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
GSFunctionInfo *line = [frames objectAtIndex: i];
|
id line = [frames objectAtIndex: i];
|
||||||
|
|
||||||
[result appendFormat: @"%3d: %@\n", i, line];
|
[result appendFormat: @"%3d: %@\n", i, line];
|
||||||
}
|
}
|
||||||
|
@ -479,7 +474,7 @@ static NSNull *null = nil;
|
||||||
return [frames objectEnumerator];
|
return [frames objectEnumerator];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (GSFunctionInfo*) frameAt: (unsigned)index
|
- (id) frameAt: (unsigned)index
|
||||||
{
|
{
|
||||||
return [frames objectAtIndex: index];
|
return [frames objectAtIndex: index];
|
||||||
}
|
}
|
||||||
|
@ -490,10 +485,9 @@ static NSNull *null = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab the current stack
|
// grab the current stack
|
||||||
// this MAX_FRAME comes from NSDebug.h which warn only 100 frames are available
|
|
||||||
#define MAX_FRAME 100
|
|
||||||
- (id) init
|
- (id) init
|
||||||
{
|
{
|
||||||
|
#if defined(STACKSYMBOLS)
|
||||||
NSArray *modules;
|
NSArray *modules;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
@ -505,7 +499,7 @@ static NSNull *null = nil;
|
||||||
n = NSCountFrames();
|
n = NSCountFrames();
|
||||||
m = [modules count];
|
m = [modules count];
|
||||||
|
|
||||||
for (i = 0; i < n && i < MAX_FRAME; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
GSFunctionInfo *aFrame = nil;
|
GSFunctionInfo *aFrame = nil;
|
||||||
void *address = NSReturnAddress(i);
|
void *address = NSReturnAddress(i);
|
||||||
|
@ -514,7 +508,7 @@ static NSNull *null = nil;
|
||||||
{
|
{
|
||||||
GSBinaryFileInfo *bfi = [modules objectAtIndex: j];
|
GSBinaryFileInfo *bfi = [modules objectAtIndex: j];
|
||||||
|
|
||||||
if ((id)bfi != (id)null)
|
if ((id)bfi != (id)[NSNull null])
|
||||||
{
|
{
|
||||||
aFrame = [bfi functionForAddress: address];
|
aFrame = [bfi functionForAddress: address];
|
||||||
if (aFrame)
|
if (aFrame)
|
||||||
|
@ -537,6 +531,20 @@ static NSNull *null = nil;
|
||||||
[frames addObject: aFrame];
|
[frames addObject: aFrame];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
int i;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
frames = [[NSMutableArray alloc] init];
|
||||||
|
n = NSCountFrames();
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
void *address = NSReturnAddress(i);
|
||||||
|
|
||||||
|
[frames addObject: [NSString stringWithFormat: @"%p", address]];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -548,7 +556,6 @@ static NSNull *null = nil;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* STACKTRACE */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -599,10 +606,18 @@ static void _terminate()
|
||||||
static void
|
static void
|
||||||
_NSFoundationUncaughtExceptionHandler (NSException *exception)
|
_NSFoundationUncaughtExceptionHandler (NSException *exception)
|
||||||
{
|
{
|
||||||
|
NSString *stack;
|
||||||
|
|
||||||
fprintf(stderr, "%s: Uncaught exception %s, reason: %s\n",
|
fprintf(stderr, "%s: Uncaught exception %s, reason: %s\n",
|
||||||
GSPrivateArgZero(),
|
GSPrivateArgZero(),
|
||||||
[[exception name] lossyCString], [[exception reason] lossyCString]);
|
[[exception name] lossyCString], [[exception reason] lossyCString]);
|
||||||
fflush(stderr); /* NEEDED UNDER MINGW */
|
fflush(stderr); /* NEEDED UNDER MINGW */
|
||||||
|
stack = [[[exception userInfo] objectForKey: @"GSStackTraceKey"] description];
|
||||||
|
if (stack != nil)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Stack\n%s\n", [stack lossyCString]);
|
||||||
|
}
|
||||||
|
fflush(stderr); /* NEEDED UNDER MINGW */
|
||||||
|
|
||||||
_terminate();
|
_terminate();
|
||||||
}
|
}
|
||||||
|
@ -665,7 +680,7 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
|
||||||
NSHandler *handler;
|
NSHandler *handler;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(STACKTRACE)
|
#if defined(DEBUG)
|
||||||
if ([_e_info objectForKey: @"GSStackTraceKey"] == nil)
|
if ([_e_info objectForKey: @"GSStackTraceKey"] == nil)
|
||||||
{
|
{
|
||||||
NSMutableDictionary *m;
|
NSMutableDictionary *m;
|
||||||
|
|
|
@ -980,3 +980,39 @@ static unsigned posForIndex(GSIArray array, unsigned index)
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation NSIndexSet (NSCharacterSet)
|
||||||
|
/* Extra method to let NSCharacterSet play with index sets more efficiently.
|
||||||
|
*/
|
||||||
|
- (unsigned int) _gapGreaterThanIndex: (unsigned int)anIndex
|
||||||
|
{
|
||||||
|
unsigned pos;
|
||||||
|
NSRange r;
|
||||||
|
|
||||||
|
if (anIndex++ == NSNotFound)
|
||||||
|
{
|
||||||
|
return NSNotFound;
|
||||||
|
}
|
||||||
|
if (_array == 0 || GSIArrayCount(_array) == 0)
|
||||||
|
{
|
||||||
|
return NSNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pos = posForIndex(_array, anIndex)) >= GSIArrayCount(_array))
|
||||||
|
{
|
||||||
|
r = GSIArrayItemAtIndex(_array, pos-1).ext;
|
||||||
|
if (anIndex > NSMaxRange(r))
|
||||||
|
{
|
||||||
|
return NSNotFound;
|
||||||
|
}
|
||||||
|
return anIndex; // anIndex is the gap after the last index.
|
||||||
|
}
|
||||||
|
r = GSIArrayItemAtIndex(_array, pos).ext;
|
||||||
|
if (r.location > anIndex)
|
||||||
|
{
|
||||||
|
return anIndex; // anIndex is in a gap between index ranges.
|
||||||
|
}
|
||||||
|
return NSMaxRange(r); // Return start of gap after the index range.
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue