profile picture

Debug iOS Crashlytics

July 03, 2022 - iOS debugging

I was recently made confused by the famous unclear EXC_BREAKPOINT error on Crashlytics for an iOS project. The code SomeAPI below was converted from Objective C to Swift. The error log was

Crashed: com.apple.main-thread
EXC_BREAKPOINT 0x000000010457c8f4

Crashed: com.apple.main-thread
0  ExampleApp                     0x16d08f4 SomeAPI.report(obj:reason:duration:) + 172 (SomeAPI.swift:172)
1  ExampleApp                     0x16d0950 @objc SomeAPI.report(obj:reason:duration:) + 4284740 (<compiler-generated>:4284740)
2  ExampleApp                     0x168f8c4 -[SomeObject report:duration:] + 139 (SomeObject.m:139)
3  ExampleApp                     0x286e0 -[SomeViewController report:] + 286 (SomeViewController.m:286)
4  CoreFoundation                 0x292d8 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
5  CoreFoundation                 0xbe8d4 ___CFXRegistrationPost_block_invoke + 48
6  CoreFoundation                 0x93bf4 _CFXRegistrationPost + 416

Line 172 of SomeAPI is not that helpful.

func report(
    obj: SomeObject,
    reason: SomeEnum,
    duration: TimeInterval
) -> SomeResult {
    delegateReport(
        url: someUrl,
        obj: obj,
        additionalInfo: ["duration": NSNumber(value: (UInt) duration)]
    )
} // line 172

After looking around on StackOverflow with keyword EXC_BREAKPOINT, most were related to race conditions. Coming from Android with the helpful error stacktrace, I was desperate for another clues. What I found out was that the first line was always 0x16d08f4. Can we disassemble the build output to know what's the instruction at that offset?

  1. We can easily get the build output (dSym files) from App Store. I saw multiple dSym files in a version, but I knew that my app had the largest size. Let's say it's my.dSYM.
  2. Based on this site help, I found the start address
    otool -l my.dSYM/Contents/Resources/DWARF/target
    
    Which results in
    Load command 3  
          cmd LC_SEGMENT_64
      cmdsize 1992
      segname __TEXT
       vmaddr 0x0000000100000000 <---
       vmsize 0x0000000000f90000
    
  3. Add the 0x16d08f4 to 0x0000000100000000.
    The result is 0x00000001016d08f4.
  4. Use dwarfdump.
    dwarfdump --arch arm64 my.dSYM --lookup 0x00000001016d08f4
    
    The result made everything clear.
    DW_AT_abstract_origin	(0x004d7653 "Swift runtime failure: Double value cannot be converted to UInt because it is either infinite or NaN")
    

References