What is a dSYM file?

In project development, we often need to analyze crash log to track down online bugs, in which we will use an important file, called dSYM file. DSYM is a mapping table of memory addresses with function names, file names, and line numbers. It is commonly used for crash log analysis. < Start address > < End address > < function > [< file name: line number >]

The symbol table file. DSYM is actually a directory of files extracted from the Mach-o file. The actual folder used to store the debugging information is DWARF

When Xcode compiles the project, we will see a dSYM file with the same name. DSYM is a relay file that holds the address mapping information for hexadecimal functions. The symbols we are debugging will be included in this file, and a new dSYM file will be generated each time we compile the project. Located in the/Users / < user name > / Library/Developer/Xcode/Archives directory.

Usage of dSYM files

Obtain the address of the crashed function from the crash log, and then query the corresponding function name and file name in the dSYM file based on the function address to locate the error.

The error stack

0 libobjc.A.dylib   0x00000001941bbbdc objc_msgSend + 28
1 UIKit 0x00000001885f0f74 0x00000001881fc000 + 4149108
2 UIKit 0x00000001882e5bec 0x00000001881fc000 + 957420
3 UIKit 0x00000001882e5960 0x00000001881fc000 + 956768
4 UIKit 0x00000001882ec5e0 0x00000001881fc000 + 984544
5 UIKit 0x00000001882095f8 0x00000001881fc000 + 54776
6 UIKit 0x000000018822aa34 0x00000001881fc000 + 191028
7 UIKit 0x0000000188209310 0x00000001881fc000 + 54032
8 UIKit 0x0000000188209310 0x00000001881fc000 + 54032
9 UIKit 0x000000018822aa34 0x00000001881fc000 + 191028
10 UIKit    0x0000000188209310 0x00000001881fc000 + 54032
11 UIKit    0x0000000188209310 0x00000001881fc000 + 54032
12 UIKit    0x0000000188209310 0x00000001881fc000 + 54032
13 UIKit    0x0000000188209310 0x00000001881fc000 + 54032
14 UIKit    0x0000000188209310 0x00000001881fc000 + 54032
15 UIKit    0x0000000188209310 0x00000001881fc000 + 54032
16 UIKit    0x00000001882089e0 0x00000001881fc000 + 51680
17 Foundation   0x0000000184891908 0x000000018483c000 + 350472
18 UIKit    0x00000001882088a0 0x00000001881fc000 + 51360
19 UIKit    0x00000001882143a0 0x00000001881fc000 + 99232
20 UIKit    0x00000001883000b0 0x00000001881fc000 + 1065136
21 UIKit    0x0000000188344128 0x00000001881fc000 + 1343784
22 UIKit    0x00000001883439f0 0x00000001881fc000 + 1341936
23 UIKit    0x000000018840d5c4 0x00000001881fc000 + 2168260
24 UIKit    0x0000000188241418 0x00000001881fc000 + 283672
25 UIKit    0x000000018840d430 0x00000001881fc000 + 2167856
26 UIKit    0x0000000188241418 0x00000001881fc000 + 283672
27 UIKit    0x000000018822a52c 0x00000001881fc000 + 189740
28 UIKit    0x000000018840d068 0x00000001881fc000 + 2166888
29 UIKit    0x0000000188241418 0x00000001881fc000 + 283672
30 UIKit    0x000000018822a52c 0x00000001881fc000 + 189740
31 UIKit    0x0000000188240db4 0x00000001881fc000 + 282036
32 UIKit    0x0000000188200750 0x00000001881fc000 + 18256
33 CoreFoundation   0x0000000183a16a50 0x0000000183938000 + 911952
34 CoreFoundation   0x0000000183a139dc 0x0000000183938000 + 899548
35 CoreFoundation   0x0000000183a13dbc 0x0000000183938000 + 900540
36 CoreFoundation   0x00000001839410a4 CFRunLoopRunSpecific + 396
37 GraphicsServices 0x000000018cadb5a4 GSEventRunModal + 168
38 UIKit    0x0000000188272aa4 UIApplicationMain + 1488
39 APP_BUNDLE_NAME  0x0000000100327938 0x00000001000a0000 + 2652472
40 libdyld.dylib    0x0000000194816a08 0x0000000194814000 + 10760
Copy the code

Analyze the data

  • Stack Address:0x0000000100327938
  • Load Address (initial Address) :0x00000001000a0000
  • Slide Value (32-bit virtual address) :0x00004000
  • Slide Value (64-bit virtual address) :0x0000000100000000
  • Symbol Offset:2652472
  • File Address (32 bits) :0x28B938
  • File Address (64-bit File Address) :0x100287938

Note that virtual addresses distinguish between 32-bit (LC_SEGMENT) and 64-bit (LC_SEGMENT_64) segments

Symbolic dSYM files

Each xx.app and xx.app.dSYM file has its own UUID, and the crash file also has its own UUID. As long as the UUID of these three files is the same, we can use them to resolve the correct error function information. By symbolizing a dSYM file, you can locate the error file and line number information.

Xcode is automatically symbolized

Xcode comes with the Symbolicatecrash tool. The Crash and. DSYM files are symbolized to get detailed Crash information.

If you don’t have the distribution package, such as computer packaging is others publish a package, or is the package on some platforms, only need you to copy xcarchive to $HOME/Library/Developer/Xcode/Archives directory, Xcode can automatically help you symbolization.

Atos single/multi-line symbolization

Atos will offer to calculate the virtual address for us as long as we provide the first address and the stack address

  1. To view the UUID of the xx.app file, enter the command dwarfdump -uuid xx.app/xx (xx stands for your project name) in terminal.

  2. To view the UUID of the xx.app.dSYM file, run the following command in terminal:

Dwarfdump - uuid appName. App. DSYMCopy the code
  1. Crash fileIn the first rowIncident IdentifierIs that theCrash filetheUUID.
  2. useATOSCommand toA singleorMultiple linesStack progresssymbolicOperation, in order toArmv7 architectureAs an example. Complete syntaxAtos-arch \<architecture\> -o \<binary filename\> -l \<load address\> \<stack address 1\> \<stack address 2\>...
Atos armv7 -o appName crashAddressCopy the code

The result might look something like this:

main (in ) (main.m:14)
Copy the code

Use LLDB for symbolization

