iOS Development - Manual Resolution of Crash Log

I. dSYM file

dSYM(debugging SYMbols), also known as debugging symbol table, originated from Debugging With Attributed Record Formats in Bell Labs.

2. dSYM file and Crash Log consistency

The corresponding relationship between the two can be determined by UUID.

1. Getting UUID from the crash log

The crash log has a Binary Images module

Binary Images:
       0x100e30000 -        0x106983fff  XXXXAPP arm64-unknown  <3671a0be1d663f4789dbfeb9190fdacf> /var/containers/Bundle/Application/643F8D1D-9000-4211-8DA0-0C2D42DB03C4/XXXXAPP.app/XXXXAPP
       0x181bee000 -        0x181c72fff  IOKit arm64-unknown  <54433b44779d39378d0789a4017a2948> /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
       0x181f0e000 -        0x1822bcfff  CFNetwork arm64-unknown   /System/Library/Frameworks/CFNetwork.framework/CFNetwork
       0x188503000 -        0x189081fff  JavaScriptCore arm64-unknown  <8be29f5ee31a302bbc16e47869e799ac> /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
       0x181845000 -        0x181bdbfff  CoreFoundation arm64-unknown  <533c841ed6e9313d8adb02388744e2ef> /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
       0x1839de000 -        0x183f8efff  ImageIO arm64-unknown  <728aeffd50883729bc1ac09900f05cf2> /System/Library/Frameworks/ImageIO.framework/ImageIO
       0x18323e000 -        0x183785fff  CoreGraphics arm64-unknown  <59a6f76dbc9f3e44bdf30351088b637d> /System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
       0x1872c6000 -        0x1873bcfff  AVFAudio arm64-unknown   /System/Library/Frameworks/AVFoundation.framework/Frameworks/AVFAudio.framework/AVFAudio
       0x18131d000 -        0x18139afff  libsystem_c.dylib arm64-unknown  <61d2e950add73139aea459b55997ea48> /usr/lib/system/libsystem_c.dylib
       0x18382b000 -        0x18383efff  GraphicsServices arm64-unknown  <5011ec2511d73a56af501e8207d54962> /System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices
       0x18127b000 -        0x1812e0fff  libdispatch.dylib arm64-unknown  <0c931ac760133de187bb6f440beed5eb> /usr/lib/system/libdispatch.dylib
       0x189ad3000 -        0x18b1a5fff  WebCore arm64-unknown  <2fe4173593ba35c4a5e04b40b40f1a7e> /System/Library/PrivateFrameworks/WebCore.framework/WebCore
       0x182a6d000 -        0x182a77fff  IOSurface arm64-unknown  <1f24b80565013f8d94b5e18c144f24bc> /System/Library/Frameworks/IOSurface.framework/IOSurface
EOF

Some information can be seen from this:

The starting and ending address of the code segment is: 0x100e30000 - 0x106983fff
 The CPU instruction set to run your application is: arm64
 The UUID of the application is 3671a0be1d663f4789dbfeb9190fdacf (case-insensitive)

2. Obtaining UUID from Symbol Table

Execute the following command to extract UUID from the symbol table:

user$ dwarfdump --uuid xxx.dSYM

//Or the command dwarfdump --uuid xxx.dSYM/Contents/Resources/DWARF/xxx

UUID: 815AF08E-2A1E-359C-9082-7C98326D51F4 (armv7) xxx.dSYM/Contents/Resources/DWARF/xxx
UUID: 3671A0BE-1D66-3F47-89DB-FEB9190FDACF (arm64) xxx.dSYM/Contents/Resources/DWARF/xxx
The UUID of armv7 instruction set is 815AF08E-2A1E-359C-9082-7C98326D51F4.
The UUID of arm64 instruction set is 3671A0BE-1D66-3F47-89DB-FEB9190FDACF.

If your binary supports multiple instruction sets, the UUID s corresponding to the symbol tables for each instruction set are listed here. Comparisons with the crash logs show that the two are identical before further parsing can be performed.

3. Computing the address of the crash symbol table

Thread 0 Lagged:
0   libsystem_kernel.dylib               0x1813efde8 0x1813ef000 + _mach_msg_trap
1   libsystem_kernel.dylib               0x1813efc60 0x1813ef000 + _mach_msg
2   IOKit                                0x181c57bb8 0x181bee000 + _io_connect_method
3   IOKit                                0x181bf4038 0x181bee000 + _IOConnectCallMethod
4   IOSurface                            0x182a71f9c 0x182a6d000 + _IOSurfaceClientWrapClientImage
5   IOSurface                            0x182a7545c 0x182a6d000 + _IOSurfaceWrapClientImage
6   ImageIO                              0x183aa8c78 0x1839de000 + __Z34IIO_CreateImageIOSurfaceWithFormatmmmj
7   ImageIO                              0x183a312d8 0x1839de000 + __ZN14JPEGReadPlugin37createImageBlockSetWithHardware_aspenEP7InfoRecP15CGImageProviderPK8__CFData6CGSizePb
8   ImageIO                              0x183b8cfc8 0x1839de000 + __ZN19AppleJPEGReadPlugin37createImageBlockSetWithHardwareDecodeEP7InfoRecP15CGImageProvider6CGSizePb
9   ImageIO                              0x183b8c8b0 0x1839de000 + __ZN19AppleJPEGReadPlugin17copyImageBlockSetEP7InfoRecP15CGImageProvider6CGRect6CGSizePK14__CFDictionary
10  ImageIO                              0x183b8b690 0x1839de000 + __ZN19AppleJPEGReadPlugin21CopyImageBlockSetProcEPvP15CGImageProvider6CGRect6CGSizePK14__CFDictionary
11  ImageIO                              0x183a13684 0x1839de000 + __ZN20IIOImageProviderInfo28copyImageBlockSetWithOptionsEP15CGImageProvider6CGRect6CGSizePK14__CFDictionary
12  ImageIO                              0x183a10e98 0x1839de000 + __ZN20IIOImageProviderInfo28CopyImageBlockSetWithOptionsEPvP15CGImageProvider6CGRect6CGSizePK14__CFDictionary
13  CoreGraphics                         0x18341d360 0x18323e000 + _img_blocks_create
14  CoreGraphics                         0x183424b8c 0x18323e000 + _img_data_lock
15  CoreGraphics                         0x183424444 0x18323e000 + _CGSImageDataLock
16  CoreGraphics                         0x183242440 0x18323e000 + _ripc_AcquireRIPImageData
17  CoreGraphics                         0x183438f5c 0x18323e000 + _ripc_DrawImage
18  CoreGraphics                         0x183428de8 0x18323e000 + _CGContextDrawImageWithOptions
19  xxx                            0x100ec4040 0x100e30000 + 606272
20  xxx                            0x100eb3868 0x100e30000 + 538728
21  xxx                            0x100ec9a70 0x100e30000 + 629360
22  xxx                            0x100eca478 0x100e30000 + 631928
23  xxx                            0x100f47dd8 0x100e30000 + 1146328
24  xxx                            0x101698d10 0x100e30000 + 8817936
25  xxx                            0x1016bcf54 0x100e30000 + 8965972
26  libdispatch.dylib                    0x18127caa0 0x18127b000 + __dispatch_call_block_and_release
27  libdispatch.dylib                    0x18127ca60 0x18127b000 + __dispatch_client_callout
28  libdispatch.dylib                    0x18128949c 0x18127b000 + __dispatch_main_queue_callback_4CF$VARIANT$mp
29  CoreFoundation                       0x181933070 0x181845000 + ___CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
30  CoreFoundation                       0x181930bc8 0x181845000 + ___CFRunLoopRun
31  CoreFoundation                       0x181850da8 0x181845000 + _CFRunLoopRunSpecific
32  GraphicsServices                     0x183836020 0x18382b000 + _GSEventRunModal
33  UIKit                                0x18b870758 0x18b553000 + _UIApplicationMain
34  xxx                            0x100e3413c 0x100e30000 + 16700
35  libdyld.dylib                        0x1812e1fc0 0x1812e1000 + _start

1. Symbol Table Stack Address Computing Method

In order to use symbol table to resolve the corresponding crash location, we need to calculate the corresponding crash stack address in symbol table.
From line 19 above, we can see that the application crash occurs at the runtime address 0x100ec4040, the starting address of the process is 0x100e30000, and the offset from the starting address of the process at the crash is 606272 decimal (corresponding to 0x94040 hexadecimal).
Three corresponding relations:

0x100ec4040 = 0x100e30000 + 0x94040

The corresponding formula is:

