Отладка SIGBUS на x86 Linux - PullRequest
       76

Отладка SIGBUS на x86 Linux

14 голосов
/ 18 января 2010

Что может вызвать SIGBUS (ошибка шины) в универсальном пользовательском приложении x86 в Linux?Все обсуждения, которые мне удалось найти в Интернете, касаются ошибок выравнивания памяти, которые, насколько я понимаю, на самом деле не относятся к x86.

(мой код работает на Geode , если там есть какие-то специфические особенности процессора.)

Ответы [ 7 ]

19 голосов
/ 19 января 2010

SIGBUS может происходить в Linux по нескольким причинам, помимо ошибок выравнивания памяти - например, если вы пытаетесь получить доступ к области mmap за концом сопоставленного файла.

Используете ли вы что-то вроде mmap, областей совместно используемой памяти или подобное?

13 голосов
/ 19 января 2010

Вы можете получить SIGBUS из доступа без выравнивания, если вы включите ловушку доступа без выравнивания, но обычно она отключена на x86. Вы также можете получить доступ к устройству, отображенному в памяти, если есть какая-либо ошибка.

Лучше всего использовать отладчик для определения неисправной инструкции (SIGBUS работает синхронно) и пытаться увидеть, что он пытается сделать.

8 голосов
/ 20 сентября 2016

SIGBUS на x86 (включая x86_64) Linux - редкий зверь. Это может произойти из-за попытки получить доступ к концу mmap ed-файла или из-за некоторых других ситуаций, описанных POSIX.

Но из-за аппаратных сбоев получить SIGBUS непросто. А именно, несогласованный доступ из любой инструкции - будь то SIMD или нет - обычно приводит к SIGSEGV. Переполнение стека приводит к SIGSEGV. Даже доступ к адресам не в канонической форме приводит к SIGSEGV. Все это из-за повышения #GP, которое почти всегда отображается в SIGSEGV.

Теперь вот несколько способов получить SIGBUS из-за исключения процессора:

  1. Включить бит переменного тока в EFLAGS, затем выполнить несоосный доступ по любой инструкции чтения или записи в память. Подробнее см. в этом обсуждении .

  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 голосов
/ 19 января 2010

О, да, есть еще один странный способ получить SIGBUS.

Если ядру не удается выполнить листинг в кодовой странице из-за нехватки памяти (необходимо отключить OOM killer) или неудачного запроса ввода-вывода, SIGBUS.

2 голосов
/ 05 декабря 2017

Это было кратко упомянуто выше как «неудавшийся запрос ввода-вывода», но я немного подробнее остановлюсь на этом.

Часто случается, когда вы лениво увеличиваете файл с помощью ftruncate, отображаете его в память, начинаете записывать данные, а затем исчерпываете место в вашей файловой системе. Физическое пространство для сопоставленного файла выделяется при ошибках страницы, если ничего не осталось, процесс получает SIGBUS.

Если вам нужно, чтобы ваше приложение корректно восстанавливалось после этой ошибки, имеет смысл явно зарезервировать пространство до mmap с помощью fallocate. Обработка ENOSPC в errno после вызова fallocate намного проще, чем обработка сигналов, особенно в многопоточном приложении.

0 голосов
/ 18 апреля 2012

Это немного по проторенному пути, но вы можете получить SIGBUS от невыровненной нагрузки SSE2 (m128).

0 голосов
/ 19 января 2010

Распространенной причиной ошибки шины в x86 Linux является попытка разыменования чего-то, что на самом деле не является указателем или является диким указателем. Например, если инициализировать указатель не удастся или присвоить указателю произвольное целое число, а затем попытаться разыменовать его, это обычно приведет к ошибке сегментации или ошибке шины.

Выравнивание действительно относится к x86. Несмотря на то, что память в x86 является адресуемой по байту (так что вы можете иметь символьный указатель на любой адрес), если у вас есть, например, указатель на 4-байтовое целое число, этот указатель должен быть выровнен.

Вам следует запустить свою программу в gdb и определить, какой указатель доступа генерирует ошибку шины для диагностики проблемы.

...