Есть ли способ отключить встроенный ассемблер в GCC? - PullRequest
4 голосов
/ 16 марта 2019

Я разрабатываю онлайн-систему судейства для конкурсов по программированию, таких как LeetCode, Codeforces и т. Д. Что касается большинства конкурсов по программированию, встроенный ассемблер не разрешен в C / C ++, поэтому я хотел бы добавить такое же ограничение в мою систему.

Я бы хотел, чтобы GCC и G ++ выдавали ошибку при компиляции программы на C / C ++, содержащей встроенный ассемблер, так что любой код, содержащий встроенный ассемблер, приведет к ошибке компиляции.

Есть ли способ достичь этого?Должен ли я передать некоторые аргументы командной строки в GCC / G ++?

Примечание: отключение встроенного ассемблера только для соблюдения правил, а не из соображений безопасности.

1 Ответ

10 голосов
/ 16 марта 2019

Есть ли способ отключить встроенный ассемблер в GCC?

Да, есть несколько способов.

Отключить сборку в компиляторе

Чтобы сделать это на этапе компиляции, используйте параметр -fno-asm.Однако имейте в виду, что это повлияет только на asm, а не __asm__.

Документация:

-fno-asm

Не распознавать "asm "," inline "или" typeof "в качестве ключевого слова, чтобы код мог использовать эти слова в качестве идентификаторов.Вместо этого вы можете использовать ключевые слова "__asm__", "__inline__" и "__typeof__".-ansi подразумевает -fno-asm.

В C ++ этот переключатель влияет только на ключевое слово "typeof", поскольку "asm" и "inline" являются стандартными ключевыми словами.Вместо этого вы можете использовать флаг -fno-gnu-keywords, который имеет тот же эффект.В режиме C99 (-std=c99 или -std=gnu99) этот переключатель влияет только на ключевые слова "asm" и "typeof", поскольку "inline" является стандартным ключевым словом в ISO C99.

Определение макроса

Вы можете использовать параметры -Dasm=error -D__asm__=error

Обратите внимание, что эта конструкция является общей.Что он делает, это создает макросы.Это работает почти как #define.Документация гласит:

-D name=definition

Содержимое определения маркируется и обрабатывается так, как если бы оно появилось на третьем этапе перевода в директиве #define.В частности, определение будет усечено встроенными символами новой строки.

...

Итак, он просто меняет вхождения asm или __asm__ на error.Это делается на этапе препроцессора.Вам не нужно использовать error.Просто выберите все, что не будет компилироваться.

Использовать макрос, который запускается во время компиляции

Способ решения этой проблемы на этапе компиляции с помощью макроса, как предложено в комментариях zwol , вы можете использовать -D'asm(...)=_Static_assert(0,"inline assembly not allowed")'.Это также решит проблему, если существует идентификатор с именем error.

Примечание: Этот метод требует -std=c11 или выше.

Использование grep перед использованием gcc

Еще один способ, который может решить вашу проблему, это просто сделать grep в корне дерева исходного кода перед компиляцией:

grep -nr "asm"

Это также перехватит __asm__ но он может давать ложные срабатывания, например, если у вас есть строковый литерал, идентификатор или комментарий, содержащий подстроку "asm".Но в вашем случае вы можете решить эту проблему, также запретив любое вхождение этой строки в любом месте исходного кода.Просто измените правила.

Возможные непредвиденные проблемы

Обратите внимание, что отключение сборки может вызвать другие проблемы.Например, я не мог использовать stdio.h с этой опцией.Обычно системные заголовки содержат встроенный код ассемблера.

Способ обмана вышеуказанных методов

Строки можно выполнять как машинный код.См. Этот ответ для примера: https://stackoverflow.com/a/18477070/6699433

Часть кода по ссылке выше:

/* our machine code */
char code[] = {0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x48,
0x89,0x75,0xf0,0xb8,0x2a,0x00,0x00,0x00,0xc9,0xc3,0x00};

/* copy code to executable buffer */    
void *buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
            MAP_PRIVATE|MAP_ANON,-1,0);
memcpy (buf, code, sizeof(code));

/* run code */
int i = ((int (*) (void))buf)();

Код выше предназначен только для того, чтобы дать быстрое представление о том, как обманутьПравила ОП изложены.Это не предназначено, чтобы быть хорошим примером того, как фактически выполнить это в действительности.Кроме того, код не мой.Это просто краткая цитата из ссылки, которую я предоставил.Если у вас есть идеи о том, как его улучшить, прокомментируйте вместо этого оригинальный пост 4pie0:

...