Sometimes when working in Xcode with the
All Exceptions breakpoint turned on, when starting the app it pauses on the
__cxa_throw symbol, but we can continue without crashing. This post will cover one of the common causes, missing font entitlements.
When enabling Exception Breakpoints in Xcode, lldb adds two symbolic breakpoints, one for Objective-C and one for C++. Objective-C uses
__cxa_throw. The reason we can resume from this breakpoint is that the exception is being caught by the caller of the function producing the exception.
For uncaught exceptions, it’s much easier to figure out the failure: for C++ and Objective-C we can wrap the caller in a
try/catch block. Additionally in Objective-C we can install an uncaught exception handler (this is how tools like crashlytics/fabric report exceptions) using
NSSetUncaughtExceptionHandler()1, but because the exception we are looking at is caught by a system framework, there are some other approaches we can take.
This is what the stacktrace looks like in Xcode:
frame 5 in that stacktrace, we can see that the method takes a
char const* value as the first parameter. This parameter represents the paths of the font being loaded. From this we should be able to figure out which font is causing us an issue.
We can set a symbolic breakpoint on this function and print the path of the font being loaded. As we want to print the first argument, we need to print the value of a register. This can get complicated across architectures, on arm 32-bit devices this value is stored in the
$r0 register, arm64 is stored in
$x0, on x86-64 it’s stored in
$rdi. LLDB makes this easy by providing an alias to the first arguments register:
$arg1. This is what our symbolic breakpoint looks like:
After running with the symbolic breakpoint set, we get a number of font paths (some of them system level fonts):
"~/Library/Developer/CoreSimulator/Devices/B5565658-9D7B-4E6F-9E41-743869B5B28F/data/Containers/Bundle/Application/728FC5B7-A342-45ED-97B8-5992E0E8DA39/MyCoolApp.app/OpenSans-Light.ttf" "~/Library/Developer/CoreSimulator/Devices/B5565658-9D7B-4E6F-9E41-743869B5B28F/data/Containers/Bundle/Application/728FC5B7-A342-45ED-97B8-5992E0E8DA39/MyCoolApp.app/OpenSans-Regular.ttf" "~/Library/Developer/CoreSimulator/Devices/B5565658-9D7B-4E6F-9E41-743869B5B28F/data/Containers/Bundle/Application/728FC5B7-A342-45ED-97B8-5992E0E8DA39/MyCoolApp.app/OpenSans-Semibold.ttf" .... snip other open sans fonts (there are a lot) ... "~/Library/Developer/CoreSimulator/Devices/B5565658-9D7B-4E6F-9E41-743869B5B28F/data/Containers/Bundle/Application/1F016E2B-031B-4512-8DA2-52B6FEFDC878/MyCoolApp.app/Roboto-Bold.ttf" "~/Library/Developer/CoreSimulator/Devices/B5565658-9D7B-4E6F-9E41-743869B5B28F/data/Containers/Bundle/Application/728FC5B7-A342-45ED-97B8-5992E0E8DA39/MyCoolApp.app/MyCoolApp-v2.4.ttf" "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Fonts/CoreUI/SFUIText.ttf" "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Fonts/CoreUI/SFUIDisplay.ttf"
Cross checking these against the
UIAppFonts we register in our
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <array> <string>MyCoolApp-v2.4.ttf</string> <string>OpenSans-Light.ttf</string> <string>OpenSans-Regular.ttf</string> <string>OpenSans-Semibold.ttf</string> <string>OpenSans-Bold.ttf</string> <string>OpenSans-ExtraBold.ttf</string> <string>OpenSans-Italic.ttf</string> <string>OpenSans-LightItalic.ttf</string> <string>OpenSans-SemiboldItalic.ttf</string> <string>OpenSans-BoldItalic.ttf</string> <string>OpenSans-ExtraBoldItalic.ttf</string> <string>Calibre-Black.otf</string> <string>Calibre-Semibold.otf</string> </array> </plist>
Hmmm, the Roboto font isn’t registered in there. Roboto is an Android font, we probably don’t want it in our iOS project. So we have to find out where this is being referenced from. Searching through code gives us no results, so this is probably specified in a
storyboard. We can find the usage using
$ ack --type-set xib:ext:xib,storyboard --type=xib Roboto
Classes/LoginController.xib 14: <array key="Roboto-Bold.ttf"> 15: <string>Roboto-Bold</string> 47: <fontDescription key="fontDescription" name="Roboto-Bold" family="Roboto" pointSize="10"/> 61: <fontDescription key="fontDescription" name="Roboto-Bold" family="Roboto" pointSize="14"/>
Aha! Once removing from the xib file and replacing with a font we do register for, the caught exception goes away and we are once again able to have our exception breakpoint set without interfering with our app start up.