代码之家  ›  专栏  ›  技术社区  ›  Josh Kelley

在x86linux上调试SIGBUS

  •  13
  • Josh Kelley  · 技术社区  · 15 年前

    (我的代码正在一台计算机上运行 Geode

    7 回复  |  直到 15 年前
        1
  •  15
  •   Chris Dodd    15 年前

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

    最好的方法是使用调试器来识别出错指令(SIGBUS是同步的),并尝试查看它试图执行的操作。

        2
  •  23
  •   caf    15 年前

    SIGBUS mmap 超出映射文件结尾的区域。

    mmap 、共享内存区域或类似区域?

        3
  •  10
  •   Ruslan PiotrNycz    8 年前

    x86(包括x86_64)Linux上的SIGBUS是一种罕见的野兽。它可能出现在试图访问超过 mmap 或者POSIX描述的其他一些情况。

    但由于硬件故障,要获得SIGBUS并不容易。也就是说,来自任何指令的未对齐访问(无论是否为SIMD)通常会导致SIGSEGV。堆栈溢出导致SIGSEGV。即使对非规范格式地址的访问也会导致SIGSEGV。所有这些都是由于#GP被提升,它几乎总是映射到SIGSEGV。

    现在,以下是一些由于CPU异常而获取SIGBUS的方法:

    1. 在中启用交流位 EFLAGS this discussion 详情请参阅。

    2. 通过堆栈指针寄存器执行规范冲突( rsp rbp ),生成#SS。下面是一个GCC示例(使用 gcc test.c -o test -masm=intel ):

    int main()
    {
        __asm__("mov rbp,0x400000000000000\n"
                "mov rax,[rbp]\n"
                "ud2\n");
    }
    
        4
  •  6
  •   Joshua    15 年前

    哦,是的,还有一种更奇怪的方法可以找到SIGBUS。

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

        5
  •  4
  •   salmin    7 年前

    一种常见的情况是,您使用ftruncate惰性地增长文件,将其映射到内存中,开始写入数据,然后文件系统中的空间用完。映射文件的物理空间是在页面错误上分配的,若并没有剩余空间,则进程将接收SIGBUS。

    如果您需要应用程序正确地从该错误中恢复,那么在使用fallocate进行mmap之前显式地保留空间是有意义的。在errno after fallocate调用中处理ENOSPC比处理信号简单得多,特别是在多线程应用程序中。

        7
  •  0
  •   Luchs    5 年前

    mmap MAP_HUGETLB flag,你可以 SIGBUS 如果内核用完了分配的巨大页面,因此无法处理页面错误。

    在这种情况下,您需要通过

    • /sys/kernel/mm/hugepages/hugepages-<size>/nr_hugepages
    • /sys/devices/system/node/nodeX/hugepages/hugepages-<size>/nr_hugepages
        8
  •  -1
  •   Tyler McHenry    15 年前

    x86 Linux上发生总线错误的一个常见原因是,试图取消引用并非真正的指针或野生指针的内容。例如,未能初始化指针,或为指针指定任意整数,然后尝试取消引用它,通常会产生分段错误或总线错误。

    对齐确实适用于x86。即使x86上的内存是字节可寻址的(因此您可以有一个指向任何地址的char指针),但如果您有一个指向4字节整数的指针,则该指针必须对齐。

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

        9
  •  -1
  •   Mischa    13 年前

    这有点离经叛道,但您可以从未对齐的SSE2(m128)负载获得SIGBUS。