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:@"%12x %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 protected])
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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]