我目前正在使用GCC 4.5.3,为PowerPC 440编译,并且正在编译一些不需要libc的代码。我没有直接调用memcpy(),但编译器似乎在构建期间插入了一个。
有像-nostdlib,-nostartfiles,-nodefaultlibs这样的链接器选项但我无法使用它们,因为我没有进行链接阶段。我只是在编译。有这样的事情:
$ powerpc-440-eabi-gcc -O2 -g -c -o output.o input.c
如果我用nm检查output.o,我会看到对memcpy的引用:
$ powerpc-440-eabi-nm output.o | grep memcpy
U memcpy
$
GCC手册页明确了如何使用链接器删除对memcpy和其他libc调用的调用,但我不希望编译器首先插入它们,因为我使用的是完全不同的链接器(不是GNU的ld,它不知道libc)。
感谢您提供的任何帮助。
答案 0 :(得分:6)
您需要使用-fno-builtin禁用该优化。尝试编译C库的memcpy时,我遇到过这个问题。它自称。糟糕!
答案 1 :(得分:5)
在某些情况下,Gcc会发出对memcpy的调用,例如,如果要复制结构。 无法更改GCC行为,但您可以尝试通过修改代码来避免此类复制。最好的办法是查看程序集,找出为什么gcc发出memcpy并尝试解决它。这会很烦人,因为你基本上需要了解gcc是如何工作的。
摘自http://gcc.gnu.org/onlinedocs/gcc/Standards.html:
GCC使用的大多数编译器支持例程都存在于libgcc中,但也有一些例外。 GCC要求独立环境提供memcpy,memmove,memset和memcmp。最后,如果使用了__builtin_trap,并且目标没有实现陷阱模式,那么GCC将发出中止调用。
答案 2 :(得分:3)
您还可以将二进制文件设为“独立”二进制文件:
ISO C标准(在第4节中)定义了两类符合要求的实现。符合标准的托管实现支持整个标准[...];只有提供某些图书馆设施才需要符合标准的独立实施:在,,,和;从AMD1开始,也是那些;在C99中,也是在和。 [...]。
该标准还为程序定义了两个环境,一个独立的环境,所有实现都需要,并且可能没有超出独立实现所需的库设施,其中程序启动和终止的处理是实现定义的,并且是托管的环境,这是不需要的,其中提供了所有库设施,并通过函数int main(void)或int main(int,char * [])启动。
操作系统内核将是一个独立的环境;使用操作系统功能的程序通常位于托管实现中。
(我添加的段落)
更多here。并且可以找到相应的gcc选项/ s(关键字-freestanding
或-fno-builtin
){。{3}}。
答案 3 :(得分:3)
不需要-fno-builtins
或-ffreestanding
,因为它们会不必要地禁用许多重要的优化
这实际上是由gcc的tree-loop-distribute-patterns“优化”的,所以要在保留有用的内置功能的同时禁用不需要的行为,你可以使用:
<强> -fno-tree-loop-distribute-patterns
强>
Musl-libc使用此标志进行构建,并在其配置脚本中有以下注释(我查看了源代码并找不到任何宏,因此应该就足够了)
#检查防止编译器可能需要的选项 #生成memcpy,memmove,memcmp,
的自引用版本 #和memset。真的,我们应该添加一个检查来确定是否这个 #选项就足够了,如果没有,添加一个宏来削弱这些 #function with volatile ...
#tryflag CFLAGS_MEMOPS -fno-tree-loop-distribute-patterns
您还可以使用其optimize属性将此属性作为属性添加到gcc中的各个函数,以便其他函数可以从调用mem*()
答案 4 :(得分:1)
这是一个很老的问题,但我遇到了同样的问题,这里的解决方案都没有奏效。
所以我定义了这个函数:
static __attribute__((always_inline)) inline void* imemcpy (void *dest, const void *src, size_t len) {
char *d = dest;
const char *s = src;
while (len--)
*d++ = *s++;
return dest;
}
然后用它代替memcpy。这已经永久解决了我的内联问题。但是,如果您正在编译某种库,则不是很有用。