我目前使用的是GCC 4.5.3,为PowerPC 440编译,并且正在编译一些不需要libc的代码。我没有任何对memcpy()的直接调用,但编译器似乎在编译过程中插入了一个。
有一些链接器选项,如-nostdlib,-nostartfiles,-nodefaultlibs,但我无法使用它们,因为我没有在链接阶段。我只是在编译。
$ powerpc-440-eabi-gcc -O2 -g -c -o output.o input.c
如果我用nm检查输出.o,我会看到对memcpy的引用:
$ powerpc-440-eabi-nm output.o | grep memcpy
U memcpy
$
GCC手册页清楚地说明了如何使用链接器删除对memcpy的调用和其他libc调用,但我不希望编译器首先插入它们,因为我使用的是一个完全不同的链接器(不是GNU的ld,它不知道libc)。
谢谢你能提供的任何帮助。
5条答案
按热度按时间cgfeq70w1#
不需要
-fno-builtins
或-ffreestanding
,因为它们将不必要地禁用许多重要的优化这实际上是由gcc的tree-loop-distribute-patterns "优化"的,所以要在保留有用的内置功能的同时禁用不需要的行为,您可以使用:
Musl-libc使用这个标记来构建,并且在他们的configure脚本中有以下注解(我查看了源代码,没有发现任何宏,所以这应该足够了)
检查可能需要哪些选项来防止编译器
#生成memcpy、memmove、memcmp、
#和memset。实际上,我们应该添加一个检查来确定
#选项就足够了,如果不够,请添加一个宏来削弱它们
#具有volatile的函数...
#tryflag CFLAGS_MEMOPS-无树循环分布模式
您还可以使用其optimize属性将其作为属性添加到gcc中的各个函数,以便其他函数可以从调用
mem*()
中受益或者,(至少现在)可以在循环中添加一个混淆的空asm语句,以阻碍模式识别。
wz8daaqr2#
在某些情况下,Gcc会发出对memcpy的调用,例如,如果你正在复制一个结构。没有办法改变GCC的行为,但是你可以通过修改代码来避免这种情况。最好的办法是查看程序集,找出gcc发出memcpy的原因,并尝试解决它。尽管这会很烦人,因为你基本上需要了解gcc是如何工作的。
从http://gcc.gnu.org/onlinedocs/gcc/Standards.html中提取:
GCC使用的大多数编译器支持例程都存在于libgcc中,但也有少数例外。GCC要求独立环境提供memcpy、memmove、memset和memcmp。最后,如果使用了__builtin_trap,而目标没有实现陷阱模式,那么GCC将发出一个调用来中止。
r1zk6ea13#
你需要用-fno-builtin来禁用一个优化。我曾经在为一个C库编译memcpy时遇到过这个问题。它自己调用了。哎呀!
bnlyeluc4#
你也可以让你的二进制文件成为一个“独立的”二进制文件:
ISO C标准(在第4章)定义了两类符合标准的实现,符合标准的托管实现支持整个标准[...];符合的独立实现仅需要提供某些库设施:、、和中的那些;自AMD 1以来,还包括;和在C99中,还有那些在和中。[...]。
该标准还定义了两种程序环境:独立环境,所有实现都需要,并且除了独立实现所需的库设施之外,可能没有库设施,其中程序启动和终止的处理是由实现定义的;以及托管环境,不需要,其中提供了所有库设施,并且通过函数int main(void)或int main(int,char *[])启动。
操作系统内核是一个独立的环境;使用操作系统的设施的程序通常处于托管实现中。
更多的here和相应的gcc选项(关键字
-ffreestanding
或-fno-builtin
)可以在这里找到。vbkedwbf5#
这是一个很老的问题,但我也遇到过同样的问题,这里的解决方案都不起作用。
所以我定义了这个函数:
然后用它来代替memcpy。这为我永久地解决了内联问题。但是如果你正在编译某种库,那就不是很有用了。