assembly - 跟踪和反汇编与内核镜像文件不匹配的 Linux 内核指令

标签 assembly gcc linux-kernel x86 trace

我正在尝试验证和理解在模拟框架中执行的指令。
模拟步骤如下:

  • 在主机 x86 机器中使用 gcc(带有 -fPIC 标志)交叉编译二进制文件
  • 然后在名为 SimNow(AMD 用于测试其处理器)的 x86 虚拟机中移动并执行二进制文件
  • SimNow 机器生成已执行指令的列表,这些指令将传递给框架,其中包括有关每条指令的信息:虚拟地址、物理地址、大小、操作码。
  • 由于使用 x86 反汇编器(名为 distorm),该框架生成了执行指令的跟踪,包括助记符和操作数。
    这是跟踪输出的示例:
    enter image description here

  • 执行指令列表包括包含在二进制和可能的内核指令中的指令。
    我正在通过使用二进制文件上 objdump 的输出来验证跟踪的用户指令。它们是相等的,确认了执行的正确性。
    这是上图中指令的 objdump 输出:
    enter image description here
    对于内核指令,我必须应用初步步骤:
  • 我将内核头文件安装到虚拟机中,并提取了 linux 镜像以在其上执行 objdump。
  • 我通过将内核指令的虚拟地址与/proc/kallsysms 中包含的虚拟地址进行比较,将内核符号添加到跟踪输出中。

  • 对于验证步骤,我使用与用户指令相同的方法,将 linux 内核镜像的 objdump 与跟踪输出进行比较。
    但是,我注意到了一些差异……主要是在发现内核符号指令时。
    这是跟踪的输出:
    enter image description here
    这是 linux 内核镜像的对应部分:
    enter image description here
    enter image description here
    enter image description here
    从这些图片中可以看出,每个对应于内核符号的 callq(将 linux 镜像的虚拟地址与/proc/kallsyms 进行比较)在跟踪输出中被替换为 NOP DWORD(nopl 指令)。
    我想要做的是理解为什么内核符号有一个 NOP DWORD 而不是 callq。
    是因为搬家吗?如果是,我如何重建此类指令的重定位?
    注意:我用 -dr 执行了 objdump用于检查 Linux 镜像上的重定位,但输出没有改变。
    我的内核指令验证方法错误?

    最佳答案

    (部分答案/猜测可能会为您指明正确的方向。更新:Jester 建议这看起来像 ftrace 机械:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/ftrace.c?h=v5.10)
    我怀疑这些调用在加载后被 NOPed,可能是在相关的跟踪点或任何未启用的情况下。出于某种原因取消调用将解释为什么有与 NOP 关联的调用目标或符号重定位元数据。
    我想我已经阅读了关于 Linux 使用代码修改来实现低开销跟踪点或其他东西的信息,并且自修改代码是 Linux 肯定会做的事情。
    Linux 使用自修改代码,在启动时修改一次,或在非常罕见的配置更改时修改,以减少每次执行与分支的开销,对于一些不同的事情。 (例如,在 UP 机器上启动 SMP 内核将消除原子 RMW 中的 lock 前缀,这些前缀只需要是 SMP 安全的,而不是硬件设备。)内联 asm 宏定义符号和自定义部分,以便内核具有必要的元数据.还有最近关于修改 rel32 的事情调用目标而不是使用间接分支,以避免需要在这些站点上进行任何 Spectre 缓解,但这不是这里发生的事情。
    因此,一般而言,当您尝试针对内核镜像文件验证执行时,您应该会看到一些不匹配,这可能是其中之一
    在这种情况下,这看起来像是一个函数的最顶部(在设置帧指针之前),这听起来很可能是找到某种特殊调用的地方,也许是为了跟踪(到一个保留所有寄存器的特殊函数)。
    gcc 生成的代码永远不会 AFAIK 做 call之前 push %rbp/mov %rsp, %rbp .一方面,这会违反 16 字节堆栈对齐 ABI 要求。 (虽然也许内核使用 -mpreferred-stack-boundary=3 而不是 4?两次推送后,还有另一个更正常的调用,如果这是一个正常的函数,它也会有一个未对齐的 RSP。)无论如何,这是另一个迹象,表明存在一些自定义的内联 asm 黑客或正在发生的事情。

    关于assembly - 跟踪和反汇编与内核镜像文件不匹配的 Linux 内核指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65701383/

    相关文章:

    linux - 64 位 NASM 文件处理问题

    c++ - if 语句与 if-else 语句,哪个更快?

    c - ASM to C - 有人能解释一下这是什么结构吗?

    c++ - 如何编写支持 LTO 的代码?

    linux - 包含 linux 内核配置的正确方法是什么?

    c - 将内核模块与用户空间程序通信的最佳方式是什么?

    assembly - 向量汇编中的元素求和

    c - C语言中如何知道未知类型变量的数据类型?

    c - 如何让gcc为gprof生成信息?

    linux - 设备驱动程序如何写入/读取