【发布时间】:2017-07-13 14:34:54
【问题描述】:
我在 aarch64 上遇到 gdb 问题。我无法描述有关平台的很多细节,但它不是必需的。问题是断点处理。只有断点的第一个停止运行良好,在没有再次插入继续断点之后,程序将在没有后续断点停止的情况下运行。这会导致更多错误,例如内部 gdb 断点无法正常工作,并且动态库未正确自动加载。
据我所知,gdb 会在感兴趣的位置插入特殊的 bp 指令(类似于 x86-64 上的 INT 3),这会在执行期间生成 SIGTRAP,由 gdb 处理(用于 bp 停止、符号加载等)。当继续执行时,gdb 必须再次插入该指令。
我在 aarch64 和 x86-64 上都遇到了这种错误(用于理解正确的行为)在继续后立即:
infrun: skipping breakpoint: stepping past insn at: <bp addr>
这是因为gdb在continue后会经过bp位置(原指令还没有执行),会导致无限停止。
但是在 x86-64 上,我看到 gdb 在 bp 之后的 下一条指令 继续之后处理另一个 SIGTRAP,并且此时 bp 可以正确插入(因为 bp 地址已经传递)。但是在我的 aarch64 平台上,我只从 bp 位置获得了 1 个 SIGTRAP,仅此而已。据我了解,这导致不再插入 bp。
我调试了 GDB(是的,先生),发现在 x86-64 上没有为下一条指令插入 bp。因此,我无法调查 aarch64 的同一个地方并了解错误的来源。
我是否正确理解了 bp 实现?哪些代码影响了“隐藏的”第二代 SIGTRAP?
统一更新: 我发现,带有 request=PTRACE_SINGLESTEP 的 ptrace 在 aarch64 上不起作用(程序将继续运行直到终止)。还有,aarch64使用了软件单步,但是aarch64_software_single_step返回0(异常完成),可能是这个原因。
【问题讨论】: