程序的构建过程

程序的构建过程

下图勾勒出了构建并执行一个C语言程序的典型过程。最左侧是源程序,它经过编译器(compiler)被编译为等价的汇编语言模块,再经过汇编器(assembler)产生出与目标平台CPU一致的机器码模块。尽管机器码模块中包含的指令已经可以被目标CPU所执行,但是其中可能还包含没有解决的名称和地址引用,因此需要链接器(linker)解决这些问题,并产生出符合目标平台上的操作系统所要求格式的可执行模块。当用户执行程序时,操作系统的加载器(loader)会解读链接器记录在可执行模块中的格式信息,将程序中的代码和数据”布置“在内存中,成为真正可以运行的内存映像。

1074633-20181204162941422-1237442106.png

编译器和汇编器所做的主要都是翻译工作,因此以目标代码(机器码)为分界,可以把程序的构建过程分为编译和链接两个阶段。

  • 链接器

    链接器的主要职责是将编译器产生的多个目标文件合为一个可以在目标平台下执行的执行映像。这里说的目标平台是指程序的运行环境,包括CPU和操作系统。举例来说,如果要在windows平台下运行,那么链接器就要产生PE(Protable Executable)格式的可执行文件。要产生一个PE格式的可执行文件,链接器要完成的典型任务如下:

    1. 解决目标文件中的外部符号,包括函数调用和变量引用。如果调用的函数是Windows API或其他位于DLL模块的函数,那么必须为这些调用建立输入目录表(Import Directory Table)和输入地址表(Import Address Table)。输入目录表用来描述被引用的文件,IAT表用来记录或重定位被引用函数的地址。链接器会把输入目录表和IAT表放在PE文件的输入数据段(.idata)中。
    2. 生成代码段(.text),放入已经解决了外部引用的目标代码。
    3. 生成包含只读数据的数据段(.data)。
    4. 生成包含资源数据的资源段(.rsrc)。
    5. 生成包含基地址重定位表(Base Relocation Table)的.reloc段。当链接器产生PE文件时,它会假定一个地址作为本模块的基地址,比如VC6编译器为EXE模块定义的默认基地址是0x00400000。当程序运行时,如果加载器将一个模块加载到与默认地址不同的基地址,那么这时便必须要用重定位表来进行重定位。可以通过链接器的链接选项来指定模块的默认基地址。
    6. 如果定义了输出函数和变量,则产生包含输出表的.edata段。输出表通常出现在DLL文件中,EXE文件中一般不包含.edata段,但NTOSKERNL.EXE是个例外。
    7. 生成PE文件头,文件头描述了文件的构成和程序的基本信息。
  • 加载器

    加载器是操作系统的一部分,它负责将可执行程序从外部存储器(如硬盘)加载到内存中,并做好执行准备,包括遍历输入目录表加载依赖模块,遍历IAT表绑定动态调用的函数,对基地址发生冲突的模块执行调整工作等。NTDLL中包含了一系列以Ldr开头的函数,用于完成以上任务。

转载于:https://www.cnblogs.com/amaza/p/10064931.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值