关于objdump中DWARF结构体及其成员变量信息的理解验证
关于DWARF信息与结构体内存布局的理解验证
背景
我自认为已正确理解相关问题,但仅依据文档和直觉,希望资深专家能验证或纠正我的理解。我找到过一个相近的问题,但它只询问如何获取偏移的实现方式,并未解释如何解读这些信息(此外我使用的是pyelftools,与该帖子中的解决方案不同)。
示例代码与编译
示例C代码
#include <stdio.h> // hello.c struct myStruct { int myNum; char myLetter; int myNum2; }; struct badStruct { int testingNum; }; void foo() { struct badStruct bad; bad.testingNum = 17; struct myStruct s2; s2.myNum2 = 27; s2.myNum = 10; } int main() { struct myStruct s1; s1.myNum = 0; s1.myNum2 = 17; s1.myLetter = 'a'; int non_struct = 71; printf("Hello World %d %d\n", s1.myNum2, non_struct); return 0; }
编译命令
gcc -save-temps -masm=intel -gdwarf-2 -O0 hello.c -o hello.out
反汇编与DWARF信息
main函数反汇编(Intel格式,仅保留关键部分)
main: endbr64 push rbp mov rbp, rsp .cfi_def_cfa_register 6 sub rsp, 16 mov DWORD PTR -12[rbp], 0 mov DWORD PTR -4[rbp], 17 mov BYTE PTR -8[rbp], 97
关键DWARF信息(来自objdump --dwarf=info ./hello.out)
<1><71>: Abbrev Number: 5 (DW_TAG_structure_type) <72> DW_AT_name : (indirect string, offset: 0x125): myStruct <76> DW_AT_byte_size : 12 ... <2><7e>: Abbrev Number: 6 (DW_TAG_member) <7f> DW_AT_name : (indirect string, offset: 0x15d): myNum ... <8a> DW_AT_data_member_location: 2 byte block: 23 0 (DW_OP_plus_uconst: 0) <2><8d>: Abbrev Number: 6 (DW_TAG_member) <8e> DW_AT_name : (indirect string, offset: 0xc1): myLetter ... <99> DW_AT_data_member_location: 2 byte block: 23 4 (DW_OP_plus_uconst: 4) <2><9c>: Abbrev Number: 6 (DW_TAG_member) <9d> DW_AT_name : (indirect string, offset: 0x113): myNum2 ... <a8> DW_AT_data_member_location: 2 byte block: 23 8 (DW_OP_plus_uconst: 8)
核心疑问与推导
根据DWARF2文档,myStruct的DW_AT_byte_size为12,这是否意味着所有分配myStruct对象的函数,都会在栈帧中分配偏移为-12(如rbp-12)的空间?
DWARF2中DW_AT_byte_size的定义:
如果结构体、联合体或类类型的实例大小可在编译时静态确定,该类型条目会带有DW_AT_byte_size属性,其常量值为存储该类型实例所需的字节数(包含填充字节)。
而成员变量的偏移可通过DW_OP_plus_uconst获取,其定义为:
结构体成员距离结构体实例起始位置的字节数,假定基地址已在栈上。
据此推导:
myNum的地址为rbp-12 + 0即rbp-12,与汇编代码mov DWORD PTR -12[rbp], 0一致;myNum2的地址为rbp-12 + 8即rbp-4,对应汇编代码mov DWORD PTR -4[rbp], 17。
我对DWARF信息与结构体工作机制的理解是否正确?若有错误,请指出。
补充验证:foo函数的情况
foo函数反汇编(关键部分):
foo: endbr64 push rbp mov rbp, rsp mov DWORD PTR -16[rbp], 17 mov DWORD PTR -4[rbp], 27 mov DWORD PTR -12[rbp], 10
用DWARF偏移信息验证:
myNum2的地址仍为rbp-4,对应mov DWORD PTR -4[rbp], 27,即使在不同函数中也是如此。
foo中在myStruct对象上方添加了badStruct对象,其成员testingNum的偏移为rbp-16(myStruct大小12 + badStruct大小4)。对应的DWARF信息:
<1><ac>: Abbrev Number: 5 (DW_TAG_structure_type) <ad> DW_AT_name : (indirect string, offset: 0x109): badStruct <b1> DW_AT_byte_size : 4 <2><b9>: Abbrev Number: 6 (DW_TAG_member) <ba> DW_AT_name : (indirect string, offset: 0x11a): testingNum <c5> DW_AT_data_member_location: 2 byte block: 23 0 (DW_OP_plus_uconst: 0)
目前发现的小问题:需要累加各个结构体的DW_AT_byte_size来遍历栈上的结构体列表,但信息是按顺序提供的,影响不大。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

