Function to get current Backtrace and Address Slide
Function to get current Backtrace and Address Slide
- Subject: Function to get current Backtrace and Address Slide
- From: Jerry Krinock <email@hidden>
- Date: Mon, 28 Feb 2011 15:01:37 -0800
When my app encounters some errors, I display an error dialog offering the user to email me the current backtrace. That was easy to do using the backtrace() and backtrace_symbols() functions from execinfo.h, but I forgot to grab the dynamic-load address slide, which is needed to symbolize the addresses, since most of my code is in a private framework.
Apparently I can get the slides by using the _dyld_xxx_xxx_xxx() functions from mach-o/dyld.h. I've tested the following and it seems to work. But since I'm completely out of my league with this stuff I thought I'd throw this code out there in case someone who knows what they're doing sees something that is going to blow up. In particular, I'm not sure that it is 64-bit clean.
Oh, I know that there is a Cocoa alternative to getting the backtrace, but it requires the Mac OS X 10.6 SDK. The following code compiles with the 10.5 SDK.
Thanks,
Jerry Krinock
/********* .h *************/
/*!
@brief Returns a string containing the current backtrace, prefixed
by a table of useful library load addresses (slides).
@details Slides for system libraries, those in directories
/usr/lib/ or /System/Library, are not included in the table
of slides because they are useless and consume many bytes.
*/
NSString* SSYDebugBacktrace() ;
/********* .m *************/
#import "SSYDebug.h"
#import <execinfo.h>
#import <mach-o/dyld.h>
/* Just a little utility function for C strings */
static bool hasPrefix(const char* target, const char* prefix) {
int targetLength = strlen(target) ;
int prefixLength = strlen(prefix) ;
if (targetLength < prefixLength) {
return NO ;
}
NSInteger i ;
for (i=0; i<prefixLength; i++) {
if (target[i] != prefix[i]) {
return NO ;
}
}
return YES ;
}
NSString* SSYDebugBacktrace() {
NSMutableString* nsString = [[NSMutableString alloc] initWithString:
@" Slide (hex) Library\n"] ;
unsigned long i;
unsigned long count = _dyld_image_count();
for (i = 0; i < count; i++) {
unsigned long slide = _dyld_get_image_vmaddr_slide(i);
const char* name = _dyld_get_image_name(i);
const char* exclude1 = "/usr/lib/" ;
const char* exclude2 = "/System/Library/" ;
if (hasPrefix(name, exclude1)) {
continue ;
}
if (hasPrefix(name, exclude2)) {
continue ;
}
[nsString appendFormat:@"x %s\n", slide, name] ;
}
[nsString appendString:@"Call Stack:\n"] ;
// An infinite loop will "blow its stack" at 512 calls, so
// we allow a little more than that.
void* callstack[514] ;
NSInteger frames = backtrace(callstack, 514) ;
char** strs = backtrace_symbols(callstack, frames) ;
NSInteger iFrame ;
for (iFrame = 0; iFrame < frames; ++iFrame) {
NSString* moreString = [NSString stringWithCString:strs[iFrame]
encoding:NSUTF8StringEncoding] ;
[nsString appendString:moreString] ;
[nsString appendString:@"\n"] ;
}
free(strs) ;
NSString* answer = [nsString copy] ;
[nsString release] ;
return [answer autorelease] ;
}
/******* Example Return Value from SSYDebugBacktrace() *******/
Slide (hex) Library
0 /path/to/MyApp.app/Contents/MacOS/MyApp
5000 /path/to/MyFrmWk.framework/Versions/A/MyFrmWk
3bd000 /path/to/SSYLocalize.framework/Versions/A/SSYLocalize
3c4000 /path/toRBSplitView(Leo).framework/Versions/A/RBSplitView(Leo)
3d8000 /path/to/Sparkle.framework/Versions/A/SparkleCall Stack:
0 MyFrmWk 0x0015464f SSYDebugBacktrace + 264
1 MyFrmWk 0x00154784 SSYDebugLogBacktrace + 18
2 MyFrmWk 0x0001484e -[MyAppDelegate init] + 20
3 AppKit 0x94411c3b -[NSCustomObject nibInstantiate] + 384
4 AppKit 0x94411a49 -[NSIBObjectData instantiateObject:] + 253
5 AppKit 0x94410d4e -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 336
6 AppKit 0x9440f1f4 loadNib + 257
7 AppKit 0x9440e5ed +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 228
8 AppKit 0x9440e4fe +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 158
9 AppKit 0x9440e449 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 383
10 AppKit 0x9440b24d NSApplicationMain + 434
11 MyApp 0x00001db6 start + 54
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden