我正在编译和连接裸机应用程序。在这种情况下,简单的标准c代码(我自己不写,但我仔细阅读,似乎不需要任何库)进行AES加密。
链接时出现问题。这是使用的链接器命令。
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 };
在主要功能中。我可以通过简单地切割这三行并将它们放在主函数之外来消除这些错误。这告诉我,main函数内部的行需要将数据从一个内存区复制到另一个内存区。 (如果我错了,请纠正我)。现在我已经读过memcpy是在libgcc.a中定义的。我甚至为它(在armv6-m架构的目录中)进行了搜索,我得到了一个匹配(二进制文件./libgcc.a与grep命令相匹配)。
所以我的问题就变成为什么这个错误仍然存在?我是否需要与其他图书馆联系?
只是为了澄清我的任何源文件都没有包含,除了我自己写的其他文件(没有string.hn stddefs.h或其中任何一个)。
答案 0 :(得分:3)
数组是例程中的变量,编译器使用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 };
答案 1 :(得分:2)
我在嵌入式系统的裸应用程序中也遇到了这个问题。
我在代码中没有使用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]);
}
}
很好。
所以我认为功能unsigned char arr[]={'a','b','c'};
依赖于memcopy()。
您可以修改代码或提供自己的memcopy()。
答案 2 :(得分:1)
通常你应该完全依赖编译驱动程序而不是显式调用链接器,但是如果你真的想这样做,你必须明确告诉链接器链接标准库(通常是标志-lc
)。
允许编译器更改位置,可以使用memcpy优化代码,编译器要求它存在。
答案 3 :(得分:0)
在使用arm-none-eabi
工具链创建裸机应用程序时,我遇到了同样的问题。
我实现了以下功能:
u8* strcpy(u8 *s1, u8 *s2)
{
...
}
并在我的代码中使用它:
strcpy((u8 *)tp->clock, "00:00:00");
然后arm-none-eabi-ld
总是这样:
undefined reference to `memcpy'
将以下选项添加到编译器选项后,错误消失了。
-fno-builtin
根据here:
不使用-fno-builtin进行编译时,编译器可以替换对 某些标准C库函数(带有内联代码或对的调用) 其他库函数。 Arm®架构的运行时ABI 列出了编译器可以使用的库函数。 这意味着 您对标准C库函数的重新实现可能不会 会被链接器删除。
因此,我比较了带有和不带有-fno-builtin
选项的反汇编。
没有-fno-builtin
:
404: ebfffffe bl 0 <memcpy>
使用-fno-builtin
:
3f8: ebfffffe bl 0 <strcpy>
所以我们可以看到,这是编译器在幕后做的事情。