Resources:The Mac OS X Debugging Magic Technote contains a wealth of information about various debugging options built in to OS X. IMPORTANT: By default, Xcode has the "Load Symbols Lazily" preference set. As a result, any symbols not in the main static library (99% of our code) won't be visible to set breakpoints. The result is that you set breakpoints in the editor window and they're ignored entirely when you run. The fix, however, is very simple! Uncheck the "Load Symbols Lazily" checkbox in the "Debugging" panel in preferences. Now all your breakpoints will work, at the expense of a little longer load time in gdb. Well worth it, if you ask me.Debugging the renderer process:XCode's built in gdb wrapper doesn't allow you to debug more than one process at once and doesn't deal very well with debugging Chrome's subprocesses directly. There are two different ways around this: (a) Run Chrome in a single process
From now on Chromium will launch in single-process mode when invoked through this Xcode project, and the debugger will work fine. This obviously changes the apps behavior slightly, but for most purposes the differences aren't significant. If they are, though, you'll need to… (b) or, Attach XCode's debugger to a renderer process after launch1. Launch the main executable from the Terminal (not through XCode) and pass in the --renderer-startup-dialog flag on the command line. On OS X this causes the renderer to print a message with it's PID and then call pause() immediately up on startup. This has the effect of pausing execution of the renderer until the process receives a signal (such as attaching the debugger). e.g. $ ~/dev/chrome//src/xcodebuild/Debug/Chromium.app/Contents/MacOS/Chromium --renderer-startup-dialog the output should look like: ... [33215:2055:244180145280185:WARNING:/Users/Shared/bla/chrome/src/chrome/renderer/renderer_main.cc(48)] Renderer (33215) paused waiting for debugger to attach @ pid ... So 33215 is the PID of the renderer process in question. 2. Open chrome.xcodeproj in XCode and select Run -> Attach To Process -> Process ID .. 3. Click OK and off you go... Temporarily disabling the SandboxDisabling the sandbox can sometimes be useful when debugging, this can be achieved by passing the --no-sandbox flag on the command line. This will, for example, allow writing out debugging information to a file from the Renderer Process. e.g. $ ~/dev/chrome//src/xcodebuild/Debug/Chromium.app/Contents/MacOS/Chromium --no-sandbox Tips on Debugging the Renderer SandboxIn src/chrome/renderer/renderer.sb add the text (debug deny) right under the (deny default) line. This will cause a message to be printed to the Console every time an operation is denied by the Sandbox. This is really useful for debugging and can often provide an explanation for very puzzling problems. You can also get the Sandbox to send a SIGSTOP to a process when the sandbox denies functionality. This allows you to attach with a debugger and continue the execution from where it left off: $ sandbox-exec -p '(version 1) (allow default) (deny file-write* (regex "foo") (with send-signal SIGSTOP))' touch foo Breakpoints Not Getting Hit in gdbIf a breakpoint you set isn't causing the debugger to stop, try one of these solutions:
Debugging in Release ModeIn release mode, gdb will not be able to locate symbols for the framework that contains most of the application’s code. You can create a symbolic link to help gdb find these symbols. $ cd /path/to/chrome/src/xcodebuild $ ln -fs ../../../Chromium\ Framework.framework.dSYM Release/Chromium.app/Contents/Frameworks/ Preserving symbols in Release buildsProfiling tools like Shark and 'sample' expect to find symbol names in the binary, but in Release builds most symbols are stripped out. You can preserve symbols by temporarily changing the build process:
Note: Chromium has a ton of symbols, and the profiling tools are extremely slow at loading them in on 10.5. Either be prepared to wait several minutes, or use 10.6 in which this is much faster. (The above "Debugging in Release Mode" trick with the .dSYM file might work for Shark/sample too; I haven't tried it yet. —snej) Using DTracejgm's awesome introductory article:http://www.mactech.com/articles/mactech/Vol.23/23.11/ExploringLeopardwithDTrace/index.html Defining static probes on OS X: http://www.macresearch.org/tuning-cocoa-applications-using-dtrace-custom-static-probes-and-instruments http://www.brendangregg.com/dtrace.html#Examples http://blogs.sun.com/bmc/resource/dtrace_tips.pdf DTrace examples on OS X: /usr/share/examples/DTTk To get truss on Mac OS X, use dtruss. That requires root, so I often sudo dtruss -p and attach to a running nonroot program. Memory/Heap InspectionThere are several low-level command-line tools that can be used to inspect what's going on with memory inside a process.
'malloc_history' identifies the stack backtrace that allocated every malloc block in the heap. It lists every unique backtrace together with its number of blocks and their total size. It requires that the process use malloc stack logging, which is enabled if the environment variable MallocStackLogging is set when it launches. The 'env' command is handy for this: $ env MallocStackLogging=1 Chromium.app/Contents/MacOS/ChromiumThen in another shell you run $ malloc_history pid -all_by_sizeWatch out: the output is big. I ran malloc_history on a fairly bloated heap and got 60MB of text. 'leaks' finds malloc blocks that have no pointers to them and are probably leaked. It doesn't require MallocStackLogging, but it's more useful if it's on because it can then show the backtrace that allocated each leaked block. (So far I've seen only trivial leakage in Chrome.) 'vmmap' shows all the virtual-memory regions in the process's address space. This is less useful since it doesn't say anything about individual malloc blocks (except huge ones) but it can be useful for looking at things like static data size, mapped files, and how much memory is paged out. I recommend the "-resident" flag, which shows how much of each allocation is currently paged into RAM. See the man page for details. Notes:
Debugging on Leopard Issues The following issues apply when working on Leopard (10.5.x). NSZombieEnabled When debugging, be aware that using NSZombieEnabled has an interesting bug on Leopard. If NSZombieEnabled is on, C++ objects that are owned by Objective C objects do not get their destructors called. There are several Objective C objects in Chromium that own C++ objects thus rendering NSZombieEnabled virtually useless for debugging Chromium on Leopard. This does not apply to Snow Leopard where the bug appears to be fixed. Using Shark and Instruments Trying to use Shark and/or Instruments on Leopard with Chromium is extremely slow. Loading symbols can take virtually forever. Apple appears to have fixed up symbol loading in Snow Leopard as it works just fine there. Unless you have no other choice we would not recommend attempting to use Shark or Instruments with Chromium on Leopard. |