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

DWARF DIE变量跟踪异常求助(GDB调试报错)

编译器DWARF生成与GDB变量跟踪报错排查

问题背景

自研编译器生成DWARF DIE时遭遇变量跟踪异常:变量实际存储在汇编的-8(%rbp)位置,DWARF中DW_AT_location使用DW_OP_fbreg: -24描述,但GDB设置观察点后执行报错,提示无法访问内存地址0x1。尝试调整偏移无效,环境为GDB 15.2、gcc 14.2.1编译AT&T语法汇编、DWARF版本5。

相关DWARF信息

变量条目缩写

DW_AT_name         DW_FORM_string
DW_AT_decl_file    DW_FORM_data1
DW_AT_decl_line    DW_FORM_data1
DW_AT_decl_column  DW_FORM_data1
DW_AT_type         DW_FORM_ref4
DW_AT_location     DW_FORM_exprloc

对应debug_info内容

DW_AT_name        : x
DW_AT_decl_file   : 1
DW_AT_decl_line   : 2
DW_AT_decl_column : 24
DW_AT_type        : <0x65>
DW_AT_location    : 2 byte block: 91 68      (DW_OP_fbreg: -24)

GDB报错日志

(gdb) start
........ Not important
(gdb) watch x
Hardware watchpoint 2: x
(gdb) step
Warning:
Cannot insert breakpoint -1.
Cannot access memory at address 0x1

Command aborted.

编译器生成的汇编示例

.file "main.zu"
.text
globl main
.file 0 "main.zu"
.Ltext0:
.weak .Ltext0
.loc 0 1 6
    
.Ldie1_debug_start:
    
.type main, @function
main:
    .loc 0 1 17
    .cfi_startproc
    pushq %rbp
    .cfi_def_cfa_offset 16
    movq %rsp, %rbp
    .cfi_def_cfa_register 6
    .loc 0 1 26
    # Variable declaration for 'stinky'
    movq $415, -8(%rbp)
    # End of variable declaration for 'stinky'
    movq $913, -8(%rbp)
    movq $69, %rdi
    movq $60, %rax
    syscall # SYS_EXIT
    ret
    .Ldie1_debug_end:
.cfi_endproc
.size main, .-main
    .Ldebug_text0:
.section    .debug_info,"",@progbits
    
.long .Ldebug_end - .Ldebug_info
.Ldebug_info:
.weak .Ldebug_info
.word 0x5
.byte 0x1
.byte 0x8
.long .Ldebug_abbrev

.uleb128 1
.long .Ldebug_producer_string
.byte 0x8042
.long .Ldebug_file_string
.long .Ldebug_file_dir
.quad .Ltext0
.quad .Ldebug_text0 - .Ltext0
.long .Ldebug_line0
.uleb128 2
.long .Ldie1_string
.byte 0
.byte 1
.byte 17
.long .Lint_debug_type
.quad .Ldie1_debug_start
.quad .Ldie1_debug_end - .Ldie1_debug_start
.uleb128 0x01
.byte 0x9c
.uleb128 7
.long .Ldie2_string
.byte 0
.byte 2
.byte 7
.long .Lint_debug_type
.uleb128 0x02
.byte 0x91
.sleb128 -24
.byte 0

.Lint_debug_type:
.uleb128 8
.byte 8
.byte 5
.string "int"
.Lfloat_debug_type:
.uleb128 8
.byte 4
.byte 4
.string "float"
.Lstr_debug_type:
.uleb128 9
.byte 8
.long .Lchar_debug_type
.Lchar_debug_type:
.uleb128 8
.byte 1
.byte 6
.string "char"

.byte 0
.Ldebug_end:
.section .debug_abbrev,"",@progbits
.Ldebug_abbrev:

.uleb128 1
.uleb128 0x11 # TAG_compile_unit
.byte   0x1 # No children
.uleb128 0x25 # AT_producer
.uleb128 0xe # FORM_strp
.uleb128 0x13 # AT_language
.uleb128 0xb # FORM_data1
.uleb128 0x3 # AT_name
.uleb128 0x1f # FORM_line_strp
.uleb128 0x1b # AT_comp_dir
.uleb128 0x1f # FORM_line_strp
.uleb128 0x11 # AT_low_pc
.uleb128 0x1 # FORM_addr
.uleb128 0x12 # AT_high_pc
.uleb128 0x7 # FORM_data8
.uleb128 0x10 # AT_stmt_list
.uleb128 0x17 # FORM_sec_offset
.byte 0
.byte 0

