Skip to content

Instantly share code, notes, and snippets.

@jpmhouston
Created February 7, 2014 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpmhouston/8873003 to your computer and use it in GitHub Desktop.
Save jpmhouston/8873003 to your computer and use it in GitHub Desktop.
Backtrace category on NSObject
@interface NSObject (Backtrace)
+ (NSString *)appBacktraceOfDepth:(int)depth fromStackSymbols:(NSArray *)frames;
+ (NSString *)backtraceOfDepth:(int)depth fromStackSymbols:(NSArray *)frames;
+ (NSString *)backtraceOfDepth:(int)depth fromStackSymbols:(NSArray *)frames matching:(NSString *)from;
@end
#define BACKTRACE_DEPTH(DEPTH) ([[NSThread class] respondsToSelector:@selector(callStackSymbols)] ? [NSObject appBacktraceOfDepth:DEPTH fromStackSymbols:[NSThread callStackSymbols]] : @"")
#define CALLSTACK_DEPTH(DEPTH) BACKTRACE_DEPTH(DEPTH)
@implementation NSObject (Backtrace)
+ (NSString *)appBacktraceOfDepth:(int)depth fromStackSymbols:(NSArray *)frames {
return [self backtraceOfDepth:depth fromStackSymbols:frames matching:[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleNameKey]];
}
+ (NSString *)backtraceOfDepth:(int)depth fromStackSymbols:(NSArray *)frames {
return [self backtraceOfDepth:depth fromStackSymbols:frames matching:nil];
}
+ (NSString *)backtraceOfDepth:(int)depth fromStackSymbols:(NSArray *)frames matching:(NSString *)from {
NSRegularExpression *regex = nil;
if (!NSClassFromString(@"NSRegularExpression") || !(regex = [NSRegularExpression regularExpressionWithPattern:@"[0-9]+ +(.+[^ ]) +0x[0-9a-f]+ (.+) \\+ [0-9a-f]+" options:0 error:nil]))
return [[frames objectAtIndex:1] substringFromIndex:51]; // no regex, be lame and rely on column counts
NSString *result = nil;
for (int goodframes=0, framenum=1; goodframes < depth && framenum < [frames count]; ++framenum) {
NSString *frame = [frames objectAtIndex:framenum];
NSTextCheckingResult *match = [regex firstMatchInString:frame options:0 range:NSMakeRange(0, [frame length])];
if (!match) NSAssert1(NO, @"unparsed stack frame: %@", frame);
if (from && ![from isEqualToString:[regex replacementStringForResult:match inString:frame offset:0 template:@"$1"]]) continue;
++goodframes;
NSString *caller = [regex replacementStringForResult:match inString:frame offset:0 template:@"$2"];
if (from && goodframes == 1 && [caller isEqualToString:@"main"]) return [self backtraceOfDepth:depth fromStackSymbols:frames matching:nil]; // no useful calls from us, take ones from anyone instead
result = !result ? caller : [result stringByAppendingFormat:@" < %@", caller];
}
return result ? result : @"?";
}
@end
@jpmhouston
Copy link
Author

provides macro "BACKTRACE_DEPTH(n)" that returns a string listing the methods that called you, useful for logging.
alternately spelled "CALLSTACK_DEPTH(n)"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment