编译链接

本文,解析Linux C/C++ 可执行程序的编译链接。

编译全过程:
hello.c —1— hello.i —2— hello.s —3— hello.o —4— a.out/hello

细化步骤解剖:

(1)预处理:gcc -E hello.c -o hello.i
-E只对文件进行预处理,不编译汇编、链接
编译器对各种预处理命令进行处理:头文件包含、宏定义扩展、条件编译选择等
hello.c(C源文件)——hello.i(C源文件)
file hello.i输出:
hello.i:      C source, ASCII text

(2)编译:gcc -S hello.i
-S只对文件进行编译,不汇编、链接
将预处理得到的源文件,进行“翻译转换”,产生出机器语言的目标程序
hello.i(C源文件)——hello.s(汇编文件)
file hello.s输出:
hello.s:      assembler source, ASCII text

(3)汇编:gcc -c hello.s
-c只对文件进行编译,不链接
将汇编文件翻译为可重定位文件(relocatable)
hello.s(汇编文件)——hello.o(relocatable)
file hello.o输出:
hello.o:      ELF 32-bit LSB relocatable , Intel 80386, version 1 (SYSV), not stripped

(4)链接:gcc hello.o -o hello
进行链接,生成可执行文件
处理可重定向文件,把各种符号引用和符号定义转换为可执行文件中的合适信息(虚拟地址)
hello.o(relocatable)——a.out/hello(可执行文件)
file a.out输出:
ELF 32-bit LSB executable , Intel 80386, version 1 (SYSV), dynamically linked , interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=d4bf39d5b3e516e739864f738d408212334f9d35, not stripped

PS:上述根据编译链接的整体过程,不断的推进,所以彼此间的文件出现:“下一步依赖上一步”的关系。

解析
  1. (1)步骤的-o选项,是表示-E选项操作输出到hello.i文件中,-o意为output,确定输出文件名字,同理(4)步骤也是
  2. .o称为可重定向文件(relocatable),是因为<链接>将把地址转化为虚拟地址,提供程序链接运行使用。
  3. 实际开发:
    1. 直接生成xxx.o、或链接库xxx.so/xxx.a
    2. 链接依赖库,生成a.out

补充:

静态链接
gcc hello.o -static -o hello_static
file hello_static:
hello_static: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked , for GNU/Linux 2.6.32, BuildID[sha1]=e3b978f18ef711ce682a6c1868317cbde1d05adf, not stripped

参考链接
  1. 程序的链接和装入及Linux下动态链接的实现 ,链接
  2. 编译器的工作过程,链接

后期改进
  1. 实际上,gcc/g++编译器是非常复杂的应用程序,堪比OS,同时这也是泛指的“编译器”,实际上是编译器+链接器的结合,甚至还有其他更加复杂的功能在里面,我们暂时理解到这个层面就可以了。日后需要使用到,再去深入理解。

拓展:
     实际上,理解了整个编译链接过程,还需要继续深入到执行文件,研究执行文件的组成,真正观察“编译器”和“链接器”的工作成果。 [Linux]C程序的存储空间布局

你可能感兴趣的:(Linux,C/C++)