一 点睛
在成功汇编之后,就进入了链接阶段。链接主要是为了解决多个文件之间符号引用的问题。编译时编译器只对单个文件进行处理,如果该文件里面需要引用到其他文件中符号(例如全局变量或者某个函数库中的函数),那么这时在这个文件中该符号的地址是没法确定的,只能等链接器把所有的目标文件连接到一起才能确定最终的地址,最终生成可执行文件。
当所有目标文件都生成之后,gcc就在内部调用链接器ld完成链接工作。在链接阶段,所有的目标文件被安排在可执行文件的恰当位置。
值的注意的是,在Linux系统中,可执行文件没有统一的后缀,系统从文件属性来区分可执行文件和不可执行文件。
二 函数库介绍
我们看看下面C源代码
#include <stdio.h>
int main(int argc,char *argv[])
{
printf("hello, boy \n" );
return 0;
}
程序中并没有定义printf的函数实现,且在预编译中包含进来的“stdio.h”中也只有该函数的声明,而没有定义函数的实现。GUN组织把这些函数实现都放到名为libc.so.6的库中去了,该文件是GNU的标准C函数库,里面实现了printf。gcc会到系统默认的搜索路径“usr/lib64”下查找libc.so.6,然后就可以发现printf在libc.so.6中的实现,这样printf函数的地址就确定了,即printf符号的引用问题就解决了,就不会报链接时候的错误,比如找不到函数实现等。
这就是链接的作用。libc.so.6是Linux下的GNU C函数库(glibc),是gcc在编译时默认使用的C函数库。查看当前系统glibc的版本:
[root@localhost test]# /lib64/libc.so.6
GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.8.5 20150623 (Red Hat 4.8.5-16).
Compiled on a Linux 3.10.0 system on 2017-11-30.
Available extensions:
The C stubs add-on version 2.1.2.
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
RT using linux kernel aio
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
当前glibc的版本是2.17。注意,/lib64是一个文件夹链接,它的真实文件夹是/usr/lib64。glibc是GNU组织对C的标准实现库,是操作系统UNIX/Linux的基石之一。
微软也有自己的C标准库,叫msvcrt;嵌入式行业里还常用uClibc,是一个迷你版的C标准实现库。