• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Function to get current Backtrace and Address Slide
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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

  • Follow-Ups:
    • Re: Function to get current Backtrace and Address Slide
      • From: Wim Lewis <email@hidden>
  • Prev by Date: Canceling all touches
  • Next by Date: Performing a Fetch Request on a specific MO.
  • Previous by thread: Canceling all touches
  • Next by thread: Re: Function to get current Backtrace and Address Slide
  • Index(es):
    • Date
    • Thread