尝试使用静态 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
程序启动。
我的 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
程序启动。