gpt4 book ai didi

assembly - 在代码执行时将未对齐写入机器代码中的立即操作数是否安全?

转载 作者:行者123 更新时间:2023-12-05 01:51:52 25 4
gpt4 key购买 nike

假设我有这样的 x86-64 代码(尽管这个问题更普遍地适用于所有代码):

mov rbx,7F0140E5247Dh
jmp rbx

如果目标值未对齐,覆盖目标常量是否安全,而该代码可能正在执行?换句话说,我是否可以观察到部分更新的跳转目标,从而导致跳转到不存在的地址?另外,如果目标常量跨越页面或缓存行边界,这是否安全?

编辑:

我只对更改单个指令感兴趣,对更改指令边界位置不感兴趣。

最佳答案

仅当写入是原子的,这是有保证的 with unaligned qword writes on Intel as long as it doesn't span a cache-line boundary ,但不能保证在 AMD 上。最低公分母原子性保证是 8 字节对齐的存储是原子的,仅此而已。

使用 xchg 执行保证原子的 RMW。如果常量本身跨越缓存行边界,那将非常慢,但我相信是正确的。 (总线锁,不仅仅是高速缓存锁;如此之慢,甚至还有一个 perf 计数器,甚至只是用于 split-lock,甚至是一个 CPU 功能,至少在内核代码中会出现该错误,因此您可以找到它在 VM 中。)如果常量不跨越任何 CPU 的问题边界,它应该与对齐的原子操作一样快。

或者,如果您的 CPU 支持 AVX,则 16 字节对齐的 SSE/AVX 存储在具有 AVX 的 CPU 上保证是原子的。 (直到最近几年才知道这在实践中基本上是安全的,但幸运的是它对所有 AVX CPU 都有追溯力,没有新的功能位。)所以如果你能让你的常量排队不跨越 16 字节边界,你可以那样更新它。 (用自己覆盖周围的字节不会导致问题,除非另一个线程也在附近更新另一个常量。)

如果性能对此很重要(例如,每分钟执行一次以上),可能值得使用一些填充或 NOP 来使常量 8 字节对齐,特别是如果你可以 just lengthen earlier instructions不需要实际的 NOP,甚至不需要 mov r64,imm64 本身。 (虽然它是 10 个字节,一条指令的最大长度是 15。)


完全概括为替换多条指令

在其他情况下,您可能要重写指令序列,其中一个指令边界在不同的地方,那就是另一回事了。您说这个问题“更普遍”适用,但仅适用于替换立即数或用相同长度的指令替换整个 4 字节或 8 字节指令。如果另一个线程可能在您正在编写的区域内使用 RIP 休眠或运行,则您必须考虑在更新后从旧序列的任何可能的 RIP 中获取代码的情况。所以正如我所说,改变指令边界是有问题的。

但是如果您遵守该限制,交叉修改代码是 AFAIK 安全的。我认为 Windows 热修补会停止可能正在运行代码的其他线程,但我不知道为什么,因为它已经确保有一个足够大的指令供它覆盖。他们要么过于谨慎,要么存在一些我不知道的不尊重存储原子性的代码获取风险。也许只是他们不想在未对齐函数的情况下依赖 2 字节存储原子性,甚至认为这是正常编译器设置的默认设置。

关于assembly - 在代码执行时将未对齐写入机器代码中的立即操作数是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71933875/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com