问题描述
我正在为LeetCode,Codeforces等编程竞赛开发一个在线裁判系统.对于大多数编程竞赛,C/C ++均不允许使用内联汇编程序,因此我想对系统添加相同的限制.
I'm developing an online judge system for programming contests like LeetCode, Codeforces, etc. As for most programming contests, inline assembler is not allowed in C/C++, so I would like to add the same restriction to my system.
我想让GCC和G ++在编译包含内联汇编程序的C/C ++程序时产生错误,以便任何包含内联汇编程序的代码都将导致编译错误.
I would like to let GCC and G++ produce an error when compiling a C/C++ program containing inline assembler, so that any code containing inline assembler will result in compilation error.
有没有办法做到这一点?我应该将一些命令行参数传递给GCC/G ++吗?
Is there a way to achieve that? Should I pass some command line arguments to GCC/G++?
注意:禁用内联汇编程序仅是为了遵守规则,而不是出于安全考虑.
Note: disabling inline assembler is just for obeying the rules, not for security concerns.
推荐答案
是否可以在GCC中禁用内联汇编程序?
是的,有两种方法.
Is there a way to disable inline assembler in GCC?
Yes there are a couple of methods.
要在编译阶段执行此操作,请使用参数-fno-asm
.但是,请记住,这只会影响asm
,而不会影响__asm__
.
To do it in compilation phase, use the parameter -fno-asm
. However, keep in mind that this will only affect asm
and not __asm__
.
文档:
不识别"asm
","inline
".或"typeof
"作为关键字,以便代码可以将这些单词用作标识符.您可以使用关键字"__asm__
","__inline__
"和"__typeof__
"反而. -ansi
表示-fno-asm
.
Do not recognize "asm
", "inline
" or "typeof
" as a keyword, so that code can use these words as identifiers. You can use the keywords "__asm__
", "__inline__
" and "__typeof__
" instead. -ansi
implies -fno-asm
.
在C ++中,此开关仅影响"typeof
"关键字,因为"asm
"和"inline
"是标准关键字.您可能想改用-fno-gnu-keywords
标志,这具有相同的效果.在C99模式(-std=c99
或-std=gnu99
)中,此开关仅影响"asm
".和"typeof
"关键字,因为"inline
"是ISO C99中的标准关键字.
In C++ , this switch only affects the "typeof
" keyword, since "asm
" and "inline
" are standard keywords. You may want to use the -fno-gnu-keywords
flag instead, which has the same effect. In C99 mode (-std=c99
or -std=gnu99
), this switch only affects the "asm
" and "typeof
" keywords, since "inline
" is a standard keyword in ISO C99.
定义宏
您可以使用参数-Dasm=error -D__asm__=error
请注意,此构造是通用的.它的作用是创建宏.它的工作原理很像#define
.该文档说:
Note that this construction is generic. What it does is to create macros. It works pretty much like a #define
. The documentation says:
对定义的内容进行标记和处理,就像它们出现在#define指令的第三翻译阶段中一样.特别是,该定义将被嵌入的换行符截断.
The contents of definition are tokenized and processed as if they appeared during translation phase three in a #define directive. In particular, the definition will be truncated by embedded newline characters.
...
因此,只需将asm
或__asm__
的出现更改为error
.这是在预处理阶段完成的.您不必使用error
.只要选择不会编译的东西即可.
So what it does is simply to change occurrences of asm
or __asm__
to error
. This is done in the preprocessor phase. You don't have to use error
. Just pick anything that will not compile.
如 zwol 的注释中所建议的那样,通过使用宏在编译阶段解决该问题的方法,您可以使用.如果存在一个名为error
的标识符,这也将解决该问题.
A way to solve it in compilation phase by using a macro, as suggested in comments by zwol, you can use -D'asm(...)=_Static_assert(0,"inline assembly not allowed")'
. This will also solve the problem if there exist an identifier called error
.
注意::此方法需要-std=c11
或更高版本.
Note: This method requires -std=c11
or higher.
另一种可能解决您问题的方法是,在编译之前仅在源树的根目录中执行grep
Yet another way that may be the solution to your problem is to just do a grep
in the root of the source tree before compiling:
grep -nr "asm"
这也将捕获__asm__
,但可能会产生误报,例如,您有包含字符串"asm"
的字符串文字,标识符或注释.但是根据您的情况,您可以通过在源代码中的任何位置禁止该字符串的出现来解决此问题.只需更改规则即可.
This will also catch __asm__
but it may give false positives, for instance is you have a string literal, identifier or comment containing the substring "asm"
. But in your case you could solve this problem by also forbidding any occurrence of that string anywhere in the source code. Just change the rules.
请注意,禁用汇编可能会导致其他问题.例如,我不能将stdio.h
与该选项一起使用.系统标题通常包含内联汇编代码.
Note that disabling assembly can cause other problems. For instance, I could not use stdio.h
with this option. It is common that system headers contains inline assembly code.
可以将字符串作为机器代码执行.参见以下示例答案: https://stackoverflow.com/a/18477070/6699433
It is possible to execute strings as machine code. See this answer for an example: https://stackoverflow.com/a/18477070/6699433
上面链接中的一部分代码:
A piece of the code from the link above:
/* 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的原始帖子中发表评论.
The code above is only intended to give a quick idea of how to trick the rules OP has stated. It is not intended to be a good example of how to actually perform it in reality. Furthermore, the code is not mine. It is just a short code quote from the link I supplied. If you have ideas about how to improve it, then please comment on 4pie0:s original post instead.
这篇关于有没有一种方法可以在GCC中禁用内联汇编程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!