前语
不知道咱们有没有用过bugly,bugly供给了一种从dSYM文件中抽取轻量符号表的功用,生成的符号表更加细巧,并且保留了地址和符号的映射联络,日志解析后仍然能够精确到行号。
可读符号表解压翻开后如下:
Symbol table:
5ef0 5f00 viewDidLoad ViewController.swift:10
5f00 5f18 viewDidLoad ViewController.swi汇编指令表ft:0
5f18 5f2c viewDidLoad ViewController.sw汇编指令incift:11
5f2c 5f48 viewDidLoad ViewController.swift:11
5f48 5f4c viewDidLoad ViewCongithubtroller.swift:0
5f4c 5f68 viewDidLoad ViewControll汇编指令leaer.swift:11
笔者在2018年做技能项目时第一次触摸DWARF文件,当时做了简略的调研后没有持续在深入研究。直到今年才开始考虑bugly供给的buglySymboliOS.jar到底是怎样作业的。前段时间对DWARF做了一些调研,发现尽汇编指令inc管相关文章许多,可是同质附近的内容较多,且大多数停留在概念介绍上,实在操刀实战的文章少之又少。因而,笔者抽出部分时间将这段时间遇到的问题以宫颈癌及处理方式收拾总结成文章,供感兴趣的人参考。
什么是DWARF文件
首要来介绍下什么是DWARF文件,DWARF(”Debug二进制ging With Attrios14.4.2值得更新吗ibuted RecordFormats”)是记载运用的调试信息的文件,现在最新版本是V5。在iOS中,咱们将Build Settings -> Deb汇编指令incug Information Format
修改为DWARF Wigithub敞开私库th dSYM File
即可将调试信息从可执行文件中剥离到dSYM文件中。一旦可执行文件被剥离了DWARF文件,那么原则上可执行文件中内部ios下载的符号地址映射就不存在了(这儿需求注意下,近giti轮胎是什么品牌期发ios是什么意思现假定咱们本地修改为release编译虽然能生成dSYM文件,可是可执行文件中仍旧保留了符号表,假定有相关实验不要被此误导)。虽然咱们能够经过OC的存储特性来恢复这种映射联络,可是这现已脱离了DWARF的规划汇编指令了。
DWARF简介
介绍DWARF的文章非常多,概念和用处都介绍的非常详尽。咱们能够随意查找D汇编指令WARF等关键字了解相关内容,笔者在这儿不想摘抄相关内容。经过MachOView翻开DWARF后会发现其外层仍旧是Mach-O格局。其间debug_汇编指令info这个s枸杞ection中存储了首要的调试gitee信息。汇编指令test咱们Git能够经过dwarfdump指令来了解下其间存储的内容。
dwarfdump --debug-infiOSo xxxx.app.dSYM/Contents/Resources/DWAR汇编指令详解F/xxxx
在输入demo产生的DWARF文件其打印片段如下:
0x0008ec6f: DW_TAG_subprogram
DW_AT_low_pc (0x000000010000b4b8)
DW_AT_high_p二进制转八进制c (0x000000010000b6ac)
DW_AT_frame_base (DW_OP_reg29 W29)
DW_AT_object_pointer (0x0008ec8d)
DW_AT_name ("+[WBOCTest ggiteeeios14桌面布局图片tTypeName:]")
DW_AT_decl_file ("/Users/a58/SwiftVTHook/SwifGittDemo/SwiftDemo/WBOCTest.m")
DW_AT_decl_line (199)
DW_AT_prototyped (true)
DW_AT_type (0x0008f1a3 "NSSios系统tring*")
0x0008ec8d: DW_TAG_二进制转十进制计算器formal_parameter
DW_AT_location (DW_OP_fbreg -宫颈癌疫苗24)
DW_AT_name ("self")
DW_AT_type (0x0008f1cc "const Class")
DW_A二进制亡者列车T_artifi汇编指令leacial汇编指令cmp (true)
0x0008ec9a: DW_TAG_formal_pios下载arameter
DW_AT_location (DW_OP_fbreg -3汇编指令详解2)
DW_AT_name ("_c公积金md")
DW_AT_type (0x0008e2d3 "SEL")
DW_AT_artificial (true)
0x0008eca7: DW_TAG_formal_parameter
DW_AT_location (DW_OP_fbreg -40)
DW_AT_name ("typeOffsios模拟器et")
DW_AT_decl_file ("/Users/a58/SwiftVTHook/SwiftDemo/SwiftDemo/WBOCTest.m")
DW_AT_decl_line (199Git)
DW_AT_type (0x000000000000101f "uintptr_t汇编指令lea")
0x0008ecb6: DW_T汇编指令大全AG_vargoogleiable
DW_AT_location (DW_OP_fb二进制亡者列车reg -48)
DW_二进制转化为十进制AT_nam二进制e ("linkedit枸杞")
DW_AT_decl_file ("/Users/a58/SwiftVTHook/SwiftDemo/SwiftDemo/WBOCTest.m")
DW_AT_decl_line (201)
DW_AT_type (0x0008f1d1 "const seg公积金ment_command_64*")
0x0008eccgitee5: DW_TAG_variable
DW_AT_loc宫颈癌ation (DW_OP_fbreg -56)
DW_AT_name ("linkBase")
DW_AT_decl_file ("/Users/a58/SwiftVTHook狗狗币/SwiftDemo/SwiftDemo/WBOCTest.m")
DW_AT_decl_line (203)
DW_AT_ty汇编指令cldpe (0x000000000000101f "uint汇编指令集ptr_t")
0x0008ecd4狗狗币: DW_TAG_variagithub永久回家地址ble
DW_AT_location (DW_O龚俊P_fbreg -64)giti轮胎是什么品牌
DW_ATios14桌面布局图片_name ("exeHeader")
DW_AT_decl_filios退款e ("/Users/a58/SwiftVTHook/SwiftDemo/SwiftDemo/WBOCTest.m")
DW_AT_decl_line (204)
DW_AT_type (0x000000000000101f "uintptr_t")
0x0008宫颈癌疫苗ece3: DW_TAG_variable
DW_AT_location (DW龚俊_OP_fbreg -72)
DW汇编指令cmp_AT_name ("typeAddress")
DW_AT_decl_file ("/Users/a58/SwiftVTHook/SwiftDemo/SwiftDemo/WBOCTest.m")
DW_AT_decl_line (205)
DW_AT_type (0x000000000000101f "uintptr_t")
以上是dwarfdump指令帮咱们提取并格局化输出的信息,便于咱们理解。debug_info中的数据是树形ios退款结构存储的。首要咱们需求先了解几个名词,这几个名词也是在文章和工商银行本文所介绍的l龚俊ibdwarf开源库中常常提及到的概念。
- DIE
调试信息项(Debgithub永久回家地址ugging InformationEntry——DIE),在上文github永久回家地址打印的信息中DW_TAG_subprogram
DW_TAG_variable
等都能够称为一个DIE。宫颈癌前期症状一般来说”DW_汇编指令movTAG_*”开端的都是一个DIE,DIE作为树的节点,互相或许存在父子兄弟联络。在上文中打印片段中,DW_TAG_subprogram
就Git包二进制亡者列车含多个DW_TAG_formal_parameter
以及多个DW_TAG_v二进制亡者列车ariable
子节点。
- Attribute
望文生义-特征,作为DIE的描绘信息。例如
DW_TAG_subprogram
DW_AT_lgithub敞开私库ow_pc (0x000000010000b4b8)
DW_AT_high_pc (0x000000010000b6ac)
DW_AT_frame_base (DW_OP_reg29 W29)
DW_AT_obios模拟器ject_pointer (0x0008ec8d)
DW_AT_name ("+[WBOCTest getTypeName:]")
DW_AT_decl_file ("/Users/a58/SwiftVTHook/SwiftDemo/SwiftDemo/WBOCTest.m")
DW_AT_decl_line (199)
DW_AT_prototyped (true)
DW_AT_type (0x0008f1a3 "NSSt二进制转化器ring*")
代表的便是DW_TAG_汇编指令testsubprogram
这个DIE有DW_AT_low_pc
DW_AT_high_pc
DW_AT_fr二进制转十六进制公式ame_base
等特征。其间DW_AT_lgitlabow_pc
代表这个DIE的开始地址,DW_AT_high_pc
代表这iOS个DIE的结束地址,地址前闭后开[)。DW_AT_decl_file
代表这个函数所处的文件。DW_AT_decl_line
代表这个函数gitlab从哪一行开始界说。
- CU
编译单元,一般来说一个文件便是一个编译单元。
- subprogram
子程序,一般指咱们在文件中编写的函数方法等。
- variable
变量界说
那debug_info在文件中是怎样存储的git命令呢?首要咱们来看个图片。
因为画图东西的束缚没有列出每个字节对应的格局化输出。在二进制中debug_info中存储的是连续的不定长的带有层级的数据。这儿的解析libdwarf帮咱们做了解析,否则这是一个很大的作业量。
怎样提取轻量符号表
提取轻量符号表便是确定每个文件每个函数每一行代码的汇编指令区间。开源库libdwarf供给了解析DWARF的才华。
考虑进程,
- 符号地址映射
经过MachOView咱们能清楚的看到,DWARFgithub永久回家地址文件中二进制转八进制保存了符号表结构(Symboios14.4.1更新了什么l Table)。因而笔者开端的主意二进制转化器是经过Symbol Table来结束提取轻量符号表。可是有个很实际的问题摆在面前,在Symbol Table中只存储了函数和地址的映射,并没有行号信息。也就git命令是说Symbol Table无法精确到行等级的指令区别。因而bugly必定不是这样处理的。
- 怎样精确到行号?
从上文打印的debug_info信二进制转八进制息片段中,咱们能够看出DW_TAG汇编指令test_subprogram
以及部分子节点都存在DW_AT_de汇编指令incc汇编指令大全l_line
或者 DW_AT_call_line
的特征。抱负情ios14.4.2值得更新吗况下,假定一棵树每个节点都存在行号特征和地址规划,那是不是意味着咱们能知道每个函数的每一行的指令区间了?但实践上必定不是这么简略的,由giti轮胎是什么品牌于在实践后就会发现许多的DW_TAG_variable
没有提取出地址区间。假定存在如下代码
BOOL hasVtable = [self hasVTab二进制怎样算le:baseType];
那么debug_info中只存储了变量界说DW_TAG_variable
这个DIE,在DW_TAG_variable
的DW_AT_location
中记载github的是当时这个变量位于哪个寄存器的偏移方位。没有找到这一行代码二进制转化为十进制的指令区间。因而需求换一种方式来考虑问题了。
- 山穷水尽—github敞开私库—linegithub永久回家地址
在DWARF文件中,能够看到存在一个debug_line的section,这儿存储的是行信息。因而查验dump看下行信息都包括哪些内容。
dwarfdump --debug-line xxxo.app.dSYM/Conios14.4.2值得更新吗tents/Regithub永久回家地址sources/DWARF/xxx
打印片段如下:
include_directories[ 1] = "SwiftDemo"
file_names[ 1]:
name: "SwgiteeiftMethodTableModel.h"
dir_index: 1
mod_time: 0x00000000
length: 0x00000000
file_names[ 2]:
name:汇编指令inc "SwiftMethodTableModel.m"
dir_index: 1
mod_汇编指令详解time: 0x00000000
length: 0x00000000
Address Line Column File ISA Discriminator F公积金贷款lgoogleags
------------------ ------ ---ios14桌面布局图片--- ------ --google- ------------- -------------
0x000000010000bbac 15 0 1 0 0 is_stmt
0x000000010000bbb8 15 35 1 0 0 is_stmt prol二进制八进制十进制十六进制转化ogue_end
0x000000010000bbd0 15 0 1 0 0 is_stmt
0x000000010000bbe8 15 35 1 0 0 is_stmt prologue_end
0x000000010000bc08 17 0 1 0 0 is_stmt
0x000000010000bc14 17 37 1 0 0 is_stmt p汇编指令大全rologue_end
0x000000010000bc24 17 0 1 0 0 is_stm汇编指令详解t
0x000000010000bc34 17 37 1 0 0 is_stmt prologue_end
0x000000010000bc48 19 0 1 0 0 is_stmt
0x000000010000bc54 19 37 1 0 0 is_stmt prolgit教程ogue_end
0x000000010000bc64 19 0 1 0 0 is_stmt
0x000000010000bc74 19 37 1 0 0 is_stmt prologue_end
0x000000010000bc88 21 0 1 0 0 is_stmt
0x000000010000bc94 21 37 1 0 0 is_stmt prologue_e二进制怎样算nd
0x000000010000bca4 21 0 1 0 0 is_stmt
0x000000010000bcb4二进制计算器 21 37 1 0 0 is_stmt prologue_end
0x000000010000bcc8 10 0 2 0 0 is_stmt
0x000000010000bcdc 10 1二进制怎样算7 2 0 0 is_stmt prologue_end
0x000000010000bcf8 28 0 1 0 0 is_stgitlabmt
0x000000010000bd04 28 35 1 0 0 is_stmt prologue_end
0x000000010000bd1c 28 0 1 0 0 is_stmt
0x000000010000bd34 28 35 1 0 0 is_stmt prologue_end
0x000000010000bd54 30 0 1 0 0 is_stmt
0x000000010000bd60 30 35 1 0 0 is_stmt prologue_end
0x000000010000bd78 30 0 1 0 0 is_stmt
0x000000010000bd90 30 35 1 0 0 is_stmt prologu二进制怎样算e_enGod
0x000000010000bdb0 14 0 2 0 0 is_s工商银行tmt
0x000000010000bdc8 14 17汇编指令集 2 0 0 is_stmt prologue_end
0x000000010000bdf4 14 17 2 0 0 is_stmt end_sequence
从打印片段中,咱们很简单就能看出每个文件的每一行代码都存储github中文官网网页了开始地址以及行号。也便是说到这一步,我google们能够提取出开始地址、行号、文件名。回想下bugly的轻量符号表
Symbol table:
5ef0 5f00 viewDidLoadgit教程 ViewController.swift:10
咱们短少函数名信息。到这一步就比较利益理了,回想下上文,咱们经过DW_TAG_subprogram
能够获取到这个函数的文件名、函数名、函数开始地址、函数停止地址。因而获取到行信息后,能够检giti查当时这个行的开始地址位于同文件github下那个函数的指令区间内,即可得汇编指令cld知函数名。
遇到的坑
1、数据获取失利
有时获取地址经过Godwgithub敞开私库arf_formaddr函数并不能获取到数据ios14桌面布局图片,假定失利需求查验dwarf_formudata、dwarf_formsdata等函数。
res = dwarf_formaddr(attr,&uval,errp);
if(res == DW_DLV_OK) {
*val = uval;
return;
}
res = dwarf_formudata(attr, &uval, errp);giti
if(res == DW_DLV_OK) {
*val = uval;
return;
}
Dwarf_Signed sival = 0;
res = dwarf_formsdata(attr, &sival, errp);
if(res == DW_DLV_OK) {github中文官网网页
*va二进制怎样算l = siva宫颈癌疫苗l;
return;
}
2、DW二进制转化器_AT_high_pc
实践发现DW_AT_high_pc
中存储的并不是结束地址,而是当时这个DIE的地址长度,即size。
3、dwarf_line_s汇编指令rcfileno
从函数名来看,似乎是获取该行的文件编汇编指令test号,可是实践调用上会发现调用报错。libdwarf相似的状况还许多,常常函ios14.4.2值得更新吗数调用报错可是却短少错误信息,这对开发和调试来说很不便当。
总结及展望
初见debug汇编指令cld_in汇编指令大全fo的宫颈癌疫苗存储有点像二进制转化器AST的感觉,从DWARF文件中咱们也能找出源码中的蛛丝马迹,甚至能依据DWARF恢复出源码中的部分内容。例如变量界说,在DWARF文件中变量的名字、变量的类型都有介绍,形参类型等也有介绍。那么是不是某些依据抽象语法树二进制八进制十进制十六进制转化的技能方案能够考虑能否用宫颈癌疫苗DWARF解析来结束呢?
下篇文章介绍
《怎样经过Mach-O扫描S二进制转八进制wift无用代码》
之前在简书平台上介绍过《从Mach-O视点谈谈Swift和OC的存储差异》和《一种Swift Hook新思路——从Swift的虚汇编指令cld函数表说起》,经过Macgithub永久回家地址h-O扫描OC无用类方案或许咱们现已很熟悉了,可是Swift类假定调用的话并没有放到classref这个section中,那怎样辨认一个Swift类被调用呢?
作者简书:www.jianshu.com/u/739b67792…
参考文献
github.com/avast/lib二进制八进制十进制十六进制转化d二进制计算器w…
blog.csdn.net/wuhui_gdnt/ios是什么意思…
gohalo.me/post/progra…
stackoverflow.com/questions/9…
stackoverflow.com/questions/4…