This document explains how to debug Mozilla-derived applications such as Firefox, Thunderbird and SeaMonkey on Mac OS X using Xcode. For specific information on a way to debug hangs, see Debugging a hang on OS X.
See the Mac OS X build requirements.
Creating the project in Xcode
Xcode is Apple's set of developer tools and IDE, shipping with the system as of Mac OS X 10.3.
- Open Xcode, and create a new workspace using File > New > New Workspace
Name and save your .xcworkspace file in your source directory
- Select File > Add Files to "Workspace" ("Workspace" will appear as your workspace's unique name)
Choose your source folder and click "Add files"
Select the "Create groups for any added folders" option.
This will take a few minutes.
- Create a new Project with File > New Project
Choose command-line application
Make sure it is a 32-bit (x86) application
Name it "Firefox"
You won't actually build this command line app, but you need a project in order to create a Scheme.
- Create a new Scheme with Product > New Scheme
- Modify the scheme to launch the actual Firefox binary using Product > Edit Scheme
Build Configuration: Debug
Executable: Choose the path to your debug build (NightlyDebug.app) on disk.
Now you can set breakpoints, in Xcode and choose Product > Run to start Firefox and debug.
- Open Xcode, and create a new Project with File > New Project. In the list, choose "Empty Project" as the project type, click Next, name the project and choose where to save the project, then click Finish.
- Now you need to add the executable. Select Project > New Custom Executable and type a pretty name, then click the Choose button to locate the .app file that you want to debug (Mozilla.app, Firefox.app, DeerParkDebug.app etc). The .app file is typically found inside the "dist" folder in your build directory. Do not click Finish yet!
- Important! - Older versions of Xcode won't make your life that easy; there is still one vital step to be done if you aren't using XCode 3 or higher. You must manually locate the executable binary inside the application bundle, and edit the path to that. In other words, the value of the Executable Path text field should look something like this: " ~/builds/mozilla/dist/DeerParkDebug.app/Contents/MacOS/firefox-bin" (Make sure to select the "-bin" file, the non-"-bin" is just a launch script.)
- Now click Finish. An entry with the pretty name you entered in the previous dialog will appear under the "Executables" branch of the "Groups & Files" pane in the Xcode Project window.
- In order for Xcode to know what sources you want to debug, you need to tell it where to find them. Go to Project > Edit Active Executable, click the Debugging tab, and finally drag your top-level mozilla/ directory to the panel "Additional folders to find source files in".
- Still in "Edit Active Executable", go to the panel titled "Arguments". Add "-P profilename" where profilename is the name of your debugging Firefox profile to the argument list.
- Still in "Arguments" panel, add variable "NO_EM_RESTART" with value "1" to the variable list.
- Go to Xcode > Preferences. Find the Debugging preferences pane, and make sure "Load symbols lazily" is unchecked.
- Finally, if you are debugging Firefox, Thunderbird or some other application that supports multiple profiles, using a separate profile for debugging purposes is recommended. See "Having a profile for debugging purposes" below.
Starting a debug session
When you have created a project file, simply use the menu item Debug > Debug Executable, or change to the debug view by clicking the debug button (typically the third one from the left), and click "Debug".
Setting a breakpoint is easy. Just open the source file you want to debug in Xcode, and click in the margin to the left of the line of code where you want to break.
During the debugging session, each time that line is executed, the debugger will break there, and you will be able to debug it.
Having a profile for debugging purposes
It is recommended to create a separate profile to debug with, whatever your task, so that you don't lose precious data like Bookmarks, saved passwords, etc. So that you're not bothered with the profile manager every time you start to debug, expand the "Executables" branch of the "Groups & Files" list and double click on the Executable you added for Mozilla. Click the plus icon under the "Arguments" list and type "-P <profile name>" (e.g. "-P MozillaDebug"). Close the window when you're done.
Looking at variables
Printing out information in realtime about "native" Objective-C objects is simple. For example, if there's an NSString named 'myString' that you want to get the contents of, you can use the print-object (or short: po) command.
(gdb) po myString 'This is the contents of the string'
Below are instructions for how to deal with C++ objects, such as when debugging code written in XPCOM.
If you've used a debugger before, this is pretty simple. There are two things that should be pointed out, though.
First, when looking at variables that are C++ classes, Xcode separates the protected/private members into their own sub-hierarchy called protected and private, respectively. It will also group inherited member variables into a sub-hierarchy named by the parent class. If you don't see the member variable you're looking for, make sure that you drill down all the way.
If you want to save yourself the hassle of flipping down many little triangles, you can display a variable on the console using
(gdb) p variable_name
Pointer types aren't automatically dereferenced so you may need to do that in the command. It will write out a fully expanded representation to the console. This representation is extremely customizable with various set print feature-name commands. See the gdb doc.
See Debugging Mozilla with gdb for non-Mac-specific information about using gdb.
Debugging from the Terminal with gdb
Debugging from within Xcode (see above) is much easier, but debugging with gdb in the Terminal is also possible.
1. cd into your Mozilla application (.app) bundle. As an example, we'll use a Firefox debug build.
% cd dist/DeerParkDebug.app/Contents/MacOS
2. Set the DYLD_LIBRARY_PATH environment variable to tell the loader that this is where all the shared libraries are
% export DYLD_LIBRARY_PATH=`pwd`
% cd ../../.. % gdb ./firefox-bin
Original version by Mike Pinkerton (mailto:email@example.com), migrated by Brian Ray (mailto:firstname.lastname@example.org). Updated to the new Xcode world and maintained by Håkan Waara (mailto:email@example.com).