【问题标题】:How is PTRACE_SINGLESTEP implemented?PTRACE_SINGLESTEP 是如何实现的?
【发布时间】:2016-08-21 13:57:06
【问题描述】:

据我所知(我可能是错的),没有办法只在 x86-64 系统上执行 一个 指令。也许您可以执行指令后跟“ud2”操作码来触发信号——但是您必须担心指令会修改控制流并转到其他地方。

然而,如果我理解正确的话,ptrace() 系统调用有一个 SINGLESTEP 选项,它只执行一条指令。这是如何实施的?我无法想象内核有某种反汇编程序来识别指令及其原因。那么,它使用了某种我不知道的架构特性吗?还是完全不同的东西?

【问题讨论】:

  • 我不是最新的,但陷阱标志 (TF) 不再是一个东西吗?
  • 不,我只是不知道!

标签: linux assembly x86 x86-64 ptrace


【解决方案1】:

是的,x86 上有一个架构单步标志。从内核返回到用户空间使内核有机会同时设置 RIP/RFLAGS,因此它可以为用户空间设置单步,而无需触发内核指令。

出于某种原因,Trap Flag 有自己的维基百科文章!另见wikipedia's EFLAGS article

请参阅 标签 wiki,获取指向英特尔架构手册的链接,其中记录了所有这些内容。


也许您可以执行指令后跟“ud2”操作码来触发信号

然后您需要代码来确定解码 x86 指令长度。你不会使用ud2,你会使用int3 which exists for this purpose.

IIRC,还有调试寄存器,可以在不修改代码的情况下设置硬件断点。


有趣的事实:并非所有 ISA 都支持PTRACE_SINGLESTEP

例如,Linux 内核曾经为 ARM 模拟它,但这需要内核中的 ARM 反汇编程序在下一条指令处放置断点,即使是分支目标也是如此。它于 2011 年被移除;现在 ptrace(PTRACE_SINGLESTEP) 在 ARM 上返回 -ENOSYS

他们只是去掉了所有这些复杂性,而不是试图使其 SMP 安全并支持每条新指令,例如 Thumb-2 等。 (http://lists.infradead.org/pipermail/linux-arm-kernel/2011-February/041324.html)

因此调试器必须在此类 ISA 上手动使用断点,而不是让内核为它们执行此操作。如果这意味着其他线程暂时注意到内存中的调试中断操作码,那不是内核的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 2015-05-22
    • 2015-04-22
    • 2020-07-31
    • 2011-04-24
    • 2016-04-17
    • 2013-08-23
    相关资源
    最近更新 更多