我的操作系统是ubuntu 14.04 32位,我的源程序test.c是:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("test.");
return;
}
我用命令编译它:
gcc -S test.c
输出为test.s文件。我用命令组装它:
as -o test.o test.s
然后我想静态地将它与c标准库链接起来。我搜索了libc.a
文件,该文件位于/usr/lib/i386-linux-gnu/libc.a
。所以我试着用命令链接它:
ld test.o /usr/lib/i386-linux-gnu/libc.a
但是出现了很多错误消息:
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048210
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x20): undefined reference to `_Unwind_GetIP'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x45): undefined reference to `_Unwind_GetGR'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x50): undefined reference to `_Unwind_GetCFA'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `__backtrace':
(.text+0xb1): undefined reference to `_Unwind_Backtrace'
/usr/lib/i386-linux-gnu/libc.a(iofclose.o): In function `_IO_new_fclose':
(.text+0x1b1): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofclose.o):(.eh_frame+0x167): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofflush.o): In function `_IO_fflush':
(.text+0xd7): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofflush.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofputs.o): In function `_IO_fputs':
(.text+0xf9): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofputs.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofwrite.o): In function `_IO_fwrite':
(.text+0x139): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofwrite.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iogetdelim.o): In function `_IO_getdelim':
(.text+0x285): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iogetdelim.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(wfileops.o): In function `_IO_wfile_underflow':
(.text+0x5fc): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(wfileops.o):(.eh_frame+0x137): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(fileops.o): In function `_IO_new_file_underflow':
(.text+0x40b): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(fileops.o):(.eh_frame+0x1b3): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0xbc6): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0xc08): undefined reference to `__moddi3'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0x249d): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtod_l.o): In function `____strtod_l_internal':
(.text+0xcc9): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtod_l.o): In function `____strtod_l_internal':
(.text+0xd0b): undefined reference to `__moddi3'
...
...
我的问题是,为什么会出现这些错误消息?我正在努力学习编译系统是如何工作的,所以我不想知道如何解决这个问题,而是更希望知道它是如何实现的。似乎静态C库依赖于其他库,为什么以及这些库是什么?
编辑:
我这样做是因为我想知道事情是如何运作的,所以我宁愿避免使用gcc
脚本。
答案 0 :(得分:4)
您还需要crt0个启动对象文件(除了静态libc.a
),它们特别定义_start
入口点(在您的ELF可执行文件中)并包含ABI特定(prologue和epilog)代码,用于调用main
(最后处理atexit(3)个注册处理程序和stdio刷新)。还需要低级libgcc。细节复杂且具体实现。要理解它们,请将测试代码编译为
gcc -v -static test.c -o mytest
(避免调用可执行文件test
,因为它会与/usr/bin/test
或shell的内置版本冲突)
在实践中,至少与gcc
如果您感到好奇,请充分利用Linux free software并研究源代码(例如GCC,C standard library,binutils等。 ..)。您可能会发现musl-libc很有趣。
我宁愿避开
gcc
脚本
从技术上讲,gcc
不是脚本而是驱动程序(请参阅gcc/gcc.c源代码中的GCC)。但它会运行ld
,它确实会运行一些linker scripts。实际编译由cc1完成,由gcc
程序启动。
答案 1 :(得分:2)
您还必须链接gcc
内在库。最简单的方法是使用gcc
前端编译并链接-static
选项:
gcc -static -o test test.c
如果你坚持从汇编编译,你可以这样做:
gcc -static -o test test.s
您的系统可能不支持静态链接。
编辑:给gcc -v
选项会告诉你它执行了什么命令。