链接概述和目标文件格式
可执行文件生成概述
执行流程
预处理
预处理命令 – $gcc –E hello.c –o hello.i – $cpp hello.c > hello.i • 处理源文件中以“#”开头的预编译指令,包括: – 删除“#define”并展开所定义的宏 – 处理所有条件预编译指令,如“#if”,“#ifdef”, “#endif”等 – 插入头文件到“#include”处,可以递归方式进行处理 – 删除所有的注释“//”和“/* */” – 添加行号和文件名标识,以便编译时编译器产生调试用的行号信息 – 保留所有#pragma编译指令(编译器需要用) • 经过预编译处理后,得到的是预处理文件(如,hello.i) ,它还是一个可读的文本文件 ,但不包含任何宏定义
编译
编译过程就是将预处理后得到的预处理文件(如 hello.i)进行 词法分析、语法分析、语义分析、优化后,生成汇编代码文件 • 用来进行编译处理的程序称为编译程序(编译器,Compiler) • 编译命令 – $gcc –S hello.i –o hello.s – $gcc –S hello.c –o hello.s – $/user/lib/gcc/i486-linux-gnu/4.1/cc1 hello.c • 经过编译后,得到的汇编代码文件(如 hello.s)还是可读的文本文件,CPU无法理解和执行它 gcc命令实际上是具体程序(如ccp、cc1、as等)的包装命令,用户通过gcc命令来使用具体的预处理程序ccp、编译程序cc1和汇编程序as等
汇编
汇编代码文件(由汇编指令构成)称为汇编语言源程序 • 汇编程序(汇编器)用来将汇编语言源程序转换为机器指令序列 (机器语言程序) • 汇编指令和机器指令一一对应,前者是后者的符号表示,它们都 属于机器级指令,所构成的程序称为机器级代码 • 汇编命令 – $gcc –c hello.s –o hello.o – $gcc –c hello.c –o hello.o – $as hello.s -o hello.o (as是一个汇编程序) 汇编结果是一个可重定位目标文件(如,hello.o),其中包含 的是不可读的二进制代码,必须用相应的工具软件来查看其内容
链接
预处理、编译和汇编三个阶段针对一个模块(一个*.c文件)进行处理,得到对应的一个可重定位目标文件(一个*.o文件)
• 链接过程将多个可重定位目标文件合并以生成可执行目标文件
• 链接命令
– $gcc –static –o myproc main.o test.o
– $ld –static –o myproc main.o test.o
–static 表示静态链接,如果不指定-o选项,则可执行文件名为“a.out”
链接器的由来
使用链接的好处
链接带来的好处1:模块化 (1)一个程序可以分成很多源程序文件 (2)可构建公共函数库,如数学库,标准C库等 (代码重用,开发效率高) 链接带来的好处2:效率高 (1)时间上,可分开编译 只需重新编译被修改的源程序文件,然后重新链接 (2)空间上,无需包含共享库所有代码 源文件中无需包含共享库函数的源码,只要直接调用即可 (如,只要直接调用printf()函数,无需包含其源码) 可执行文件和运行时的内存中只需包含所调用函数的代码 而不需要包含整个共享库
实例:
可执行文件的存储器映像
目标文件格式概述
链接操作的步骤
链接的操作步骤
三类目标文件
可重定位目标文件 (.o) – 其代码和数据可和其他可重定位文件合并为可执行文件
• 每个.o 文件由对应的.c文件生成
• 每个.o文件代码和数据地址都从0开始
• 可执行目标文件 (默认为a.out) – 包含的代码和数据可以被直接复制到内存并被执行
– 代码和数据地址为虚拟地址空间中的地址
• 共享的目标文件 (.so) – 特殊的可重定位目标文件,能在装入或运行时被装入到内存并自动被链接,称为共享库文件
– Windows 中称其为 Dynamic Link Libraries (DLLs)
目标文件的格式
目标代码(Object Code)指编译器和汇编器处理源代码后所生 成的机器语言目标代码
目标文件(Object File)指包含目标代码的文件
ELF
链接视图—可重定位目标文件
执行视图—可执行目标文件
ELF可重定位目标文件
未初始化变量(.bss节)
C语言规定: – 未初始化的全局变量和局部静态变量的默认初始值为0 • 将未初始化变量(.bss节)与已初始化变量(.data节)分开的好处 – .data节中存放具体的初始值,需要占磁盘空间 – .bss节中无需存放初始值,只要说明.bss中的每个变量将来在执行时占用几个字节即可, 因此,.bss节实际上不占用磁盘空间,提高了磁盘空间利用率 • BSS(Block Started by Symbol)最初是UA-SAP汇编程序中所用的一个伪指令,用于为 符号预留一块内存空间 • 所有未初始化的全局变量和局部静态变量都被汇总到.bss节中,通过专门的“节头表(Section header table)”来说明应该为.bss节预留多大的空间
可重定位目标文件格式
ELF头(ELF Header)
ELF头信息举例
节头表(Section Header Table)
节头表信息举例
ELF可执行目标文件
可执行目标文件格式
可执行文件中的程序头表