Hacking your Crash Reports

In a conversation on #macdev, it was pointed out that the Crash Reporter has an “Application Specific Information:” line when certain Apple apps crash. This obviously warranted investigation, and through the powers of Google it was determined that said investigation had in fact happened a few months ago. How fortunate that we didn’t spend time investigating it and writing test cases, only to find someone had already done a better job.

Anyway, this is an entirely unsupported thing to do, and the means of doing it may disappear at any time, so don’t. But if you do, do it cleanly, like this:

#ifndef NDEBUG
/*  Function to set “Application Specific Information” field in crash reporter
    log in Leopard. Extremely unsupported, so not used in release builds.
*/
static void InitCrashReporterInfo(void);
static void SetCrashReporterInfo(const char *info);
static BOOL sCrashReporterInfoAvailable = NO;
#else
#define InitCrashReporterInfo() do {} while (0)
#define SetCrashReporterInfo(i) do {} while (0)
#define sCrashReporterInfoAvailable 0
#endif

/* Insert code here. Or make it non-static, depending on what you’re doing. */

#ifndef NDEBUG
static char **sCrashReporterInfo = NULL;
static char *sOldCrashReporterInfo = NULL;
static NSLock *sCrashReporterInfoLock = nil;

static void InitCrashReporterInfo(void)
{
    // Load secret symbol __crashreporter_info__; don’t do anything if not found.
    sCrashReporterInfo = dlsym(RTLD_DEFAULT, "__crashreporter_info__");
    if (sCrashReporterInfo != NULL)
    {
        // We'll need a lock, too.
        sCrashReporterInfoLock = [[NSLock alloc] init];
        if (sCrashReporterInfoLock != nil)
        {
            sCrashReporterInfoAvailable = YES;
        }
        else
        {
            sCrashReporterInfo = NULL;
        }
    }
}

static void SetCrashReporterInfo(const char *info)
{
    char                    *copy = NULL, *old = NULL;
    
    /*  Don’t do anything if setup failed or the string is NULL or empty.
        (The NULL and empty checks may not be desirable in other uses.)
    */
    if (!sCrashReporterInfoAvailable || info == NULL || *info == '\0')  return;
    
    // Copy the string, which we assume to be dynamic...
    copy = strdup(info);
    if (copy == NULL)  return;
    
    /*  ...and swap it in.
        Note that we keep a separate pointer to the old value, in case
        something else overwrites __crashreporter_info__.
    */
    [sCrashReporterInfoLock lock];
    *sCrashReporterInfo = copy;
    old = sOldCrashReporterInfo;
    sOldCrashReporterInfo = copy;
    [sCrashReporterInfoLock unlock];
    
    // Delete our old string.
    if (old != NULL)  free(old);
}
#endif

For this to be actually useful, you’d want to be using Smart Crash Reports (apparently coming soonish to a Leopardy computer near you) or something similar.

This entry was posted in Code and tagged , , . Bookmark the permalink.

2 Responses to Hacking your Crash Reports

  1. Pingback: Ahruman’s Webthing » Blog Archive » Hacking your Log Messages

  2. Pingback: Recent Links Tagged With "crashreporter" - JabberTags

Leave a Reply

Your email address will not be published. Required fields are marked *