Sharing LLDB debugging helpers between projects using a dynamic library
Xcode 5 added QuickLook support for standard types like
NSString, right within Xcode. Starting with Xcode 5.1,
UIView and custom types can be quickly previewed as well, which can be quite convenient when debugging projects.
The LLDB-QuickLook project adds a similar functionality to the LLDB Xcode console as well, but requires some categories to be added to each project you want to use LLDB-QuickLook with. This process is rather inconvenient since it requires you to edit your projects to make these categories somehow available (most probably by including the corresponding source files).
Instead of adding the categories to the projects, the LLDB-QuickLook categories can namely be packaged as a dynamic library, and made available when LLDB starts. Within the iOS simulator, the library can be loaded without
dlopen-ing it from the application, and without jailbreaking. This is why this post only focuses on the iOS simulator.
The approach described below can be applied to your own LLDB debugging helpers, which can be packaged as a dynamic library shared between your projects.
Enabling iOS dynamic library compilation in Xcode
Apple does not officially provide a way to create dynamic libraries for iOS, since their use does not comply with App Store rules. Xcode unsurprisingly complains when we try to build one:
target specifies product type 'com.apple.product-type.library.dynamic', but there's no such product type for the 'iphonesimulator' platform
You can still enable iOS dynamic library support by editing some Xcode configuration files, though, as described elsewhere:
For the simulator, open the Mac OS specification file:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX Product Types.xcspec
and copy over the section beginning with
com.apple.product-type.library.dynamicto its iOS counterpart:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications/iPhone Simulator ProductTypes.xcspec
Proceed similarly with the following files:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX Package Types.xcspec /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications/iPhone Simulator PackageTypes.xcspec
and the section beginning with
Restart Xcode to take the changes into account.
Building an LLDB-Quicklook dynamic library
To build a dynamic library we create a Mac OS X Cocoa Library project, setting its type to dynamic. We remove all useless stuff, set its SDK to Latest iOS and add LLDB-QuickLook source files. The resulting project can be found on my Github page, on a branch called
Checkout the repository, switch to the
dylib branch and run the following command to build the library:
xcodebuild -sdk iphonesimulator -configuration Release -project LLDB-QuickLook.xcodeproj
The dynamic library can be found in the
build directory, and is called
Loading the LLDB-QuickLook dynamic library into LLDB
To load the
LLDB-QuickLook.dylib dynamic library when LLDB starts, copy it somewhere (e.g.
~/Library/lldb/lib/LLDB-QuickLook.dylib) and add the following line to your
~/.lldbinit configuration file:
command alias quick_look_load_sim process load ~/Library/lldb/lib/LLDB-QuickLook.dylib
replacing the path by the one you chose.
quick_look_load_sim command can be manually triggered in LLDB to load the library (when running in the iOS simulator), but cannot work when no process has been attached.
To run the
quick_look_load_sim command early when an application has been attached, add a user-defined symbolic breakpoint on a function which gets called early, e.g.
UIApplicationMain. User-defined breakpoints are common to all you projects, and can trigger actions, like executing LLDB commands. To call our custom
quick_look_load_sim command, add a Debugger Command action calling
quick_look_load_sim to the breakpoint, and check Automatically continue after evaluating.
There is hope pending breakpoints might be added to LLDB in the future, in which case this trick could be replaced with pending breakpoints defined in the
Follow the LLDB-QuickLook installation steps and add the following commands to your
command script import ~/Library/lldb/lldb_quick_look.py command alias ql quicklook
Here I saved the Python script under
Now run any project in the simulator (be sure that the user-defined breakpoint is available), pause the execution, and try to enter a QuickLook LLDB command, e.g.
ql @"Hello, World!"
QuickLook should open and display the string.
This post discussed how debugging code can be packaged as a dynamic library, and how it can be automatically loaded when an application is debugged in the iOS simulator. By applying the same strategy, you could package your own LLDB debugging helpers as dynamic libraries which can be shared between your projects, without having to modify them. Have fun!