(LLDB) target the create - arch arm64. / APP_BUNDLE_NAME app. DSYM/Contents/Resources/DWARF/APP_BUNDLE_NAME * Current the executable Set to '. / APP_BUNDLE_NAME. App. DSYM/Contents/Resources/DWARF/APP_BUNDLE_NAME '(arm64). (LLDB) image lookup * - the address 0x100287938* Address: APP_BUNDLE_NAME[0x0000000100287938] (APP_BUNDLE_NAME.__TEXT.__text + 2632468) Summary: APP_BUNDLE_NAME`main + 88 at main.m:14Copy the code

Use dwarfdump to symbolize

$ dwarfdump --lookup 0x100287938 --arch arm64 APP_BUNDLE_NAME.app.dSYM ---------------------------------------------------------------------- File: APP_BUNDLE_NAME.app.dSYM/Contents/Resources/DWARF/APP_BUNDLE_NAME (arm64) ---------------------------------------------------------------------- Looking up address: 0x0000000100287938 in .debug_info... found! 0x002942c4: Compile Unit: length = 0x0000024d version = 0x0002 abbr_offset = 0x00000000 addr_size = 0x08 (next CU at 0x00294515) 0x002942cf: TAG_compile_unit [106] * AT_producer("Apple LLVM version 8.1.0 (clang-802.0.38)") AT_language(DW_LANG_ObjC) AT_name(  "/Users/user/APP_PROJECT_NAME/APP_PROJECT_NAME/main.m" ) AT_stmt_list( 0x00128d9d ) AT_comp_dir( "/Users/user/APP_PROJECT_NAME" ) AT_APPLE_optimized( 0x01 ) AT_APPLE_major_runtime_vers( 0x02 ) AT_low_pc( 0x00000001002878d8 ) AT_high_pc( 0x0000000100287960 ) 0x00294480: TAG_subprogram [226] * AT_low_pc( 0x00000001002878e0 ) AT_high_pc( 0x0000000100287960 ) AT_frame_base( reg29 ) AT_name( "main" ) AT_decl_file( "/Users/user/APP_PROJECT_NAME/APP_PROJECT_NAME/main.m" ) AT_decl_line( 12 ) AT_prototyped( 0x01 )  AT_type( {0x002944c7} ( int ) ) AT_external( 0x01 ) AT_APPLE_optimized( 0x01 ) Line table dir : '/Users/user/APP_PROJECT_NAME/APP_PROJECT_NAME' Line table file: 'main.m' line 14, column 16 with start address 0x0000000100287924 Looking up address: 0x0000000100287938 in .debug_frame... not found.Copy the code

__debug_info data

In addition to the normal symbolic dYSM file, we can also get the __debug_info information by using the Dwarfdump tool. In combination with the assembly instructions from the disassembly of binary files, we can further analyze the problem:

$ dwarfdump --debug-info ./testDwarf.app.dSYM/Contents/Resources/DWARF/testDwarf
Copy the code
0x0004005f: TAG_subprogram [122] * AT_low_pc(0x0000000100006760) // Method code start address AT_high_pc(0x00000074) // Method code length AT_frame_base(reg29) // Specify that the frame base of this method is x29 (i.e. Fp), AT_object_pointer({0x00040078}) AT_name("-[ViewController myFunction:]") "/ Users/jz/BSL/Tests/testDwarf testDwarf/ViewController. M") / / file path AT_decl_line (22) / / line number AT_prototyped (true) 0x00040078: TAG_formal_parameter [123] AT_location( fbreg -8 ) AT_name( "self" ) AT_type( {0x000400bb} ( const ViewController* ) ) AT_artificial( true ) 0x00040084: TAG_formal_parameter [123] AT_location( fbreg -16 ) AT_name( "_cmd" ) AT_type( {0x000400c5} ( SEL ) ) AT_artificial( true ) 0x00040090: TAG_formal_parameter [124] AT_location(fbreg-20) MyFunction AT_frame_base = x29; $x29-20 AT_name("arg"); $x29-20 AT_name("arg"); "/Users/jz/bsl/Tests/testDwarf/testDwarf/ViewController.m" ) AT_decl_line( 22 ) AT_type( {0x000400d8} ( int ) ) // See the next code snippet 0x0004009e for specific type information: TAG_variable [125] AT_location(breg31 +24) == x31 +24 X31 is sp AT_name (" local ") / / local variables local AT_decl_file ("/Users/jz/BSL/Tests/testDwarf testDwarf/ViewController. M ") AT_decl_line(23) AT_type({0x000400d8} (int)) // See next code fragment 0x000400ac: TAG_variable [125] AT_location( breg31 +20 ) AT_name( "i" ) AT_decl_file( "/Users/jz/bsl/Tests/testDwarf/testDwarf/ViewController.m" ) AT_decl_line( 24 ) AT_type( {0x000400d8} ( int ) )Copy the code

For a brief analysis of 0x0004005f:

0x0004005f: TAG_subprogram [122] * AT_low_pc(0x0000000100006760) // Method code start address AT_high_pc(0x00000074) // Method code length AT_frame_base(reg29) // Specify that the frame base of this method is x29 (i.e. Fp), AT_object_pointer({0x00040078}) AT_name("-[ViewController myFunction:]") "/ Users/jz/BSL/Tests/testDwarf testDwarf/ViewController. M") / / file path AT_decl_line (22) / / line number AT_prototyped (true)Copy the code
  • AT_low_pcRepresents the starting address of the method code
  • AT_high_pcRepresents the method code length
  • AT_frame_base

If I understand this correctly, this refers to the Frame Pointer register fp(x29), which is also called the stack base register, and it holds the bottom of the stack address.

There is also the LR (X30) Register (Link Register), which is used to hold the memory address of the next instruction to call the jump instruction BL instruction

Zr (x31) Zero Register: (Zero Register), XZR/WZR respectively represent 64/32 bits of Zero Register, its function is 0, written in represents the result of discarded, read out is 0. But in the ARM64 assembly, the x31 register does not always represent the XZR, and sometimes the SP register:

Sp: (Stack Pointer), a register at the top of the Stack, used to save the top address of the Stack

  • AT_name: Indicates the name of a method, parameter, variable, etc
  • AT_location: of parameters/variablesMemory address

In combination with the concepts of fp, LR, zr and SP registers mentioned above, we can see the meanings of several parameters of location here. For example, fBREG-20 represents fp register offset -20, breg31 +24 represents SP register offset 24

After sorting out the meaning of this information, we can combine the disassembled assembly instructions to analyze the crash information in more detail.

— To be continued


Swift learning group

Welcome to join my Swift learning wechat group, and we can supervise our study together. My wechat is ReesE90

App crash site variable names and their actual values (not just registers)