.uleb128 2
.uleb128 0x2e # TAG_subprogram - FunctionNoParams, non-void
.byte 0x1 # Has children
.uleb128 0x3f # AT_external
.uleb128 0x19 # FORM_flag_present
.uleb128 0x3 # AT_name
.uleb128 0xe # FORM_strp
.uleb128 0x3a # AT_decl_file
.uleb128 0xb # FORM_data1
.uleb128 0x3b # AT_decl_line
.uleb128 0xb # FORM_data1
.uleb128 0x39 # AT_decl_column
.uleb128 0xb # FORM_data1
.uleb128 0x49 # AT_type
.uleb128 0x13 # FORM_ref4
.uleb128 0x11 # AT_low_pc
.uleb128 0x1 # FORM_addr
.uleb128 0x12 # AT_high_pc
.uleb128 0x7 # FORM_data8
.uleb128 0x40 # AT_frame_base
.uleb128 0x18 # FORM_exprloc
.uleb128 0x7a # AT_call_all_calls
.uleb128 0x19 # FORM_flag_present

.byte 0
.byte 0

.uleb128 7
.uleb128 0x34 # TAG_variable
.byte 0 # No children
.uleb128 0x3 # AT_name
.uleb128 0xe # FORM_strp
.uleb128 0x3a # AT_decl_file
.uleb128 0xb # FORM_data1
.uleb128 0x3b # AT_decl_line
.uleb128 0xb # FORM_data1
.uleb128 0x39 # AT_decl_column
.uleb128 0xb # FORM_data1
.uleb128 0x49 # AT_type
.uleb128 0x13 # FORM_ref4
.uleb128 0x2 # AT_location
.uleb128 0x18 # FORM_exprloc

.byte 0
.byte 0

.uleb128 8
.uleb128 0x24 # TAG_base_type
.byte   0 # no children
.uleb128 0xb # AT_byte_size
.uleb128 0xb # FORM_data1
.uleb128 0x3e # AT_encoding
.uleb128 0xb # FORM_data1
.uleb128 0x3 # AT_name
.uleb128 0x8 # FORM_string

.byte 0
.byte 0

.uleb128 9
.uleb128 0xF # TAG_pointer_type
.byte 0 # No children
.uleb128 0xB # AT_byte_size
.uleb128 0xb # FORM_data1
.uleb128 0x49 #  AT_type
.uleb128 0x13 #  FORM_ref4
.byte 0
.byte 0
.byte 0
.byte 0
.section .debug_aranges,"",@progbits
.Ldebug_aranges:
.long .Ldebug_aranges_end - 4 - .Ldebug_aranges
.value 0x5
.long .Ldebug_text0
.byte 0x8
.byte 0x0
.value 0
.value 0
.quad .Ltext0
.quad .Ldebug_text0-.Ltext0
.quad 0
.quad 0
.Ldebug_aranges_end:
.section .debug_line,"",@progbits
.Ldebug_line0:
.section .debug_str,"MS",@progbits,1
.Ldebug_producer_string: .string "Zura compiler v0.1.25"
.Ldie1_string: .string "main"

.Ldie2_string:
    .string "stinky"

.section .debug_line_str,"MS",@progbits,1
.Ldebug_file_string: .string "main.zu"
.Ldebug_file_dir: .string "zura_files"

排查方向

  1. 帧基地址定义错误
    当前TAG_subprogram的AT_frame_base使用0x9c(对应DW_OP_call_frame_cfa),但x86-64下函数帧基地址应绑定到rbp,正确表达式应为DW_OP_breg6, 0(即rbp+0)。DW_OP_fbreg的偏移是相对于帧基地址计算的,若帧基地址与实际栈布局不匹配,会直接导致变量地址计算错误。

  2. 偏移值逻辑错误
    变量实际存储在-8(%rbp),若帧基地址设为rbp,DW_OP_fbreg的偏移应直接写-8而非-24。C语言中用-16偏移是因为其帧基地址绑定到CFA(rsp+16),计算后得到-8(%rbp),但你的帧基地址规则与C语言不一致,不能直接套用该偏移。

  3. 函数地址范围异常
    TAG_subprogram的AT_low_pc指向.Ldie1_debug_start(位于main:标签之前),导致函数地址范围包含了函数定义前的无关代码,可能让GDB误解变量的有效作用域,应将.Ldie1_debug_start移至main:标签之后、.cfi_startproc之前。

  4. DWARF条目嵌套与作用域
    确认TAG_variable是否正确嵌套在对应TAG_subprogram的子节点下,且变量的生命周期与代码范围匹配,避免GDB在变量未生效的阶段尝试访问其地址。


内容的提问来源于stack exchange,提问作者Connor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 08:57:05