我试图验证和理解在模拟框架中执行的指令。模拟步骤如下:
二进制文件在主机processors)

执行指令的列表包括包含在二进制和可能的内核指令中的指令。
我正在通过使用二进制文件上objdump的输出来验证跟踪的用户指令。它们是相等的,确认了执行的正确性。
这是上面图片中说明的objdump输出:

对于内核说明,我必须应用初步步骤:
我在虚拟机中安装了内核头,并提取了用于在虚拟机上执行objdump的linux映像。
对于验证步骤,我使用相同的用户指令方法,将linux内核映像的objdump与跟踪输出进行比较。但是,当发现内核符号指令时,我注意到了一些differences...mostly。这是跟踪的输出:

这是linux内核映像的对应部分:



从这些图片中可以看到,在跟踪输出中,每个对应于内核符号(比较linux映像的虚拟地址与/proc/kallsyms)的调用q被替换为NOP DWORD (nopl指令)。
我想要做的是理解为什么有一个NOP DWORD而不是内核符号的调用q。
是因为搬迁吗?如果是的话,我如何重建这些指示的搬迁?
注意:我使用-dr执行objdump来检查Linux映像上的重定位,但是输出没有改变。
我的验证方法对内核指令是错误的吗?
发布于 2021-01-13 12:38:18
(部分回答/猜测可能会指向正确的方向。)更新: Jester建议这看起来像ftrace机器:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/ftrace.c?h=v5.10)
我怀疑这些调用是在加载后获得NOPed的,可能是在相关的跟踪点或其他未启用的情况下。出于某种原因,发出NOPing调用可以解释为什么会出现与NOP相关的调用目标或符号重定位元数据。
我想我读过关于Linux使用代码修改来实现低开销的跟踪点之类的东西,而自修改代码通常是Linux所做的事情。
Linux使用在启动时修改一次的自修改代码,或者进行非常罕见的配置更改,以减少每次执行的开销,而不需要对分支进行修改,用于几种不同的操作。(例如,在UP机器上引导SMP内核,只需要SMP安全,而不是硬件设备,就会在原子RMWs中删除lock前缀。)内联asm宏定义符号和自定义部分,这样内核就有了必要的元数据。另外,最近有关修改rel32调用目标而不是使用间接分支的一些内容,以避免在这些站点上进行任何谱缓解的需要,但这里并不是这样的。
因此,一般来说,当您试图验证内核映像文件的执行时,您应该会看到一些不匹配的地方,这可能是文件之一。
在这种情况下,这看起来像一个函数的顶部(在设置一个框架指针之前),这听起来像是一个可能找到某种特殊调用的地方,可能用于跟踪(保存所有寄存器的特殊函数)。
gcc生成的代码永远不会在call / mov %rsp, %rbp之前做push %rbp。首先,这违反了16字节堆栈对齐ABI的要求。(虽然内核可能使用-mpreferred-stack-boundary=3而不是4?经过两次推送后,还有另一个更正常的调用,如果这是一个正常函数,也会有一个对齐的RSP。)不管怎么说,这是另一个迹象,有一些定制的内联asm黑客或什么正在进行。
https://stackoverflow.com/questions/65701383
复制相似问题