ARM-NONE-EABI链接链中对memcpy的未定义引用

ARM-NONE-EABI链接链中对memcpy的未定义引用,c,arm,linker-errors,C,Arm,Linker Errors,我正在编译并链接一个裸机应用程序。在本例中,是用于AES加密的简单标准c代码(我自己没有编写,但我仔细阅读了它,它似乎不需要任何库) 我的问题出现在链接时。这是使用的链接器命令 arm-none-eabi-ld boot_and_link/startup.o drivers/gpio.o ../programs/aes_e/aes.o ../programs/aes_e/aes_test.o ../programs/aes_e/key_expansion.o -nostartfiles -T

我正在编译并链接一个裸机应用程序。在本例中,是用于AES加密的简单标准c代码(我自己没有编写,但我仔细阅读了它,它似乎不需要任何库)

我的问题出现在链接时。这是使用的链接器命令

arm-none-eabi-ld boot_and_link/startup.o drivers/gpio.o  ../programs/aes_e/aes.o ../programs/aes_e/aes_test.o ../programs/aes_e/key_expansion.o -nostartfiles -T boot_and_link/linker.ld -o ../programs/aes_e/aes_e.elf -L/usr/lib/gcc/arm-none-eabi/4.8/armv6-m -lgcc
我已经编写了自己的链接器脚本和启动代码。我得到三个类似这样的错误:

.../programs/aes_e/aes_test.c:41: undefined reference to `memcpy'
unsigned char key[16] =
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
从这样的三行:

.../programs/aes_e/aes_test.c:41: undefined reference to `memcpy'
unsigned char key[16] =
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
在主功能中。我可以通过简单地剪切这三行并将它们放在主函数之外来消除这些错误。这告诉我,main函数中的上面一行需要将数据从一个内存段复制到另一个内存段。(如果我错了,请纠正我)。现在我已经了解到memcpy是在libgcc.a中定义的。我甚至对它进行了grep(在armv6-m体系结构的目录中),并得到了一个匹配项(二进制文件。/libgcc.a匹配项是grep命令的结果)

所以我的问题是,为什么这个错误会持续存在?我需要和其他图书馆联系吗


我只是想澄清一下,除了我自己编写的其他文件(没有string.hn stddefs.h或任何这些文件),我的任何源文件中都没有包含任何内容。

我的嵌入式系统裸应用程序也遇到了这个问题。 我没有在代码中使用
memcopy()
。 这是我的问题代码main.c:

void main()
{
  unsigned char arr[]={'a','b','c'};
  for(int i=0;sizeof(arr);i++)
  {
     putc(arr[i]);
  }
}
将其编译为:

CFLAGS= -march=armv4t -Wall -nodefaultlibs \
        -nostdlib -nostartfiles -fno-builtin\
        -nostdinc -Wstrict-prototypes -std=gnu11

$(CROSS_COMPILE)gcc $(CFLAGS) -c -o main.o main.c
当我链接时:

$(CROSS_COMPILE)ld -Txxx.lds -o main main.o
错误:

main.c:(.text+0x48): undefined reference to `memcpy'
我修改了我的代码:

void main()
    {
      unsigned char arr[3];
      arr[0]='a';
      arr[1]='b';
      arr[2]='c';
      for(int i=0;sizeof(arr);i++)
      {
         putc(arr[i]);
      }
    }
很好

所以我认为特性
无符号字符arr[]={'a','b','c'}依赖memcopy()


您可以修改代码或提供自己的memcopy()。

通常您应该完全依赖编译驱动程序,而不是显式地调用链接器,但如果您确实想这样做,您必须显式地告诉链接器链接标准库(通常标记
-lc


编译器可以更改位置,在那里它可以使用memcpy优化代码,并且编译器要求它存在。

数组是例程中的一个变量,编译器使用memcpy将其复制到堆栈中

如果将其定义为“static const”,它将进入静态存储,而不需要复制

static const unsigned char key[16] =
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
  0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

在使用
arm-none-eabi
toolchain创建裸机应用程序时,我也遇到了同样的问题

我实现了以下功能:

u8* strcpy(u8 *s1, u8 *s2)
{
...
}
并在我的代码中使用它:

strcpy((u8 *)tp->clock, "00:00:00");
然后
arm none eabi ld
总是抱怨:

undefined reference to `memcpy'
在我将下面的选项添加到编译器选项后,错误消失了

-fno内置

根据:

在不使用-fno内置项进行编译时,编译器可以替换对的调用 具有内联代码或调用的某些标准C库函数 其他图书馆职能。Arm®体系结构的运行时ABI 列出编译器可以使用的库函数这意味着 标准C库函数的重新实现可能不会 被使用,并且可能被链接器删除。

因此,我比较了使用和不使用
-fno内置
选项的反汇编

-fno内置

 404:   ebfffffe    bl  0 <memcpy>
 3f8:   ebfffffe    bl  0 <strcpy> 

所以我们可以看到,编译器在幕后做了一些事情。

AFAIK,
memcpy
是一个libc函数,裸机应用程序可能不会有这个函数。它似乎没有在libgcc中定义。尽管libgcc确实有一个
memcpy
,但没有实现它。那么,这就可以解释它了。谢谢。如果可能,请声明数组
静态常量
,编译器将不会调用
memcpy()
。还有可能的
-fsome选项
将内联此memcpy;但它会使代码变得更大,这可能是我们试图避免的。当然,您可以提供自己的
memcpy()
;像a。这似乎是一个纯金属平台。我怀疑他是否会有一个可用的libc来链接。是的,它确实是一个纯金属平台,AFAIK newlib的设计可以很好地与纯金属拱门配合使用。它提供了libc-libm和libg。在微控制器上,二进制大小变得太大。除非真的有必要,否则最好避免调用memcpy和链接libc。我认为这是最好的解决方案!