Using breakpad in Mac client applications

This document is a step-by-step guide to building Mac client applications using Breakpad.

Prepare binary builds of Breakpad for use in your code tree

You can build breakpad framework and tool binaries through the xcode project file in the Breakpad project, or you can build them as project dependencies. The former approach is recommended and is covered in detail here, since building dependencies through other projects is problematic (matching configuration names) and the Breakpad code rarely changes as often as your application.

Build necessary goals

All directories are relative to the Breakpad source srcdirectory.


  • client/mac/Breakpad.xcodeproj'All' target built in Release mode . xcodebuildYou can see all targets of this project through the command:
breakpad % xcodebuild -list -project src/client/mac/Breakpad.xcodeproj 
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -list -project src/client/mac/Breakpad.xcodeproj

User defaults from command line:
    IDEPackageSupportUseBuiltinSCM = YES

Information about project "Breakpad":
    Targets:
        Breakpad
        Inspector
        breakpadUtilities
        crash_report_sender
        BreakpadTest
        All
        UnitTests
        generator_test
        minidump_file_writer_unittest
        handler_test
        gtest
        crash_generation_server_test
        minidump_generator_test_helper

    Build Configurations:
        Debug
        Debug With Code Coverage
        Release

    If no build configuration is specified and -scheme is not passed then "Release" is used.

    Schemes:
        All
        all_unittests
        Breakpad
        BreakpadTest
        breakpadUtilities
        byte_cursor_unittest
        bytereader_unittest
        crash_generation_server_test
        crash_report
        crash_report_sender
        dump_syms
        dwarf_cfi_to_module_unittest
        dwarf_cu_to_module_unittest
        dwarf_line_to_module_unittest
        dwarf2diehandler_unittest
        dwarf2reader_cfi_unittest
        generator_test
        gtest
        gtestmockall
        handler_test
        Inspector
        macho_dump
        macho_reader_unittest
        minidump_file_writer_unittest
        minidump_generator_test_helper
        minidump_upload
        module_unittest
        stabs_reader_unittest
        stabs_to_module_unittest
        symupload
        test_assembler_unittest
        UnitTests

Breakpad's 'All' target can be built in Release mode with the following command:

xcodebuild -configuration Release -target All -project src/client/mac/Breakpad.xcodeproj

You can also build only the Breakpad framework through the following command:

xcodebuild -configuration Release -target Breakpad -project src/client/mac/Breakpad.xcodeproj
  • implementcp -R client/mac/build/Release/Breakpad.framework <location in your source tree>
  • In tools/mac/dump_symsthe directory, build dump_syms.xcodeproj, and tools/mac/dump_syms/build/Release/dump_symscopy to a safe place where you can run it during the build process.

AddBreakpad.framework

In your application's framework, add Breakpad.Framework to your project's framework settings. When you select it from the file picker, it will let you pick a target to add; go ahead and check the one associated with your application.

Copy Breakpad into your application bundle

Copy Breakpad into your application bundle so it appears at runtime.

Go to the Targets section of the Xcode Project window. Click the triangle to display the application's build phases. Use the context menu (Control Click) to add a new Copy Files stage. In the new 'Get Info' General panel of this new stage, set the target to 'Frameworks' Close the 'Info' panel. Use the context menu to rename your new stage 'Copy Frameworks'. Now drag the Breakpad into this Copy Frameworks stage again. Drag it from wherever it appears in the project file tree.

Add a new Run Script build phase

Towards the end of the build phase, add a new Run Script build phase. This will run before Xcode calls on your project /usr/bin/strip. This is where you will call dump_symto output the symbols for each architecture built. In my case the relevant code was:

#!/bin/sh
$TOOL_DIR=<location of dump_syms from step 3 above>

"$TOOL_DIR/dump_syms" -a ppc "$PROD" > "$TARGET_NAME ppc.breakpad"

"$TOOL_DIR/dump_syms" -a i386 "$PROD" > "$TARGET_NAME i386.breakpad"

Adjust project settings

  • Open Separate Strip,
  • Set Strip Style to Non-Global Symbols.

Write code

You need to have an object as the delegate of NSApplication. In the header file of this object you need to add

  1. Add an ivar for Breakpad, and
  2. A declaration of applicationShouldTerminate:(NSApplication* sender) message.
#import <Breakpad/Breakpad.h>

@interface BreakpadTest : NSObject {
   .
   .
   .
   BreakpadRef breakpad;
   .
   .
   .
}
.
.
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
.
.
@end

In your object's implementation file,

  1. Add the following InitBreakpad method
  2. Modify your awakeFromNib method to look like this,
  3. Modify/add your application's delegate method as shown below
static BreakpadRef InitBreakpad(void) {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  BreakpadRef breakpad = 0;
  NSDictionary *plist = [[NSBundle mainBundle] infoDictionary];
  if (plist) {
    // Note: version 1.0.0.4 of the framework changed the type of the argument 
    // from CFDictionaryRef to NSDictionary * on the next line:
    breakpad = BreakpadCreate(plist);
  }
  [pool release];
  return breakpad;
}

- (void)awakeFromNib {
  breakpad = InitBreakpad();
}

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
  BreakpadRelease(breakpad);
  return NSTerminateNow;
}

Configure Breakpad

Configure Breakpad for your application.

  1. Look in the Breakpad.h file in Breakpad.framework for the keys, default values, and descriptions to be passed to BreakpadCreate().
  2. Add/edit Breakpad-specific entries in the dictionary passed to BreakpadCreate() - typically the application's information plist.

Example from Notifier Info.plist:<key>BreakpadProduct</key><string>Google_Notifier_Mac</string> <key>BreakpadProductDisplay</key><string>${PRODUCT_NAME}</string>

Build your application

almost finished!

verify

Check again:

Your app should include: myApp.app/Contents/Frameworks/Breakpad.framework in its bundle content.

The symbol files have reasonable contents (you can view them using a text editor.)

Look again at the Copy Frameworks phase of the project. Did you leak the .h file? Select them and delete them. (If you drag a bunch of files into your project, Xcode will often want to copy your .h files into the build, which will give away Google's secrets. Be wary!)

Upload symbol file

You need to configure the build process to store symbols in a location accessible to the minidump processor. There is a tool in tools/mac/symupload that can be used to send symbol files via HTTP post.

  1. test

Configure breakpad to send reports to a URL by adding to your application's Info.plist:

<key>BreakpadURL</key>
<string>upload URL</string>
<key>BreakpadReportInterval</key>
<string>30</string>

final notes

Breakpad checks to see if it's running under a debugger, and if so, usually does nothing. However, you can force Breakpad to run under a debugger by setting the Unix shell variable BREAKPAD_IGNORE_DEBUGGER to a non-zero value. You can use #if DEBUG to completely eliminate it from the debug build by surrounding the source code in the coding step above. Refer to //depot/googlemac/GoogleNotifier/main.m for examples. FYI, when your process forks(), the child process's exception handler is reset to default. Therefore they must reinitialize the Breakpad, otherwise the exception will be handled by Apple's Crash Reporter.

Reference documentation

Debugging using Breakpad’s dump file under mac

How To Add Breakpad To Your Mac Client Application

Compile via Xcode command line

Explore Xcode command line usage 1: Essential knowledge for Xcode builds

Guess you like

Origin blog.csdn.net/tq08g2z/article/details/125534778