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

GDB中until *<addr>报内存错误但tbreak *<addr>正常的原因排查

GDB until * 在纯汇编无标准库二进制中解析地址错误,是否为bug?

现象总结

调试通过gcc -nostdlib编译、以_start为入口的纯汇编x86_64二进制时,使用until *<十六进制地址>命令会触发「Cannot access memory at address 0x1」的错误,导致命令中止;但使用break或tbreak *<相同地址>却能正确设置断点并执行。而在C编译的常规二进制中,until *<addr>命令可正常工作。

使用GDB 17.2测试,根据官方手册说明,until与break命令接受相同参数,但实际行为存在明显差异。

复现示例

汇编源码

.intel_syntax noprefix
.global _start

.section .data
message:
    .ascii "hello, world!\n"

.section .text
_start:
    mov rax, 1        # syscall: write
    mov rdi, 1        # fd: stdout
    lea rsi, [rip + message]
    mov rdx, 14       # length
    syscall

    mov rax, 60       # syscall: exit
    xor rdi, rdi      # status: 0
    syscall

GDB操作日志

❯ gdb --version 
GNU gdb (GDB) 17.2
(No debugging symbols found in ./hello)
(gdb) b _start
Breakpoint 1 at 0x401000
(gdb) r
Starting program: /home/rivon0507/low-level/hello-world/hello 

Enable debuginfod for this session? (y or [n]) 
Debuginfod has been disabled.

Breakpoint 1, 0x0000000000401000 in _start ()
(gdb) until *0x40100a
❌ Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x1

❌ Command aborted.
(gdb) tbreak *0x40100a
Temporary breakpoint 2 at 0x40100a
(gdb) c
Continuing.

Temporary breakpoint 2, 0x000000000040100a in _start ()

调试日志细节(开启表达式与断点调试)

(gdb) set debug expression 1
(gdb) set debug breakpoint 1
(gdb) until *0x40100a
Operation: OP_LONG
 Type: int
 Constant: 4198410
Operation: OP_LONG
 Type: int
 Constant: 4198410
[breakpoint] update_global_location_list: insert_mode = UGLL_MAY_INSERT
[breakpoint] update_global_location_list: insert_mode = UGLL_MAY_INSERT
[breakpoint] update_global_location_list: insert_mode = UGLL_INSERT
[breakpoint] insert_bp_location: Breakpoint 0 (0x55c4b4afda30) at address 0x1
[breakpoint] insert_bp_location: Breakpoint 1 (0x55c4b4b299f0) at address 0x401000 <_start>
[breakpoint] insert_bp_location: Breakpoint 0 (0x55c4b4bcaae0) at address 0x40100a <_start+10>
❌ Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x1

❌ Command aborted.

原因分析

从调试日志可以看出,until命令执行时,除了在用户指定的0x40100a地址正确设置断点外,还额外尝试在无效地址0x1插入断点,这是导致错误的直接原因。

until命令的设计逻辑包含自动辅助断点(比如函数返回处),用于实现「执行到指定位置或函数结束」的功能。但在无标准运行时库、无调试符号且入口为_start的纯汇编二进制中,GDB的函数边界检测逻辑出现错误,误将某个值识别为返回地址或其他需要断点的位置,从而生成了无效的0x1地址。

而break/tbreak仅处理用户明确指定的地址,没有额外的自动断点逻辑,因此不受此问题影响。C编译的二进制因包含标准运行时,GDB能正确识别函数结构,辅助断点逻辑不会出错。

结论

这是GDB的bug。根据官方文档,until命令应与break接受相同参数并一致处理,但实际在特定场景下,其内部的辅助断点逻辑错误生成无效地址,导致命令失败。用户明确指定地址时,until应优先尊重用户输入,而非因错误的自动断点逻辑中止命令。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.07 05:13:11