尝试使用静态 C 标准库 link 时出错

error when trying to link with static c standard library

我的 OS 是 ubuntu 14.04 32 位,我的源程序 test.c 是:

#include <stdio.h>
int main(int argc, char *argv[])
{
        printf("test.");
        return;
}

我用命令编译它:

gcc -S test.c

输出为 test.s 文件。我用命令 assemble :

as -o test.o test.s

然后我想 link 它与 c 标准库静态地。我搜索了 libc.a 文件,找到它在 /usr/lib/i386-linux-gnu/libc.a。所以我尝试使用命令link它:

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 脚本。

您还必须 link gcc 内部库。最简单的方法是使用 gcc 前端编译和 link 加上 -static 选项:

gcc -static -o test test.c

如果你坚持要从汇编编译,你可以这样做:

gcc -static -o test test.s

您的系统可能不支持静态 linking。

编辑:给 gcc -v 选项会告诉你它执行什么命令。

你还需要crt0 startup object files (in addition of static libc.a), which notably are defining the _start entry point (in your ELF executable) and contain ABI specific (prologue and epilog) code to call your main (and finally process atexit(3) registered handlers and stdio flushing). The low-level libgcc也需要。细节很复杂并且特定于实现。要理解它们,请将您的测试代码编译为

gcc -v -static test.c -o mytest

(避免调用可执行文件 test,因为它会与 /usr/bin/test 或 shell 的内置冲突)

实际上,至少 link 和 gcc

更好

如果您好奇,请利用 Linux 大部分 free software and study the source code (e.g. of GCC, of the C standard library, of binutils, etc...). You might find musl-libc 有趣。

I'd rather avoid the gcc script

从技术上讲,gcc不是一个脚本,而是一个驱动程序(参见gcc/gcc.c in the source code of GCC). But it will run ld which indeed runs some linker scripts. The actual compilation is done by cc1,它由gcc程序启动。