提问人:Bob5421 提问时间:11/11/2023 更新时间:11/11/2023 访问量:26
动态指令修补
on the fly instruction patching
问:
我为 Linux 创建了一个小型调试器。 我试图创建一种机制来加密二进制指令并在执行前解密它们(我已经设置了硬件断点或分步运行)。 它在 100 次中有 99 次有效。
我认为问题是由于 L1 缓存造成的。 当我尝试解密指令时,此指令已在 CPU L1 缓存中。 我试过 ARM64 和 x86_64。我得到了同样的结果。
我的问题是像 gdb 或 lldb 这样的调试器如何在没有 L1 缓存副作用的情况下修补断点指令?
谢谢
答:
x86/x86_64 是一个不寻常的野兽,因为如果你写入指令内存,它将使缓存的那一行失效,所以你不需要做任何事情。这是为了向后兼容 1980 年代的芯片,当时没有任何缓存。这意味着对于该处理器,L1 缓存肯定不是问题,除非您使用不同的线性地址修改指令,如下所述:
11.6 自修改代码 写入当前缓存在处理器中的代码段中的内存位置会导致关联的缓存行(或行)失效。
例外情况是,如果你正在对地址映射做一些奇怪的事情(来自文档的同一部分):
系统软件,例如调试器,可能会修改 指令使用与用于获取的线性地址不同的线性地址 该指令将执行序列化操作,例如 CPUID 指令,在修改后的指令执行之前,这将 自动重新同步指令缓存和预取队列。
因此,在x86_64,您可以尝试 CPUID 指令。
除了这种情况,您的问题根本不是缓存 - 我会去其他地方寻找,例如寻找竞争条件(您还没有说非工作情况是什么样子的)。
对于其他现代处理器(包括 ARM),您需要自行使指令缓存的相关部分失效。
https://developer.arm.com/documentation/ddi0344/k/Babhejba
评论
cpuid
serialize
code_ready
ptrace
iret
sysret
sysret
ptrace
评论
ptrace
iret