我的编译器正在编写 DWARF DIE,我目前遇到跟踪变量的问题。 例如,缩写看起来像:
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)
C 向该位置添加 -16 的偏移量,该位置在程序集中应为 -8(%rbp)。 在我的语言中,变量也存储在 -8(%rbp) 上,偏移量也为 -24。 除了 FORM_string 是 FORM_strp(我认为这在实际调试过程中没有区别)之外,我看不到任何其他差异。 为什么我的语言在使用 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.
我尝试删除-16偏移量,但无济于事。 注意:GDB版本15.2,使用gcc 14.2.1编译AT&T语法汇编。 DWARF 版本 5.
这是编译器生成的 asm 的示例
.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"
您忘记提供构建说明。仅当代码not链接到libc,而是
main
是进程入口点时,我才能重现该问题。在这种情况下,堆栈最上面的项目将是 argv
。当为局部变量添加观察点时,gdb 还会插入一个内部断点(我相信可以检测是否离开框架)。展开器使用堆栈最顶层的项作为断点的地址,假设这是返回地址。然而,在这种情况下,如果不使用命令行参数,则为 argv
,即 1
。这就是 Cannot access memory at address 0x1
错误的来源。您可以通过传递一个参数来验证这一点,其中您应该看到更改为 0x2
(或者无论您传递多少个参数 + 1)。如果您与 libc 链接,那将 call
您的 main
,因此堆栈上将有一个正确的返回地址,并且 gdb 不会被混淆:
Hardware watchpoint 2: stinky
Old value = 0
New value = 415