我想知道如果从内核(在这种情况下是Linux)中你在进程上下文中调用ptrace_request和PTRACE_SINGLESTEP(系统调用,页面错误等等)会发生什么。它会单步执行用户空间指令还是内核空间指令。我意识到ptrace只能单步用户指令,这就是为什么我对这会产生的行为感到好奇。
为了提供更多信息,我试图从页面错误处理程序这样做(单步执行故障,但更改PTE以便指令通过)。我想知道这是否甚至是可能的,或者是否需要另一种方法来重新安排流程运行等等。
这是因为进程的task_struct(如果被抢占)仍将指向内核空间处理程序IIRC,那么单步执行ptrace会绕过这个并执行正确的用户空间指令或者根本不执行它吗?
答案 0 :(得分:1)
我并不完全理解你的意思,PTRACE_SINGLESTEP总是在用户上下文中从内核调用:当你执行你的系统调用ptrace(PTRACE_SINGLESTEP)时,你最终会在执行该函数的内核上下文中执行通常并使您正在执行的过程执行一条指令,无论您是否从页面错误处理程序调用它。你将无法像往常一样单独进入内核。
我建议您查看arch / x86 / kernel / ptrace.c以了解单步实际如何工作。单步指令实际上是由内核模拟的,IIRC没有硬件支持。
答案 1 :(得分:0)
要了解问题的答案,您需要了解英特尔硬件。
首先我们从最简单的指令开始(因为SINGLE_STEP是将Intel CPU置于单步执行模式,并在执行一个结构后返回中断处理程序):
movl(eax),ebx
遵循英特尔的格式,这意味着获取eax中的值,将其视为内存指针,访问内存,获取4字节值并将其复制到ebx。
这个ONE汇编指令 - 在内核vs用户上下文中执行时将具有不同的行为/含义。
如果在内核中,内核的pagetable将用于访问内存,并将数据复制到ebx。在用户进程中,将使用用户的页面表(顺便通过MMU硬件)从内存中读取数据并复制到ebx。 eax中的相同值,但CR3寄存器中的值不同(意味着不同的进程上下文),将触发要读取的内存的不同部分。因此在内核中跟踪用户空间程序真的很荒谬。因为你必须做一个上下文切换(它涉及整套寄存器存储和恢复操作),在执行用户指令之前和之后完成 - 这意味着4个操作有效。
正如您所看到的,我没有像您提到的那样引用任何内核函数API。总体概念理解是第一位的。