16

我想在 x86/x86_64 上使用禁止的未对齐内存访问来模拟系统。是否有一些调试工具或特殊模式可以做到这一点?

当使用为 SPARC 或其他类似 CPU 设计的软件 (C/C++) 时,我想在几台 x86/x86_64 PC 上运行许多(CPU 密集型)测试。但是我对 Sparc 的访问是有限的。

据我所知,Sparc 总是检查内存读取和写入中的对齐是否自然(从任何地址读取一个字节,但仅当地址可被 4 整除时才允许读取 4 字节字)。

可能是 Valgrind 或 PIN 有这种模式?还是编译器的特殊模式?我正在寻找 Linux 非商业工具,但也允许使用 Windows 工具。

或者可能在 EFLAGS 中有秘密的 CPU 标志?

4

4 回答 4

12

我刚刚阅读了问题是否未对齐的内存访问总是会导致总线错误?链接到 Wikipedia 文章Segmentation Fault

在这篇文章中,有一个非常罕见的英特尔处理器标志AC aka Alignment Check 的精彩提醒。

这是启用它的方法(来自维基百科的总线错误示例,为 x86-64 System V 修复了一个红色区域破坏错误,因此这在 Linux 和 MacOS 上是安全的,并且从基本 asm 转换而来,这在函数内部从来都不是一个好主意:您希望对 AC 的更改按照内存访问进行排序。

#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\n orl $0x40000,(%%esp)\n popf" ::: "memory");
# elif defined(__x86_64__) 
     /* Enable Alignment Checking on x86_64 */
    __asm__("add $-128, %%rsp \n"    // skip past the red-zone, in case there is one and the compiler has local vars there.
            "pushf\n"
            "orl $0x40000,(%%rsp)\n"
            "popf \n"
            "sub $-128, %%rsp"       // and restore the stack pointer.
           ::: "memory");       // ordered wrt. other mem access
# endif
#endif

一旦启用,它的工作原理很像 ARM 对齐设置/proc/cpu/alignment,请参阅答案如何捕获未对齐的内存访问?举些例子。

此外,如果您使用的是 GCC,我建议您启用-Wcast-align警告。在为具有严格对齐要求的目标(例如 ARM)构建时,GCC 将报告可能导致内存访问未对齐的位置。

但请注意,libc 为 memcpy 和其他功能编写的手写 asm 仍然会进行未对齐的访问,因此在 x86(包括 x86-64)上设置 AC 通常不实用。GCC 有时会发出 asm 进行非对齐访问,即使您的源没有,例如,作为一次复制或归零两个相邻数组元素或结构成员的优化。

于 2013-07-19T14:20:21.630 回答
8

这很棘手,我没有亲自做过,但我认为你可以通过以下方式做到这一点:

x86_64 CPU(特别是我检查过 Intel Corei7,但我猜也有其他的)有一个性能计数器 MISALIGN_MEM_REF,它计数器未对齐的内存引用。

所以首先,你可以运行你的程序并在 Linux 下使用“perf”工具来计算你的代码已经完成的错位访问的数量。

一个更棘手和有趣的 hack 是编写一个内核模块,该模块对性能计数器进行编程以在溢出时生成中断并让它溢出第一个未对齐的加载/存储。在内核模块中响应此中断,但向您的进程发送信号。

实际上,这会将 x86_64 变成不支持未对齐访问的内核。

但这并不简单——除了您的代码之外,系统库还使用未对齐的访问,因此将它们与您自己的代码分开会很棘手。

于 2012-08-07T06:15:29.280 回答
6

GCC 和 Clang 都内置了 UndefinedBehaviorSanitizer。其中一项检查 ,alignment可以使用-fsanitize=alignment. 它将发出代码以在运行时检查指针对齐情况,并在取消引用未对齐的指针时中止。

请参阅在线文档:

于 2020-12-20T23:25:22.763 回答
0

也许您可以通过所有对齐的动作编译到 SSE。未对齐的访问movaps是非法的,并且可能会在其他架构上表现为非法的未对齐访问。

于 2012-08-07T00:14:52.577 回答