Runtime Stack Address = Runtime Start Address + Offset

The start address and crash address of crash stack are both run-time addresses. According to the principle that virtual memory offset is invariable, the stack address in symbol table can be obtained by providing the start address of TEXT segment and adding offset (here 0x94040):

Symbol Table Stack Address = Symbol Table Start Address + Offset

2. Get the starting address of TEXT segment in symbol table

Executive order

otool -l xxx.dSYM/Contents/Resources/DWARF/xxx
Load command 0
     cmd LC_UUID
 cmdsize 24
    uuid 815AF08E-2A1E-359C-9082-7C98326D51F4
Load command 1
     cmd LC_SYMTAB
 cmdsize 24
  symoff 8192
   nsyms 475187
  stroff 5710436
 strsize 18159960
Load command 2
      cmd LC_SEGMENT
  cmdsize 56
  segname __PAGEZERO
   vmaddr 0x00000000
   vmsize 0x00004000
  fileoff 0
 filesize 0
  maxprot 0x00000000
 initprot 0x00000000
   nsects 0
    flags 0x0
Load command 3
      cmd LC_SEGMENT
  cmdsize 940
  segname __TEXT
   vmaddr 0x00004000
   vmsize 0x053e4000
  fileoff 0
 filesize 0
  maxprot 0x00000005
 initprot 0x00000005
   nsects 13
    flags 0x0

segname __TEXT
vmaddr 0x00004000
That is the starting address of the TEXT segment.

3. Computation of Symbol Table Address

By formula:

Symbol Table Stack Address = Symbol Table Start Address + Offset
Available:

0x98040 = 0x94040 + 0x4000
That is, the crash address in the symbol table is 0x98040, and then the crash location can be resolved according to this address.

IV. Recovery of Collapse Information

1. dwarfdump command

dwarfdump --lookup 0x98040 --arch armv7 xxx.dSYM/

It can also be used:
dwarfdump --arch armv7 xxx.dSYM --lookup 0x98040 | grep 'Line table'

The output is as follows

----------------------------------------------------------------------
 File: xxx.dSYM/Contents/Resources/DWARF/xxx (armv7)
----------------------------------------------------------------------
Looking up address: 0x0000000000098040 in .debug_info... found!

0x00091812: Compile Unit: length = 0x000051dd  version = 0x0002  abbr_offset = 0x00000000  addr_size = 0x04  (next CU at 0x000969f3)

0x0009181d: TAG_compile_unit [127] *
             AT_producer( "Apple LLVM version 9.1.0 (clang-902.0.39.1)" )
             AT_language( DW_LANG_ObjC )
             AT_name( "/Users/xxx/xxx/xxController.m" )
             AT_stmt_list( 0x00041b6c )
             AT_comp_dir( "/Users/xxx/Pods" )
             AT_APPLE_major_runtime_vers( 0x02 )
             AT_low_pc( 0x00095394 )
             AT_high_pc( 0x0009bcf8 )

0x00094a3f:     TAG_subprogram [178] *
                 AT_low_pc( 0x00098036 )
                 AT_high_pc( 0x00098056 )
                 AT_frame_base( r7 )
                 AT_name( "__copy_helper_block_" )
                 AT_decl_file( "/Users/xx/xxxController.m" )
                 AT_decl_line( 185 )
                 AT_APPLE_isa( 0x01 )
Line table dir : '/Users/xxxController.m' line 176, column 74 with start address 0x0000000000098040

Looking up address: 0x0000000000098040 in .debug_frame... not found.

At compile time, the file directory, the name of the file where the crash occurred, and the specific line number in the file can accurately locate the cause of the crash.

2. atos command

atos is another more concise method of crash log parsing, which can be used in the following ways:

 $atos -o LuBao -arch armv7 0x98040

Compared with the analysis results of dwarfdump command, it is more concise and intuitive to point out the location of the crash.

3. Resolution of crash address without symbol table

In fact, atos also provides another way to avoid computing the symbolic table address corresponding to the crash address. The command format is as follows:

$atos -o xxx.dSYM/Contents/Resources/DWARF/xxx -arch armv7 -l 0x100e30000 0x100ec4040

The - l option specifies the starting address 0x100e30000 for binary files at runtime (see Binary Images for access), followed by the runtime address 0x100ec4040 for crashes.

Added by Joeker on Fri, 17 May 2019 10:51:08 +0300