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

相关文章

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

C++ vector的常见用法超详细讲解

《C++vector的常见用法超详细讲解》:本文主要介绍C++vector的常见用法,包括C++中vector容器的定义、初始化方法、访问元素、常用函数及其时间复杂度,通过代码介绍的非常详细,... 目录1、vector的定义2、vector常用初始化方法1、使编程用花括号直接赋值2、使用圆括号赋值3、ve

Pytest多环境切换的常见方法介绍

《Pytest多环境切换的常见方法介绍》Pytest作为自动化测试的主力框架,如何实现本地、测试、预发、生产环境的灵活切换,本文总结了通过pytest框架实现自由环境切换的几种方法,大家可以根据需要进... 目录1.pytest-base-url2.hooks函数3.yml和fixture结论你是否也遇到过

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

java常见报错及解决方案总结

《java常见报错及解决方案总结》:本文主要介绍Java编程中常见错误类型及示例,包括语法错误、空指针异常、数组下标越界、类型转换异常、文件未找到异常、除以零异常、非法线程操作异常、方法未定义异常... 目录1. 语法错误 (Syntax Errors)示例 1:解决方案:2. 空指针异常 (NullPoi

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

Java反转字符串的五种方法总结

《Java反转字符串的五种方法总结》:本文主要介绍五种在Java中反转字符串的方法,包括使用StringBuilder的reverse()方法、字符数组、自定义StringBuilder方法、直接... 目录前言方法一:使用StringBuilder的reverse()方法方法二:使用字符数组方法三:使用自

MySQL常见的存储引擎和区别说明

《MySQL常见的存储引擎和区别说明》MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根... 目录mysql常见的存储引擎和区别说明1. InnoDB2. MyISAM3. MEMORY4. A