在x86 Linux上debuggingSIGBUS

在Linux的通用x86用户级应用程序中,什么会导致SIGBUS(总线错误)? 我在网上find的所有讨论都是关于内存alignment错误的,从我的理解来看并不适用于x86。

(我的代码在Geode上运行,以防在那里有任何相关的处理器特定怪癖。)

Solutions Collecting From Web of "在x86 Linux上debuggingSIGBUS"

如果打开未对齐的访问陷阱,您可以从未对齐的访问中获取SIGBUS,但通常在x86上关闭。 如果出现某种错误,也可以通过访问内存映射设备来获取它。

最好的办法是使用一个调试器来识别错误指令(SIGBUS是同步的),并试图看看它正在尝试做什么。

除了内存对齐错误之外, SIGBUS可能会在Linux中发生,例如,如果尝试访问超出映射文件末尾的mmap区域,

你是否使用像mmap ,共享内存区域或类似的东西?

x86上的SIGBUS(包括x86_64)Linux是一种罕见的野兽。 它可能会从尝试访问过去mmap ed文件的结尾或POSIX描述的其他一些情况中出现。

但是从硬件故障中获取SIGBUS并不容易。 也就是说,从任何指令(不管是否SIMD)进行非对齐访问通常都会导致SIGSEGV。 堆栈溢出导致SIGSEGV。 即使访问不是规范形式的地址也会导致SIGSEGV。 所有这些都是由于#GP被引发的,它几乎总是映射到SIGSEGV。

现在,由于CPU异常,这里有一些获取SIGBUS的方法:

  1. 使能EFLAGS AC位,然后通过任何存储器读取或写入指令进行非对齐访问。 详细信息请参阅此讨论 。

  2. 通过堆栈指针寄存器( rsprbp )执行规范违例,生成#SS。 下面是GCC的示例(使用gcc test.c -o test -masm=intel编译):

 int main()
 {
     __asm __(“mov rbp,0x400000000000000 \ n”
             “mov rax,[rbp] \ n”
             “UD2 \ n”);
 }

哦,是的,还有一个更奇怪的方式来获得SIGBUS。

如果由于内存压力(OOM杀手必须禁用)或者IO请求SIGBUS失败,内核无法在代码页中进行分页。

x86 Linux上一个总线错误的常见原因是试图解引用一些不是真正的指针,或者是一个野指针。 例如,未能初始化一个指针,或者将一个任意的整数指定给一个指针,然后试图解引用它,通常会产生分段错误或总线错误。

对齐确实适用于x86。 即使x86上的内存是字节地址(所以你可以有一个字符指针指向任何地址),如果你有一个指向4字节整数的指针,那么指针必须对齐。

您应该在gdb中运行您的程序,并确定哪个指针访问正在生成总线错误来诊断问题。

这是有点离谱,但你可以从未对齐的SSE2(m128)负载得到SIGBUS。