符号化的原理

502 阅读3分钟

一、 符号化流程以及地址之间的关系

符号化流程第一步:从内存地址回溯到文件(macho文件中的地址) 第二步:还原运行时调试信息

  • 第一步的关键在于回溯到macho文件,找到对应的地址(这个好理解)
  • 第二步关键,如何根据macho文件的地址,找到对应的符号

地址间的关系如下:

运行时候的image地址 = macho文件中的image地址 + aslr

运行时候的函数地址 = macho文件中函数的地址(函数地址=所在image + offset) + aslr

ASLR Slide + Linker address = Load address

其中:运行时候的image地址可以从crash文件中获得 Binary Images,macho文件中的image地址可以通过dsym获得

二、 举例感受如何符号化的

崩溃地址:0x000000010a107eb4(运行时候的函数符号地址) xxxxx + 3764,(前大后小)

第一步:回溯到文件,得到0x100000EB4(文件地址)

  1. macho文件中的函数符号地址=0x000000010a107eb4 - ALSR:算出ALSR即可

  2. 计算ALSR如下(原理:运行的image地址 - macho文件中image地址):

运行的image地址:敲出image list命令,0x000000010a107000 或者 crash文件中的image地址。

macho文件中image地址:查看dsym文件,0x0000000100000000 (objdump --macho --private-headers)

根据ASLR = 0x000000010a107eb4 - 0x0000000100000000 = 0x00000000a107000

  1. 编译出来的函数符号地址=0x000000010a107eb4 - 0x00000000a107000 = 0x100000EB4(文件地址)

第二步:还原信息,得到函数名称

  1. dwarfdump --lookup 0x100000EB4 得到:"-[ViewController warfTest]"

三、 符号化原理,即dwarfdump --lookup 0xxxxx 如何找到符号

debuf-info 比如再举个例子:崩溃文件链接地址=0x52846

1.解析debuginfo:

$ dwarfdump -e --debug-info YourPath/YourApp.dSYM/Contents/Resources/DWARF > info-e.txt ,0x52846确定在哪个文件和函数中,在showOilPricePickerView函数中

`0x00062112:     ``function` `[99] *`

`                ``low pc( 0x000502e0 )`

`                ``high pc( 0x00053730 )`

`                ``frame base( r7 )`

`                ``object pointer( {0x0006212a} )`

`                ``name( ``"-[OBDFirstConnectViewController showOilPricePickerView]"` `)`

`                ``decl file( ``"/YourSourcePath/OBDFirstConnectViewController.m"` `)`

`                ``decl line( 870 )`

`                ``prototyped( 0x01 )`

`                ``APPLE instruction set architecture( 0x01 )`

2.解析debug_line:$ dwarfdump -e --debug-line YourPath/YourApp.dSYM/Contents/Resources/DWARF > line-e.txt ,知道在哪一行,可以看到0x52846在882行

0x00000000000502e0    870 /YourSourcePath/OBDFirstConnectViewController.m
`0x0000000000052812    880`

`0x000000000005283e    881`

`0x0000000000052846    882`

`0x00000000000528c8    883`

四、知识点

1)strip style三种
  • all symbols:剥离所有符号
  • Non Global:剥离非全局符号
  • Debugging Symbols:移除debug nlist符号,保留直接符号
2)调试信息类型
  • function starts(缺方法名)
  • nlist(有名缺行)
struct nlist_64{
    uint8_t n_type:告诉我们类型,是不是直接符号
}
  • DWARF
3) DWARF详解:

相较于地址、函数名,多了关系信息。三个数据流:debug_info,debug_abbrev,debug_line

debug_info 包含了原始数据:文件名、类型、地址范围

debug_abbrev 为原始数据进行了结构化处理:解释debug_info各个字段意义

debug_line 包含了文件名和行号:关键点,它定义了一个行表程序,可以让文件地址映射到源码文件中的具体行数

每个 swift 文件都会有一个编译单元

总结: 1.DWARF 一个编译单元,包含N个子程序(文件内定义的各个函数),子程序包含地址范围。通过debug-info得到 2.查找流程:遍历编译单元,遍历子节点(子程序)

后续仔细体会

可以