在不插入对memcpy的调用的情况下编译GCC

xoshrz7s  于 2022-12-27  发布在  其他
关注(0)|答案(5)|浏览(187)

我目前使用的是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)。
谢谢你能提供的任何帮助。

cgfeq70w

cgfeq70w1#

不需要-fno-builtins-ffreestanding,因为它们将不必要地禁用许多重要的优化
这实际上是由gcc的tree-loop-distribute-patterns "优化"的,所以要在保留有用的内置功能的同时禁用不需要的行为,您可以使用:

    • 一米二米一x**

Musl-libc使用这个标记来构建,并且在他们的configure脚本中有以下注解(我查看了源代码,没有发现任何宏,所以这应该足够了)

检查可能需要哪些选项来防止编译器

#生成memcpy、memmove、memcmp、
#和memset。实际上,我们应该添加一个检查来确定
#选项就足够了,如果不够,请添加一个宏来削弱它们
#具有volatile的函数...
#tryflag CFLAGS_MEMOPS-无树循环分布模式
您还可以使用其optimize属性将其作为属性添加到gcc中的各个函数,以便其他函数可以从调用mem*()中受益

__attribute__((optimize("no-tree-loop-distribute-patterns")))
size_t strlen(const char *s){ //without attribute, gcc compiles to jmp strlen
  size_t i = -1ull;
  do { ++i; } while (s[i]);
  return i;
}

或者,(至少现在)可以在循环中添加一个混淆的空asm语句,以阻碍模式识别。

size_t strlen(const char *s){
    size_t i = -1ull;
    do {
        ++i;
        asm("");
    } while (s[i]) ;
    return i;
}
wz8daaqr

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将发出一个调用来中止。

r1zk6ea1

r1zk6ea13#

你需要用-fno-builtin来禁用一个优化。我曾经在为一个C库编译memcpy时遇到过这个问题。它自己调用了。哎呀!

bnlyeluc

bnlyeluc4#

你也可以让你的二进制文件成为一个“独立的”二进制文件:
ISO C标准(在第4章)定义了两类符合标准的实现,符合标准的托管实现支持整个标准[...];符合的独立实现仅需要提供某些库设施:、、和中的那些;自AMD 1以来,还包括;和在C99中,还有那些在和中。[...]。
该标准还定义了两种程序环境:独立环境,所有实现都需要,并且除了独立实现所需的库设施之外,可能没有库设施,其中程序启动和终止的处理是由实现定义的;以及托管环境,不需要,其中提供了所有库设施,并且通过函数int main(void)或int main(int,char *[])启动。
操作系统内核是一个独立的环境;使用操作系统的设施的程序通常处于托管实现中。

  • (由本人增补)*

更多的here和相应的gcc选项(关键字-ffreestanding-fno-builtin)可以在这里找到。

vbkedwbf

vbkedwbf5#

这是一个很老的问题,但我也遇到过同样的问题,这里的解决方案都不起作用。
所以我定义了这个函数:

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。这为我永久地解决了内联问题。但是如果你正在编译某种库,那就不是很有用了。

相关问题