禁止在x86/x86_64上进行未对齐的内存访问

osg*_*sgx 13 linux debugging x86 memory-alignment

我想在x86/x86_64上使用禁止的未对齐内存访问来模拟系统.是否有一些调试工具或特殊模式来执行此操作?

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

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

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

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

Yan*_*aud 7

我刚读过问题未对齐的内存访问是否总是导致总线错误?与维基百科文章Segmentation Fault相关联.

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

以下是如何启用它(来自Segmentation Fault):

#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__) 
     /* Enable Alignment Checking on x86_64 */
    __asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif
Run Code Online (Sandbox Code Playgroud)

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

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

  • 对于在最近的 Linux 上使用它的任何人,请注意:C 库将在 strcmp 中崩溃,它用于动态加载程序。所以在运行之前做`export LD_BIND_NOW=1`,这样ld.so 将在启动时而不是按需解析所有库符号。 (2认同)

lig*_*123 6

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

请参阅在线文档:

  • 很好,这应该可以捕获 C 源代码级未对齐指针,而不会绊倒编译器在为具有快速已知安全未对齐访问的平台(如 x86)优化窄对齐访问时故意生成的潜在未对齐访问。此外,memcpy 和其他 libc 函数在手写 asm 中使用未对齐访问(例如,对于 glibc 中的小型非 2 次幂大小的副本)。所以启用x86的AC标志一般是不可用的 (2认同)

gby*_*gby 5

这很棘手,我没有亲自完成,但我认为你可以通过以下方式完成:

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

首先,您可以运行您的程序并使用Linux下的"perf"工具来计算您的代码所做的错位访问次数.

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

实际上,这将使x86_64成为不支持未对齐访问的核心.

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

  • "对性能计数器进行编程以生成中断的内核模块" - 在进行性能分析时,它不是一种perf/oprofile模式吗?(`perf record -e MISALIGN_MEM_REF:u -c 1`.)perf已经有代码来分隔库和用户代码.来自perf的中断不会停止程序; 但是perf将记录未对齐访问的位置.我认为这种模式可以更有用,然后杀死程序并做一个一个修复. (2认同)
  • @osgx你是对的.如果以与不支持未对齐加载/存储的CPU相同的方式生成类似异常的中断并不重要,"perf record -e MISALIGN_MEM_REF:u -c 1"可用于查找我同意,这样做的程序. (2认同)