- 1、本文档共23页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
软件的链接过程详解
软件的链接过程 ——静态链接 2014.8.14 程序构建过程 目标文件的格式 静态链接 地址分配 符号解析 重定位 一个示例 目录 程序构建过程 目标文件格式——三种形式 目标文件(Object Files)有三种形式: 可重定位(Relocatable)目标文件:由编译器和汇编器生成,可以与其他可重定位目标文件合并创建一个可执行目标文件; 可执行(Executable)目标文件:由链接器生成,可以直接被拷贝到内存中执行; 共享(shared)目标文件:一类特殊的可重定位目标文件,可以在加载时或运行时被动态的加载到内存并执行。 目标文件格式——两种视角 目标文件格式——ELF头部 目标文件格式——节 .text:代码(节)段,存放已编译程序的机器代码。 .data:数据(节)段,存放初始化的全局变量。 .bss:数据(节)段,存放未初始化的全局变量。 .rodata:只读数据(节)段,存放只读属性数据。 目标文件格式——符号表 .sym:符号表,存放程序中定义和引用的函数和全局变量信息。 目标文件格式——字符串表 .strtab:字符串表,存放节头部表和符号表中的字符串。 目标文件格式——重定位表 .rel.text:.text节重定位表,存放.text节中符号位置,链接时需要修改这些位置。 .rel.data:.data节重定位表,存放.data节中符号位置,链接时需要修改这些位置。 目标文件格式——节头部表 静态链接——段合并与地址分配 静态链接——符号解析 每个可重定位的目标文件m都有一个符号表,在链接器的上下文中有三种不同的符号: 由m定义的,可以被其他模块引用的全局符号,对应于非静态的函数,以及被定义为不带static属性的全局变量。 由其他模块定义的,被m引用的全局符号,对应于定义在其他模块中的函数和变量。 只被m定义和引用的本地符号,对应于带static属性的函数和全局变量。 注:本地符号和本地程序变量(局部变量)是不同的,.symtab中的符号表不包含本地程序变量的任何符号,这些符号运行时用栈管理。但是带有static属性的本地程序变量是例外,编译器在.data和.bss节中为每个定义分配空间,并在符号表中创建一个有唯一名字的本地符号。 静态链接——符号解析 链接器从左至右的扫描可重定位目标文件以及库文件。在扫描的过程中,链接器维护着3个集合: 即将被合并到可执行目标文件中的目标文件的集合E; 没有解析的符号集合U; 在先前输入的文件中已有定义的符号集合D。 静态链接——符号解析 初始情况下,U、D、E都是空集。然后依据如下算法,依次处理输入文件: 对每一个输入文件f,链接器判断f是一个目标文件还是一个库文件。如果f是一个目标文件,把f加入E,根据f中的符号定义和符号引用更新U和D,然后处理下一个文件。 如果f是库文件,链接器尝试在库文件的成员中寻找U中符号(还没有解析的符号)的定义。如果某个成员m中包含U中某个符号的定义,那么把m加入E,根据m中的符号定义和符号引用更新U和D。重复这一过程直到U和D都不再变化,然后把不在E中的库文件的成员直接丢弃; 当链接器扫描完所有输入文件后,如果U是非空的,则报错并退出;如果U已经是空集,则合并E中的所有目标文件,形成可执行文件。 静态链接——重定位 在链接器完成了符号解析工作之后,每一个符号引用都与一个确定的符号定义相关联起来,链接器也知道了每一个输入模块的代码节和数据节的大小,然后开始重定位过程。 在重定位过程中,链接器将合并所有输入模块,为每个符号分配运行时地址。由两个步骤组成: 重定位节和符号定义。首先将所有输入文件中类型相同的节合并成新的聚合节,然后把运行时内存地址赋给聚合节、输入模块中的每一个节、以及输入模块中定义的每一个符号。 重定位节中的符号引用。链接器修改代码节和数据节中对每一个符号的引用,使它们指向正确的运行时地址,这一步骤依赖于重定位表目(relocation entry)。 静态链接——重定位 foreach section s{ foreach relocation entry r{ refptr = s + r.offset; if ( r.type == R_386_PC32 ) { refaddr = ADDR(s) + r.offset; *refptr = (unsigned) ( ADDR(r.symbol)+*refptr -refaddr); } if ( r.type == R_386_32 ) *refptr = (unsigned) ( ADDR(r.symbol)+*refptr); } } 一个示例 两个源文件main.c和swa
文档评论(0)