一、dSYM 文件生成

1、Xcode 自动生成,配置:

Xcode -> Build Settings -> Code Generation -> Generate Debug Symbols -> Yes

Xcode -> Build Settings -> Build Option -> Debug Information Format -> DWARF with dSYM File

2、手动生成:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil 

/Users/oudushu/Library/Developer/Xcode/DerivedData/YourApp-cqvijavqbptjyhbwewgpdmzbmwzk/Build/Products/Debug-iphonesimulator/YourApp.app/YourApp -o YourApp.dSYM

二、如何找到对应的 dSYM 文件:

  1. 从发布的归档包里面找: Xcode -> Window -> Organizer -> 找到打包好的文件(Show in Finder)-> 选中文件(右键显示包内容)-> dSYMs文件夹下就是了
  2. 从iTunes Connect里面找
  3. mdfind工具:mdfind “com_apple_xcode_dsym_uuids == E30FC309-DF7B-3C9F-8AC5-7F0F6047D65F”

三、symbolicatecrash

1、查找

find /Applications/Xcode.app -name symbolicatecrash -type f

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash

2、使用

export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer

./symbolicatecrash ./appName.crash ./appName.app.dSYM > customName.log

四、atos

1、使用

atos -o yourAppName.app.dSYM/Contents/Resources/DWARF/yourAppName -arch arm64/armv7 -l <load-address> <address>
或
atos -o yourAppName.app.dSYM/Contents/Resources/DWARF/yourAppName -arch arm64/armv7 <address> // 崩溃地址对应的符号表地址

二、实践

1、直接传入基地址与方法地址

atos -o liveshow.app.dSYM/Contents/Resources/DWARF/liveshow -arch arm64 -l 0x100124000 0x00000001027bd964
__55+[BLCrashGuard setupCrashGuardWithConfig:captureBlock:]_block_invoke_2 (in liveshow) (BLCrashGurad.m:0)

2、计算崩溃地址对应的符号表地址

1、从崩溃堆栈文件可知:

  1. 运行时堆栈地址(0x00000001027bd964)
  2. 运行时起始地址(0x100124000)
  3. 偏移量(40474980,转为十六进制:0x2699964)

2、符号表堆栈地址计算方式: 运行时堆栈地址 = 运行时起始地址 + 偏移量

3、根据虚拟内存偏移量不变原理 符号表堆栈地址 = 符号表起始地址 + 偏移量

知道偏移量后,只需知道符号表起始地址,即可计算出符号表堆栈地址。

可通过 otool 工具获得 __TEXT 段起始地址:

otool -l liveshow.app.dSYM/Contents/Resources/DWARF/liveshow

Load command 3
      cmd LC_SEGMENT_64
  cmdsize 1912
  segname __TEXT
   vmaddr 0x0000000100000000
   vmsize 0x0000000005bf8000
  fileoff 0
 filesize 0
  maxprot 0x00000005
 initprot 0x00000005
   nsects 23
    flags 0x0

0x0000000102699964 = 0x0000000100000000 + 0x2699964

atos -o liveshow.app.dSYM/Contents/Resources/DWARF/liveshow -arch arm64 0x0000000102699964
__55+[BLCrashGuard setupCrashGuardWithConfig:captureBlock:]_block_invoke_2 (in liveshow) (BLCrashGurad.m:0)

五、dwarfdump

1、DWARF(Debugging With Attributed Record Formats)

.xcarchive –dSYMs |–Your.app.dSYM |–Contents |–Resources |–DWARF

2、查看 dSYM 文件的 UUID:

dwarfdump --uuid Your.app.dSYM
或
dwarfdump --uuid Your.app.dSYM/Contents/Resources/DWARF/Your

3、崩溃信息还原:

dwarfdump --arch armv7 Your.app.dSYM --lookup <address> // 符号表堆栈地址
dwarfdump --arch arm64 liveshow.app.dSYM --lookup 0x0000000102699964  
liveshow.app.dSYM/Contents/Resources/DWARF/liveshow(arm64):	file format Mach-O arm64
0x0218d124: Compile Unit: length = 0x00000a63, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x0218db8b)

0x0218d12f: DW_TAG_compile_unit
              DW_AT_producer	("Apple clang version 12.0.0 (clang-1200.0.32.29)")
              DW_AT_language	(DW_LANG_ObjC)
              DW_AT_name	("/Users/Shared/Jenkins_Legacy/workspace/UNQ_liveLIVE_RELEASE_3/Pods/BLCrashGuard/BLCrashGuard/Classes/BLCrashGurad.m")
              DW_AT_LLVM_sysroot	("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.4.sdk")
              DW_AT_APPLE_sdk	("iPhoneOS14.4.sdk")
              DW_AT_stmt_list	(0x01351f66)
              DW_AT_comp_dir	("/Users/Shared/Jenkins_Legacy/workspace/UNQ_liveLIVE_RELEASE_3/Pods")
              DW_AT_APPLE_optimized	(true)
              DW_AT_APPLE_major_runtime_vers	(0x02)
              DW_AT_low_pc	(0x00000001002c1c20)
              DW_AT_high_pc	(0x00000001026999f0)

0x0218da06:   DW_TAG_subprogram
                DW_AT_low_pc	(0x0000000102699914)
                DW_AT_high_pc	(0x00000001026999f0)
                DW_AT_frame_base	(DW_OP_reg29 W29)
                DW_AT_call_all_calls	(true)
                DW_AT_linkage_name	("__55+[BLCrashGuard setupCrashGuardWithConfig:captureBlock:]_block_invoke_2")
                DW_AT_name	("__55+[BLCrashGuard setupCrashGuardWithConfig:captureBlock:]_block_invoke_2")
                DW_AT_decl_file	("/Users/Shared/Jenkins_Legacy/workspace/UNQ_liveLIVE_RELEASE_3/Pods/BLCrashGuard/BLCrashGuard/Classes/BLCrashGurad.m")
                DW_AT_decl_line	(32)
                DW_AT_prototyped	(true)
                DW_AT_APPLE_optimized	(true)
Line info: file 'BLCrashGurad.m', line 0, column 91, start line 32

六、其它常用命令行工具

1、otool

otool命令全称object file displaying tool,是针对目标文件的展示工具,可以帮助我们发现应用中使用了哪些系统库,以及调用了哪些对象的方法和属性。 常用的几个子命令如下:

otool -L path  // 查看可执行程序都链接了那些库
otool -ov path  // 输出 Object-C 类结构以及定义的方法

2、lipo

lipo 命令的作用是 create or operate on universal files,即创建或处理通用文件的工具。 常用的几个子命令如下:

lipo -info XXX // 判断静态库所支持的平台 armv7 x86_64 arm64
lipo -remove armv7 origin_xxx.a -output op_xxx.a // 删除静态库包括的 armv7 平台
lipo -thin arm64 origin_xxx.a -output op_xxx.a // 拆分静态库,只保留 arm64 CPU 架构
lipo -create device_xxx.a simulator_xxx.a -output universal_xxx.a // 对真机或者模拟器分别打出 .a 文件合并

3、nm

nm 命令的作用是显示符号表,常用的几个子命令如下:

nm path //得到Mach-O中的程序符号表
nm -nm path //目标文件的所有符号
nm -u path //Display only undefined symbols.

4、strings

strings 命令,它可以帮助我们排查二进制文件中是否包含相关字符串,常用的命令为:

strings XXX | grep yourString

5、ar

ar -t xxx.a 可以知道静态库里的 .o 文件( .a 文件是 .o 文件的合集)