You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 14:48:09