DWARF常见section总结

2023-12-22 19:12
文章标签 总结 常见 section dwarf

本文主要是介绍DWARF常见section总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、使用工具查看ELF中DWARF相关信息

使用objdump可以查看ELF中DWARF相关的所有section,具体操作说明如下:

objdump <option(s)> <file(s)>-W, --dwarf[a/=abbrev, A/=addr, r/=aranges, c/=cu_index, L/=decodedline,f/=frames, F/=frames-interp, g/=gdb_index, i/=info, o/=loc,m/=macro, p/=pubnames, t/=pubtypes, R/=Ranges, l/=rawline,s/=str, O/=str-offsets, u/=trace_abbrev, T/=trace_aranges,U/=trace_info]

如想查看可执行文件variable中的.debug_abbrev节的内容,可使用命令:

objdump -Wa variable
objdump --dwarf=abbrev variable

二、DWARF各个section详解

.debug_info 	#包含DWARF调试信息项(DIE)的核心DWARF数据,其类型的定义在debug_abbrev中
.debug_abbrev	#debug_info节中的所有对象的类型
.debug_aranges	#代码段的内存地址和debug_info编译单元之间的映射
.debug_frame	#调用帧信息
.debug_line		#行号程序
.debug_loc		#DW_AT_location属性中使用的位置列表
.debug_macinfo	#宏描述
.debug_pubnames	#全局对象和函数到编译单元的映射表
.debug_pubtypes	#全局类型名字到编译单元的映射表
.debug_ranges	#DW_AT_ranges属性中使用的地址范围
.debug_str		#debug_info使用的字符串表
.debug_types	#类型说明

2.1 debug_info 和 debug_abbrev

这两个节是天生在一起的两个节,它们是一个“实例和类型”的关系,也就是info节中的内容是abbrev节中的一个结构的实例。在abbrev节中声明了很多中不同的Dwarf类型组合(我们可以想象为C语言中的结构声明,而这些类型都是DWARF格式约定好的类型),然后在info节的每一项都声明自己使用的是abbrev节中的那个类型,也就是说明自己是那个结构的实例。这样两者结合就可以得到系统中的所有类型声明信息。

 # debug_info中的部分内容# <0>表示这是根DIE,<1>是<0>的一个子DIE,将其理解成树形结构# <b>表示这个这个DIE在debug_info节中的起始偏移,其他<b>也是字段或DIE的偏移# Abbrev Number: 1 表示这是abbrev节中第1个类型的一个实例,我们可以交叉到abbrev节的第1个类型声明看一下其中关于这个结构类型的声明<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)     # DW_TAG_compile_unit表示一个编译单元,一个源文件对应一个DW_TAG_compile_unit<c>   DW_AT_producer    : (indirect string, offset: 0x92): GNU C++14 12.2.0 -mtune=generic -march=x86-64 -gdwarf-2 -g -O0 -O0 -std=gnu++14 -fasynchronous-unwind-tables<10>   DW_AT_language    : 4    (C++)<11>   DW_AT_name        : (indirect string, offset: 0x50): /home/data/huangqiqi/workfile/myGDB/minidbg/examples/variable.cpp<15>   DW_AT_comp_dir    : (indirect string, offset: 0): /home/data/huangqiqi/workfile/myGDB/minidbg/build<19>   DW_AT_low_pc      : 0x1139   # variable.cpp编译程序的开始位置<21>   DW_AT_high_pc     : 0x118a   # variable.cpp编译程序的结束位置<29>   DW_AT_stmt_list   : 0<1><b4>: Abbrev Number: 9 (DW_TAG_subprogram)  # variable.cpp文件中的main函数<b5>   DW_AT_external    : 1 <b6>   DW_AT_name        : (indirect string, offset: 0x10d): main<ba>   DW_AT_decl_file   : 1    # 下面三个分别对应源文件、行、列<bb>   DW_AT_decl_line   : 3 <bc>   DW_AT_decl_column : 5 <bd>   DW_AT_type        : <0x57>   # 函数返回类型,与debug_info节<0x57>偏移处的类型一样<c1>   DW_AT_low_pc      : 0x1139   # low和high是函数编译后的开始和结束位置<c9>   DW_AT_high_pc     : 0x118a<d1>   DW_AT_frame_base  : 0 (location list)<d5>   DW_AT_GNU_all_tail_call_sites: 1<2><d6>: Abbrev Number: 10 (DW_TAG_variable)   # main函数中的变量a<d7>   DW_AT_name        : a <d9>   DW_AT_decl_file   : 1 <da>   DW_AT_decl_line   : 4 <db>   DW_AT_decl_column : 10<dc>   DW_AT_type        : <0x5e><e0>   DW_AT_location    : 2 byte block: 91 68  (DW_OP_fbreg: -24)

