标签:
本章主要内容:
链接——静态链接、动态链接(链接又包括两个主要任务:符号解析和重定位)
符号——全局符号和本地符号、符号表、符号解析
链接文件的创建及引用——gcc、ar rcs、sharedj及fPIC命令参数
重定位——重定位条目、重定位符号引用(PC相对引用和绝对引用)
目标文件——可重定位目标文件(其中又详细介绍了ELF可重定位文件的结构及格式)、可执行目标文件、共享目标文件
链接(linking)是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储器并执行。
链接可以执行于编译时,即源代码被翻译成机器代码时;也可执行于加载时,即在程序被加载器加载到存储器并执行时;甚至执行于运行时,由应用程序来执行。
大多数编译系统提供编译器驱动程序(compiler driver),它代表用户在需要时调用语言预处理器、编译器、汇编器和链接器。
GNU编译系统编译源码:
Unix的静态链接器(static linker)ld,以一组可重位目标文件和命令行参数作为输入,生成一个完全链接的可以加载和运行的可执行目标文件作为输出。输入的可重定位目标文件由各种不同的代码和数据节(section)组成。指令在一个节中,初始化的全局变量在另一个节中,而未初始化的变量又在另外一个节中。
为了构造可执行文件,链接器必须完成两个主要任务:
目标文件有三种形式:可重定位目标文件。可以在编译时与其它可重定位目标文件合并起来,创建一个可执行目标文件。
编译器和汇编器生成可重定位目标文件(包括共享目标文件)。链接器生成可执行目标文件。
现代Unix系统使用可执行和可链接格式(ELF)。
可重定位目标文件
一个典型的可重定位目标文件包含下面几个节:
.text:已编译程序的机器代码。
.rodata:只读数据。
.data:已初始化的全局C变量。局部C变量在运行时保存在栈中,既不出现在.data节中,也不出现在.bss节中。
.bss:未初始化的全局C变量。
每个可重定位目标模块m都有一个符号表,它包含m所定义和引用的符号的信息。
弱符号:未初始化的全局变量
规则:
规则1:不允许有多个强符号。
规则2:如果有一个强符号和多个弱符号,那么选择强符号。
规则3:如果有多个弱符号,那么从这些弱符号中任意选择一个。
所有的编译系统都提供一种机制,将所有相关的目标模块打包成为一个单独的文件,称为静态库(Linux下是存档文件,Windows下是lib),可以用做链接器的输入。
C程序开始时是一组ASCII文本文件,已经被转化为一个二进制文件,且这个二进制文件包含加载程序到存储器并运行它所需的所有信息。
段头部表:可执行文件的连续片被映射到连续的存储器段,段头部表描述了这种关系。
加载器将可执行目标文件中的执行代码和数据从磁盘拷贝到存储器中,然后通过跳转到程序的第一条指令或入口点来运行该程序。这个将程序拷贝到存储器并运行的过程叫做加载。
用户栈总是最大的合法用户地址开始,向下增长的(向低存储器地址方向增长)。从栈的上部开始的段是为操作系统驻留存储器的部分(也就是内核)的代码和数据保留的。
接下来,加载器跳转到程序的入口点,也就是符号_start的地址。在_start地址处的启动代码(startup code)是在目标文件ctrl.o中定义的,对所有的C程序都是一样的。
编译库代码,使得不需要链接器修改库代码就可以在任何地址加载和执行这些代码。
-fPIC
选项指示GNU生成PIC代码20135302魏静静——《深入理解计算机系统》第7章 学习笔记
标签:
原文地址:http://www.cnblogs.com/20135302wei/p/5357264.html