background

After the launch of App, we usually use some tools such as Bugly to collect online crash, and the function call stack on the collection are all some function addresses. We cannot know which code under which file caused the crash. If we want to know which function caused the crash, We need to upload dSYM files generated after compilation. Why do we need dSYM files?

DSYM concept

What is a DWARF

DWARF is a fixed data format used by many compilers and debuggers to support source-level debugging

What is the dSYM

DSYM is a file that stores debugging information in DWARF format, that is, dSYM is a file.

To explore the dSYM

.o with debug symbol

1, we use firstclangwilltest.mCompiled into.oFile,test.mThe content is shown below

clang -g -c test.m -o test.o
Copy the code

2, we use objcdump to view the header information of test.o

objdump --macho --private-headers test.o

Section
  sectname __debug_str
   segname __DWARF
      addr 0x0000000000000158
      size 0x00000000000000a9
    offset 1616
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Copy the code

We can see that at compile time, the debugging information is stored in a section named __DWARF.

Executable file with debug symbol

1. We continue to use clang as an executable with debug symbols, and no longer use -c arguments

clang -g test.m -o test
Copy the code

2. View the segment information

bel@beldeMacBook-Pro dSYM % objdump --macho --private-headers test test: Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags MH_MAGIC_64 X86_64 ALL 0x00 EXECUTE 16 1048 NOUNDEFS DYLDLINK TWOLEVEL PIE Load command 0 cmd LC_SEGMENT_64 cmdsize 72 segname __PAGEZERO vmaddr 0x0000000000000000 vmsize 0x0000000100000000 fileoff 0 filesize 0 maxprot --- initprot --- nsects 0 flags (none) Load command 1 cmd LC_SEGMENT_64 cmdsize 232 segname __TEXT ... Section sectname __text segname __TEXT ... Section sectname __unwind_info segname __TEXT ... Load command 2 cmd LC_SEGMENT_64 cmdsize 152 segname __DATA_CONST ... Section sectname __objc_imageinfo segname __DATA_CONST ... Load command 3 cmd LC_SEGMENT_64 cmdsize 152 segname __DATA ... Section sectname __data segname __DATA ... Load command 4 cmd LC_SEGMENT_64 cmdsize 72 segname __LINKEDIT ... Load command 5 cmd LC_DYLD_INFO_ONLY cmdsize 48 rebase_off 0 rebase_size 0 bind_off 0 bind_size 0 weak_bind_off 0 weak_bind_size 0 lazy_bind_off 0 lazy_bind_size 0 export_off 49152 export_size 80 Load command 6 cmd LC_SYMTAB cmdsize 24 symoff 49240 nsyms 23 stroff 49608 strsize 192 Load command 7 cmd LC_DYSYMTAB cmdsize 80 .... Load command 8 cmd LC_LOAD_DYLINKER cmdsize 32 name /usr/lib/dyld (offset 12) Load command 9 cmd LC_UUID cmdsize 24 uuid 2890FF4F-897E-30b1-a90C-48a58b0b0146 Load Command 10 CMD LC_BUILD_VERSION cmdsize 32 Platform MacOS SDK 11.3 Minos 11.0 Ntools 1 tool ld version 650.9 Load command 11 CMD LC_SOURCE_VERSION cmdsize 16 version 0.0 Load command 12 CMD LC_MAIN  cmdsize 24 entryoff 16256 stacksize 0 Load command 13 cmd LC_LOAD_DYLIB cmdsize 56 name /usr/lib/libSystem.B.dylib (offset 24) ....Copy the code

At this point, we find no information about __DWARF in the Mach O file,

3. View its symbol table

nm -pa test

bel@beldeMacBook-Pro dSYM % nm -pa test
0000000000000000 - 00 0000    SO /Users/bel/Desktop/dSYM/
0000000000000000 - 00 0000    SO test.m
0000000060e97f85 - 03 0001   OSO /var/folders/d2/_hhc47fd0cvd4b7n2hrcpxt80000gn/T/test-b74f6a.o
0000000100003f60 - 01 0000 BNSYM 
0000000100003f60 - 01 0000   FUN _test
0000000000000010 - 00 0000   FUN 
0000000000000010 - 01 0000 ENSYM 
0000000100003f70 - 01 0000 BNSYM 
0000000100003f70 - 01 0000   FUN _test_1
0000000000000010 - 00 0000   FUN 
0000000000000010 - 01 0000 ENSYM 
0000000100003f80 - 01 0000 BNSYM 
0000000100003f80 - 01 0000   FUN _main
0000000000000035 - 00 0000   FUN 
0000000000000035 - 01 0000 ENSYM 
0000000000000000 - 00 0000  GSYM _global
0000000000000000 - 01 0000    SO 
0000000100000000 T __mh_execute_header
0000000100008000 D _global
0000000100003f80 T _main
0000000100003f60 T _test
0000000100003f70 T _test_1
                 U dyld_stub_binder
Copy the code

In its symbol table, we see the _test, _test_1 symbols that we use,

summary

The compiler puts debugging information in the __DWARF section at compile time, removes the __DWARF section when linking, and puts symbolic information in the __DWARF section.

Generate a dSYM file

1. We use the compiled -g1 parameter to generate the dSYM file

clang -g1 test.m -o test
Copy the code

2. Run the dwarfdump command to view dSYM files

