@@ -15,13 +15,20 @@ */ #include "config.h" #include + +#ifdef HAVE_EXECINFO_H +# include +#endif #import "OFException.h" #import "OFString.h" +#import "OFArray.h" + +#import "autorelease.h" @implementation OFException + (instancetype)exceptionWithClass: (Class)class { return [[[self alloc] initWithClass: class] autorelease]; @@ -42,13 +49,24 @@ - initWithClass: (Class)class { self = [super init]; _inClass = class; +#ifdef HAVE_EXECINFO_H + _backtraceSize = backtrace(_backtraceBuffer, + OF_EXCEPTION_MAX_BACKTRACE_SIZE); +#endif return self; } + +- (void)dealloc +{ + [_backtrace release]; + + [super dealloc]; +} - (Class)inClass { return _inClass; } @@ -57,6 +75,46 @@ { return [OFString stringWithFormat: @"An exception of class %@ occurred in class %@!", object_getClass(self), _inClass]; } + +- (OFArray*)backtrace +{ +#ifdef HAVE_EXECINFO_H + char **symbols; + + if (_backtrace != nil) + return _backtrace; + + if (_backtraceSize < 1) + return nil; + + symbols = backtrace_symbols(_backtraceBuffer, _backtraceSize); + @try { + int i; + + _backtrace = [[OFMutableArray alloc] init]; + + for (i = 0; i < _backtraceSize; i++) { + void *pool = objc_autoreleasePoolPush(); + OFString *symbol; + + symbol = [OFString + stringWithCString: symbols[i] + encoding: OF_STRING_ENCODING_NATIVE]; + [_backtrace addObject: symbol]; + + objc_autoreleasePoolPop(pool); + } + } @finally { + free(symbols); + } + + [_backtrace makeImmutable]; + + return _backtrace; +#else + return nil; +#endif +} @end