使用LLVM opt&llc配合ld链接含C库程序时出现错误
解决LLVM工具链编译依赖C库程序的链接失败问题
我明白你现在在学习LLVM&Clang做项目,用到了opt、llc这些优化工具,但编译调用printf的简单程序时卡在了链接环节——这其实是个很常见的坑,因为ld不像clang那样会自动帮你处理标准库和启动代码的依赖。
先确认你的前期操作流程是完全正确的:
clang -c -emit-llvm main.c生成LLVM bitcode文件main.bcopt -O3 main.bc -o optimized.bc用opt完成O3级优化llc -march=x86-64 -filetype=obj optimized.bc -o prog.o把优化后的bitcode编译成目标文件prog.o
问题出在最后一步的ld链接:ld是底层链接器,它不会自动帮你链接标准C库(libc)和程序启动所需的初始化/清理代码(那些crt开头的目标文件),所以会报找不到printf或者_start之类的符号错误。
两种解决方法:
方法一:用clang代替ld完成链接(推荐)
clang作为前端工具,会自动处理所有依赖,你只需要把生成的prog.o传给它就行:
clang prog.o -o prog
执行完这个命令,直接运行./prog就能看到输出"hallo"了,简单省心。
方法二:手动用ld指定所有依赖(适合理解链接过程)
如果非要用ld手动链接,你需要明确指定动态链接器、启动代码文件和标准C库。以x86-64的Linux系统为例,命令大概是这样的:
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o prog.o /usr/lib/x86_64-linux-gnu/crtn.o -lc
这里每个部分的作用:
-dynamic-linker /lib64/ld-linux-x86-64.so.2:指定动态链接器的路径,负责加载动态库crt1.o、crti.o、crtn.o:这些是程序启动和退出时需要的初始化/清理代码,负责调用main函数之前的准备工作,以及退出后的收尾-lc:链接标准C库(libc.so),这样就能找到printf的实现了
注意:不同系统的crt文件路径可能不一样,如果上面的路径不对,可以用gcc -print-file-name=crt1.o来查找正确的路径。
内容的提问来源于stack exchange,提问作者MartinM
相关产品推荐
相关产品推荐