2.2 debug_aranges

debug_aranges段是编译单元(CU)与代码段地址之间的一个映射。借助工具理解这个段的方法:

  • objdump -d ./a.out > disass_log,反汇编代码
  • objdump -Wri ./a.out > dwarf_log,输出调试信息

dwarf_log文件中找到debug_aranges段,就可以看到如下的信息,Compilation Unit @ offsetdebug_info段中的内容。

Contents of the .debug_aranges section:Length:                   764    Version:                  2      Offset into .debug_info:  0   // debug_info中偏移0处的CU(Compilation Unit @ offset 0)地址映射Pointer Size:             8      Segment Size:             0      Address            Length 0000000000024909 000000000000033a   // 在disass_log中就可以找到地址24909处的指令,范围长度是33a
...Length:                   44     Version:                  2      Offset into .debug_info:  0x115f4 // debug_info中偏移0x115f4处的CU(Compilation Unit @ offset 0x115f4)地址映射Pointer Size:             8 Segment Size:             0Address            Length0000000000025496 000000000000017b0000000000000000 0000000000000000

2.3 debug_ranges

DW_AT_ranges属性中使用的地址范围。

2.4 debug_line

debug_line段包含了程序中的行号信息,通过读取、解析该段的内容,我们就能知道源代码行号与机器码指令地址之间的映射关系。如下是解析debug_line所得(objdump -WL ./a.out):

File name       Line number   Starting address
dwarf_test.c            8           0x1179
dwarf_test.c            12          0x1189
dwarf_test.c            13          0x11a5
dwarf_test.c            15          0x11ab

如果按照上面这种看上去很直观的方式来存储行号调试信息,那debug_line段所占用的空间将会非常大。设计者就设计了一种更节省空间的规则和方法,这样可以将调试信息中的debug_line内容压缩减少。对于调试器开发人员,他们如果想得到debug_line中源代码行号与机器码指令地址之间的映射关系,要先读取其中的内容,再按照规则和方法解析读取到的内容,最终就可以得到如上面代码段所示的内容。

至于规则和方法是如何设计的,可以查阅dwarf 4中的 6.2 Line Number Information章节。

也发现了一个关于这块的中文介绍:https://zhuanlan.zhihu.com/p/642441074,介绍的虽不太全,参考意义却挺大。

解析dwarf信息的开源项目挺多的,我比较熟悉的有delve调试器中所用的方法:delve/pkg/dwarf,还用过libelfin,但是没有阅读过其源码。

这篇关于DWARF常见section总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/525139

相关文章

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Java向kettle8.0传递参数的方式总结

《Java向kettle8.0传递参数的方式总结》介绍了如何在Kettle中传递参数到转换和作业中,包括设置全局properties、使用TransMeta和JobMeta的parameterValu... 目录1.传递参数到转换中2.传递参数到作业中总结1.传递参数到转换中1.1. 通过设置Trans的

C# Task Cancellation使用总结

《C#TaskCancellation使用总结》本文主要介绍了在使用CancellationTokenSource取消任务时的行为,以及如何使用Task的ContinueWith方法来处理任务的延... 目录C# Task Cancellation总结1、调用cancellationTokenSource.

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

二分最大匹配总结

HDU 2444  黑白染色 ,二分图判定 const int maxn = 208 ;vector<int> g[maxn] ;int n ;bool vis[maxn] ;int match[maxn] ;;int color[maxn] ;int setcolor(int u , int c){color[u] = c ;for(vector<int>::iter

整数Hash散列总结

方法:    step1  :线性探测  step2 散列   当 h(k)位置已经存储有元素的时候,依次探查(h(k)+i) mod S, i=1,2,3…,直到找到空的存储单元为止。其中,S为 数组长度。 HDU 1496   a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 。 x在 [-100,100] 解的个数  const int MaxN = 3000

状态dp总结

zoj 3631  N 个数中选若干数和(只能选一次)<=M 的最大值 const int Max_N = 38 ;int a[1<<16] , b[1<<16] , x[Max_N] , e[Max_N] ;void GetNum(int g[] , int n , int s[] , int &m){ int i , j , t ;m = 0 ;for(i = 0 ;