Arm 使用musl交叉标记的标准库中对符号的未定义引用

Arm 使用musl交叉标记的标准库中对符号的未定义引用,arm,cross-compiling,musl,Arm,Cross Compiling,Musl,我正在使用一个针对arm的musl交叉编译器,它是用musl交叉生成(gcc 9.2.0,musl 1.2.0)构建的。当我用printf编译一个简单的hello world c程序时,我得到了标准库中符号的未定义引用: cross-musl/bin/arm-linux-musleabihf-gcc -c hello.c -o hello.o cross-musl/bin/arm-linux-musleabihf-ld hello.o -o hello.elf cross-musl/bin/a

我正在使用一个针对arm的musl交叉编译器,它是用musl交叉生成(gcc 9.2.0,musl 1.2.0)构建的。当我用printf编译一个简单的hello world c程序时,我得到了标准库中符号的未定义引用:

cross-musl/bin/arm-linux-musleabihf-gcc -c hello.c -o hello.o
cross-musl/bin/arm-linux-musleabihf-ld  hello.o -o hello.elf
cross-musl/bin/arm-linux-musleabihf-ld: warning: cannot find entry symbol _start; defaulting to 0000000000010074
cross-musl/bin/arm-linux-musleabihf-ld: hello.o: in function `main':
hello.c:(.text+0x18): undefined reference to `puts'
将libc.a和crt1.o添加到linker命令时,没有出现错误:

cross-musl/bin/arm-linux-musleabihf-gcc -c hello.c -o hello.o
cross-musl/bin/arm-linux-musleabihf-ld -Lcross-musl/arm-linux-musleabihf/lib -lc cross-musl/arm-linux-musleabihf/lib/crt1.o hello.o -o hello.elf

我认为没有使用-nostartfiles、-nostlib或-nodefaultlibs时,没有必要指定标准库和启动文件,或者我错了吗?

这就是GNU工具的工作方式gcc最聪明的地方,它不仅用于调用编译器,而且用于调用链接器,因为它知道一切都与它相关,这就是为什么在构建基于GNU的工具链时会看到所看到的东西。检查从gcc到链接器的调用并查看它是否指定了所有内容是很简单的。劳埃德不知道它在哪里,也没有办法弄清楚它在哪里,所以必须把一切都告诉他。这就是ld的设计方法。Linux程序和交叉编译器的简单示例

#include <stdlib.h>
int main ( void )
{
    exit(1);
}

arm-linux-gnueabi-gcc so.c -o so.o
如果你想把自己联系起来,那么你就必须指向一切。一个例外是默认的链接器脚本,因为您想替换您的C库,所以您也必须替换它

这或您在gcc中构建知识/机制,让它将新的库信息传递给链接器,而不是GNU C库信息/路径

另一个示例是x86本机:

gcc -O2 so.c -o so
[1][-plugin]
[2][/usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so]
[3][-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper]
[4][-plugin-opt=-fresolution=/tmp/ccmhqpU9.res]
[5][-plugin-opt=-pass-through=-lgcc]
[6][-plugin-opt=-pass-through=-lgcc_s]
[7][-plugin-opt=-pass-through=-lc]
[8][-plugin-opt=-pass-through=-lgcc]
[9][-plugin-opt=-pass-through=-lgcc_s]
[10][--sysroot=/]
[11][--build-id]
[12][--eh-frame-hdr]
[13][-m]
[14][elf_x86_64]
[15][--hash-style=gnu]
[16][--as-needed]
[17][-dynamic-linker]
[18][/lib64/ld-linux-x86-64.so.2]
[19][-z]
[20][relro]
[21][-o]
[22][so]
[23][/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o]
[24][/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o]
[25][/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o]
[26][-L/usr/lib/gcc/x86_64-linux-gnu/5]
[27][-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu]
[28][-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib]
[29][-L/lib/x86_64-linux-gnu]
[30][-L/lib/../lib]
[31][-L/usr/lib/x86_64-linux-gnu]
[32][-L/usr/lib/../lib]
[33][-L/usr/lib/gcc/x86_64-linux-gnu/5/../../..]
[34][/tmp/ccg1E03e.o]
[35][-lgcc]
[36][--as-needed]
[37][-lgcc_s]
[38][--no-as-needed]
[39][-lc]
[40][-lgcc]
[41][--as-needed]
[42][-lgcc_s]
[43][--no-as-needed]
[44][/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o]
[45][/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o]
同样的交易,ld不知道任何东西在哪里,C库,它的引导程序,gcc库,等等…这些都被煮成了gcc,可能是设计的。(gcc当然是一个包装器,它调用多个程序来编译解析器和其他一些程序,然后是实际的编译器,然后是汇编器,然后是链接器,也许还有其他一些程序,比如汇编程序,ld just links)

很多人都熟悉baremetal,因此不使用C库或其他东西,因此链接器脚本有点微不足道(当然不会像ld file.o-o file.elf那样微不足道,除非您为该目标创建了手工环境)。当您想要添加库时,您可以向gcc教授它,或者将它所需的所有内容传递给链接器

-例如,lgcc仅仅意味着在-L指定路径中查找libgcc,没有-L指定路径,没有乐趣,因为ld不知道binutils之外的事情,可能在本地查找


binutils是一组UTIL。gcc是一个更高的级别,依赖于binutils(或替代品)。gcc离不开binutils,bintuils当然离不开gcc,这和Unix的方式一样,很明显,gcc将binutils之外的所有东西都传递给binutils,以便它成为gcc的二进制实用程序。

@old\u timer谢谢,你说得对。当我启动gcc而不是ld来生成可执行文件时,我没有未解析的外部:

arm-linux-musleabihf-gcc -c hello.c -o hello.o
arm-linux-musleabihf-gcc -o hello.elf  hello.o

因为引导程序在C库中,而不是编译器的一部分(显然也不是您的代码)。您仍然需要检查输出,确认链接器脚本与目标匹配,并且代码可以引导/运行。检查对链接器的普通gcc hello.c-o hello调用是什么样子。它有路径/库。@old_timer:这个工具链的目标是linux,而不是裸机目标,所以这应该可以工作,不是吗@ErwinP:我可以使用
https://musl.cc/armel-linux-musleabihf-cross.tgz
-你并不孤单。工具链不知道两者的区别,是吗?它只是一个愚蠢的编译器和链接器。当您的编译器执行linking.lol时,请检查链接器调用,对于x86 linux,链接器脚本调用是masive,不能在这里使用,但是像x86_64-linux-gnu/crti.o和-L/lib/x86_64-linux-gnu以及-lc和-lgcc之类的东西会跳出there@old_timer:
armnonelinuxgnueabihfld-o hello.elf hello.o
工作正常。
arm-linux-musleabihf-gcc -c hello.c -o hello.o
arm-linux-musleabihf-gcc -o hello.elf  hello.o