bel@beldeMacBook-Pro dSYM % dwarfdump test.dSYM test.dSYM/Contents/Resources/DWARF/test: file format Mach-O 64-bit x86-64 .debug_info contents: 0x00000000: Compile Unit: length = 0x00000063, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x00000067) 0x0000000b: DW_TAG_compile_unit DW_AT_producer ("Apple clang Version 12.0.5 (clang-1205.0.22.9)") DW_AT_language (DW_LANG_ObjC) DW_AT_name ("test.m") DW_AT_LLVM_sysroot ("/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk") DW_AT_APPLE_sdk ("MacOSX.sdk") DW_AT_stmt_list (0x00000000) DW_AT_comp_dir ("/Users/bel/Desktop/dSYM") DW_AT_APPLE_major_runtime_vers (0x02) DW_AT_low_pc (0x0000000100003f60) DW_AT_high_pc (0x0000000100003fb5) 0x00000033: DW_TAG_subprogram DW_AT_low_pc (0x0000000100003f60) DW_AT_high_pc (0x0000000100003f66) DW_AT_name ("test") 0x00000044: DW_TAG_subprogram DW_AT_low_pc (0x0000000100003f70) DW_AT_high_pc (0x0000000100003f76) DW_AT_name ("test_1") 0x00000055:  DW_TAG_subprogram DW_AT_low_pc (0x0000000100003f80) DW_AT_high_pc (0x0000000100003fb5) DW_AT_name ("main") 0x00000066: NULLCopy the code

We can see that in dSYM files, debug symbols are stored in a certain format, including virtual memory address values and symbol names.

How to restore virtual memory addresses to symbols

Call stack containing debug symbols

Let’s open Xcode and create a new project to crash the App 3 seconds after it starts. The code is as follows:

Its CRSAH information is as follows:

crashOccur in the-[ViewController warfTest]Method inside.

Call stack without debug symbols

By default, we are inReleaseIn modeThe App package.XcodeWill usestripCommand,Local symbolTake off, exportipaPackage generated whendSYMFile,DebugIn the mode, we need to putDeployment PostprocessingSet toYes. It is executed after each compilationstripCarry off sign

At this time, the crash log is:

From the log, we can not determine which function caused the crash.

After compiling and running, dSYM is generated

At this point, in Debug mode, the compilation only completes using strip to strip symbols, We set PROJECT -> Build Settings -> Build Options -> Debug Information Format to DWARF with dSYM File. And set Deployment Postprocessing to NO(NO unsigned) so that we can get the dSYM file

Restore debug symbols based on virtual addresses and dSYM

And then we run the project again, and then crash,

In line 3, the memory address value is 0x000000010A107eb4, which is equal to the virtual address value of the ASLR + function during execution.

First we need to get the ASLR value for this run:

(lldb) image list [ 0] 3B857210-92BA-359F-A96E-856AC9E5CB8F 0x000000010a107000 /Users/bel/Library/Developer/Xcode/DerivedData/dSYMProject-ccrqorgatcanaacgnyihzhjcjcwi/Build/Products/Debug-iphonesimul ator/dSYMProject.app/dSYMProject /Users/bel/Library/Developer/Xcode/DerivedData/dSYMProject-ccrqorgatcanaacgnyihzhjcjcwi/Build/Products/Debug-iphonesimul ator/dSYMProject.app.dSYM/Contents/Resources/DWARF/dSYMProjectCopy the code

ASLR = 0x000000010A107000-0x0000000100000000 (vmsize), The virtual address of this function is 0x000000010a107eb4-0x00000000A107000 = 0x100000EB4

Find the symbol for this address in the dSYM file:

bel@beldeMacBook-Pro ~ % dwarfdump --lookup 0x100000EB4 /Users/bel/Library/Developer/Xcode/DerivedData/dSYMProject-ccrqorgatcanaacgnyihzhjcjcwi/Build/Products/Debug-iphonesimul ator/dSYMProject.app.dSYM /Users/bel/Library/Developer/Xcode/DerivedData/dSYMProject-ccrqorgatcanaacgnyihzhjcjcwi/Build/Products/Debug-iphonesimul ator/dSYMProject.app.dSYM/Contents/Resources/DWARF/dSYMProject: file format Mach-O 64-bit x86-64 0x000474bb: Compile Unit: length = 0x0000023d, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x000476fc) 0x000474c6: DW_TAG_compile_unit DW_AT_producer ("Apple clang Version 11.0.3 (clang-1103.0.32.62)") DW_AT_language (DW_LANG_ObjC) DW_AT_name ("/Users/bel/Desktop/dSYMProject/dSYMProject/ViewController.m") DW_AT_stmt_list (0x0000a891) DW_AT_comp_dir ("/Users/bel/Desktop/dSYMProject") DW_AT_APPLE_major_runtime_vers (0x02) DW_AT_low_pc (0x0000000100000ce0) DW_AT_high_pc  (0x0000000100000ef6) 0x000475dd: DW_TAG_subprogram DW_AT_low_pc (0x0000000100000e70) DW_AT_high_pc (0x0000000100000ef6) DW_AT_frame_base (DW_OP_reg6 RBP)  DW_AT_object_pointer (0x000475f6) DW_AT_name ("-[ViewController warfTest]") DW_AT_decl_file ("/Users/bel/Desktop/dSYMProject/dSYMProject/ViewController.m") DW_AT_decl_line (26) DW_AT_prototyped (true) Line info: file 'ViewController.m', line 29, column 18, start line 26 bel@beldeMacBook-Pro ~ %Copy the code

Thus, we can conclude that 0x000000010A107eb4 represents the [ViewController warfTest] method at line 29 in the viewController.m file. This allows us to restore debug symbols based on address values and dSYM files.

conclusion

1. DSYM is a file in DWARF format,DWARF is a format for storing debugging information. 2, Deployment Postprocessing == YES and strip == All Symbols will remove All local Symbols during compilation. 3, When Deployment Postprocessing == NO and Debug Information Format == DWAR with dSYM File, dSYM will be generated after compilation. 4. According to the offset memory address value and ASLR, the real virtual address value of the function can be obtained. According to the real virtual address value, its debugging information can be obtained in the dSYM file.