Запретить невыровненный доступ к памяти на x86/x86_64
Я хочу эмулировать систему с запрещенным доступом к памяти без выравнивания на x86/x86_64. Есть ли какой-нибудь инструмент отладки или специальный режим для этого?
Я хочу запустить много (интенсивно использующих процессор) тестов на нескольких компьютерах x86 / x86_64 при работе с программным обеспечением (C/C++), разработанным для SPARC или другого подобного процессора. Но мой доступ к Sparc ограничен.
Как я знаю, Sparc всегда проверяет выравнивание в памяти для чтения и записи на естественность (чтение байта с любого адреса, но чтение 4-байтового слова допускается только тогда, когда адрес делится на 4).
Может быть, у Valgrind или PIN есть такой режим? Или специальный режим компилятора? Я ищу некоммерческий инструмент для Linux, но инструменты для Windows тоже разрешены.
или может быть есть секретный флаг процессора в EFLAGS?
4 ответа
Это сложно, и я не сделал это лично, но я думаю, что вы можете сделать это следующим образом:
Процессоры x86_64 (в частности, я проверил Intel Corei7, но я думаю, что и другие) имеют счетчик производительности MISALIGN_MEM_REF, который подсчитывает неправильные ссылки на память.
Итак, прежде всего, вы можете запустить свою программу и использовать инструмент "perf" под Linux, чтобы получить счетчик количества смещенных обращений, которые ваш код сделал.
Более хитрым и интересным хаком было бы написание модуля ядра, который программирует счетчик производительности, чтобы генерировать прерывание при переполнении и заставлять его переполнять первую невыровненную загрузку / сохранение. Ответьте на это прерывание в вашем модуле ядра, но отправьте сигнал вашему процессу.
Это, по сути, превратит x86_64 в ядро, которое не поддерживает выравниваемый доступ.
Это не будет простым, хотя - помимо вашего кода, системные библиотеки также используют не выровненный доступ, поэтому будет сложно отделить их от вашего собственного кода.
Я только что прочитал вопрос. Всегда ли неполный доступ к памяти вызывает ошибки шины? которая связана со статьей Википедии Ошибка сегментации.
В этой статье есть замечательное напоминание о довольно необычных флагах процессоров In tel AC Alkament Check.
А вот как это включить (из ошибки сегментации):
#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
После включения он работает так же, как настройки выравнивания ARM в /proc/cpu/alignment
, см. ответ Как перехватить доступ к памяти без выравнивания? Например.
Кроме того, если вы используете GCC, я предлагаю вам включить -Wcast-align
предупреждения. При создании цели со строгими требованиями к выравниванию (например, ARM) GCC будет сообщать о местах, которые могут привести к не выровненному доступу к памяти.
И GCC, и Clang имеют встроенный UndefinedBehaviorSanitizer. Одна из этих проверок,
alignment
, можно включить с помощью
-fsanitize=alignment
. Он выдаст код для проверки выравнивания указателя во время выполнения и прервет работу, если невыровненные указатели будут разыменованы.
Возможно, вы как-то могли бы скомпилировать в SSE со всеми согласованными ходами. Выровненный доступ с movaps
являются незаконными и, вероятно, будут вести себя как незаконный доступ к другим архитектурам.