链接概述和目标文件格式

可执行文件生成概述

执行流程

预处理

预处理命令
    – $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可执行目标文件

可执行目标文件格式

 

可执行文件中的程序头表

 

 

posted @ 2018-09-24 15:24  R00M  阅读(1581)  评论(0编辑  收藏  举报