X86: устранение сбоев выравнивания данных (иначе SIGBUS на sparc)

Как-то можно поймать ошибки выравнивания данных даже на i386? Возможно, установив специальный регистратор i386 или что-то в этом роде.

В Solaris-Sparc я получаю SIGBUS в этом случае, но на i386 все в порядке.

Окружающая среда:

  • 32-разрядное приложение
  • Ubuntu Karmic
  • gcc/g++ v4.4.1

ИЗМЕНИТЬ: Вот почему я спрашиваю об этом:

  • наше приложение вылетает на Sol-Sparc с SIGBUS. Для отладки я попытался бы получить аналогичное поведение на нашей платформе i386.
  • наша Sol-sparc-машина работает очень медленно, поэтому компиляция и отладка занимает много времени. И наша машина i386 невероятно проста (8 ядер, 32 Гб памяти).
  • Даже на платформах i386 существует стоимость производительности при ошибках выравнивания данных. И поэтому я хотел бы исправить ошибки выравнивания данных, где это возможно.

Ответы

Ответ 1

Чтобы развернуть на Vokuhila-Oliba ответ, глядя на "SOF Mis-aligned указатели на x86." поток кажется, что gcc может генерировать код с неправильно выровненной памятью доступ. AFAIK у вас нет никакого контроля над этим.

Включение проверки выравнивания в gcc-компилированном коде было бы плохой идеей. Вы рискуете получить ошибки SIGBUS для хорошего кода C.

ReEdited: Извините за это

Ответ 2

Тем временем я нашел документ CPU Intel, рассматривающий этот вопрос.

См. Руководство разработчика программного обеспечения для разработчиков Intel® 64 и IA-32.

Кажется, сложно собрать все это вместе. Однако это не похоже, что это совершенно невозможно. Интересная глава - 4.10.5 Проверка выравнивания

EDIT (некоторые конденсированные материалы из упомянутого документа):

страница 5-60

Interrupt 17 Alignment Check Exception (#AC)

to enable alignment checking, the following conditions must be true:

AM flag is set(bit 18 of control regisster CR0)
AC flag is set (bit 18 of the EFLAGS)
The CPL is 3 (protected mode or virtual-8086 mode).

дополнительно - в 14.8.2.6 - упоминаются ошибки контроллера памяти. Я не знаю, является ли это одним и тем же, другими словами:

table 14-11, Encoding of MMM and CCCC Sub-Fields
Address/Command Error  AC  011

Ответ 3

Я нашел очень простое решение на SOF! См. Неравномерные указатели на x86.

int main(int argc, char **argv)
{
# if defined i386
    /* EDIT: enable AC check */
    asm("pushf; "
    "orl $(1<<18), (%esp); "
    "popf;");
# endif

    char d[] = "12345678";  /* yep! - causes SIGBUS even on Linux-i386 */
    return 0;
}

Но я должен признаться, что не понимаю, почему назначение

char d [] = "12345678";

считается ошибочным?

EDIT:

на машине SPARC нет строки SIGBUS в строке присвоения char d [].

Ответ 4

Intel очень велика для поддержки невыложенных нагрузок. Если бы мне приходилось обнаруживать такие нагрузки на платформе Intel, я бы подумал, что мне придется изменить valgrind для обработки неуравновешенных нагрузок как ошибок. Такая модификация не является тривиальной, но valgrind был разработан с учетом того, что пользователи могут создавать новые "инструменты". Я думаю, что простая модификация инструмента memcheck обнаружит ваши неустановленные ссылки. И отчет об ошибках действительно очень приятный.

Ответ 5

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

Изменить: очень рад быть доказанным.

Ответ 6

Много лет спустя: если ваш gcc/clang является достаточно новым (GCC 4.9, clang 3.3?), вы можете создать свой код с помощью дезактиватора поведения undefined (-fsanitize=undefined), чтобы получать предупреждения о несогласованных доступах на (но иметь в виду, что разные платформы имеют разные требования к выравниванию, разные компиляторы будут выбирать разные макеты и т.д.). См. https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html и https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ для получения более подробной информации.