【问题标题】:QEMU GDB step-instruction advances over multiple instructionsQEMU GDB 步进指令在多条指令上前进
【发布时间】:2020-06-03 20:06:03
【问题描述】:

我在 arm64 QEMU 实例上运行了一些非常简单的裸机汇编代码。通过 QEMU 调试端口使用 GDB 进行调试时,单步 (stepi) 是在指令上前进,而不是在每行汇编中前进。该模式似乎是它直接前进到下一个分支指令或分支目标。正在推进的代码肯定会在寄存器副作用可见时执行。

例如,以下代码在单步执行 (stepi) 时仅在以下突出显示的行上停止,这些行是分支或分支目标,但是 x2 明显递增:

    ldr x0, =0x08000000
    ldr x3, =-1

loop:
    ldxr x2, [x0]          <<< GDB "stepi" stops here
    add x2, x2, #1         <<< skipped
    stxr w3, x2, [x0]      <<< skipped
    b trampoline           <<< GDB "stepi" stops here
    nop

trampoline:
    b loop                 <<< GDB "stepi" stops here

这听起来像是 .elf 文件中缺少/不完整的调试信息,但我已经尝试了我知道的每个 gcc/as -g 选项。在用户空间应用程序上本地运行 GDB 时,我没有遇到过这种行为,所以想知道这是否是 QEMU 的奇怪之处。

【问题讨论】:

  • 是的,而不是“像 .elf 文件中缺少/不完整的调试信息”,它闻起来像 QEMU 中的错误,因为机器指令不需要调试信息踩踏。也许How to single step ARM assembly in GDB on QEMU?有答案
  • 您使用的是哪个版本的 QEMU?您可以尝试使用最新的,看看它是否是已修复的错误。

标签: gcc gdb qemu arm64


【解决方案1】:

不是qemu的错误,gdb是故意的。

ldrx ... strx 是一个原子内存访问监视器操作(详细信息请阅读 ARM 程序集)。 如果 gdb 像往常一样单步执行这些指令(gdb 在后台,使用存储操作设置断点 INSTR,然后恢复原始指令 - 另一个存储操作),那么硬件将断言 ldrx .../strx 原子加载并且存储没有实现,由于某个地方(即调试器),同时进行了另一个存储操作。

如果汇编代码然后检查 strx 相对于 ldrx 是否真的是原子的,如果不是则重试(您的代码不会这样做,但通常在软件中完成),那么硬件将永远不会断言原子访问已建立.使用重试单步执行这些代码将陷入永久循环。

为了克服工件,gdb stepi 跳过原子会话(从 ldrx 到 strx 序列),就好像它们是一条指令一样。

【讨论】:

  • 在我看来我遇到了相反的问题:gdb 正在逐步执行所有这些指令,因此stlxr 总是失败并且循环永远无法完成。我不得不在循环下方的行中手动添加断点,并使用continue 来克服它。您的回答似乎可以解释这种行为,谢谢!
  • GDB 只处理 strex{,b,h,d}。此外,如果 strex 距离 ldrx 有 16 条指令,它将无法处理。如果 ldrx 和 strx 之间有多个条件分支,它将无法处理。如果只有一个条件分支,GDB 会在分支被占用的登陆地址设置断点,帮助判断是否被占用。如果这个地址还在 ldrx 和 strx 区域(不常见),即使不被占用,由于 gdb 隐藏工作,原子属性仍然受到损害。
猜你喜欢
  • 2020-10-12
  • 1970-01-01
  • 2014-08-22
  • 1970-01-01
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
相关资源
最近更新 更多