有没有办法在GCC中禁用内联汇编程序?

问题描述 投票:4回答:1

我正在为LeetCode,Codeforces等编程竞赛开发一个在线评判系统。对于大多数编程竞赛,在C / C ++中不允许使用内联汇编程序,所以我想对我的系统添加相同的限制。

我想在编译包含内联汇编程序的C / C ++程序时让GCC和G ++产生错误,这样任何包含内联汇编程序的代码都会导致编译错误。

有没有办法实现这一目标?我应该将一些命令行参数传递给GCC / G ++吗?

注意:禁用内联汇编程序只是为了遵守规则,而不是出于安全考虑。

c++ c gcc g++ inline-assembly
1个回答
10
投票

有没有办法在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指令的翻译阶段3中出现一样。特别是,定义将被嵌入的换行符截断。

...

所以它的作用只是将asm__asm__的出现改为error。这是在预处理器阶段完成的。你不必使用error。只需挑选任何无法编译的东西。

使用在编译期间触发的宏

zwol的评论中所建议的那样,在编译阶段使用宏来解决它的方法,你可以使用-D'asm(...)=_Static_assert(0,"inline assembly not allowed")'。如果存在名为error的标识符,这也将解决问题。

注意:此方法需要-std=c11或更高版本。

在使用gcc之前使用grep

另一种可能解决问题的方法是在编译之前在源树的根目录中执行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)();

上面的代码只是为了快速了解如何欺骗OP规定的规则。它并不是一个如何在现实中实际执行它的好例子。此外,代码不是我的。它只是我提供的链接的简短代码报价。如果您有关于如何改进它的想法,那么请评论4pie0:s原始帖子。

© www.soinside.com 2019 - 2024. All rights reserved.