已阅读5页,还剩45页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1 本学期考核方法 本学期平时分占60 期末考试占40 小测试共2次 每次6分 共20分作业加考勤基础分20分 少一次扣4分 作业不交加考勤不到场超过5次将取消考试资格 实验课有两个实验 每次10分 共20各种加分 回答问题 实验提前做完等 期末考试形式为闭卷考试 第四章程序的链接目标文件格式符号解析与重定位共享库与动态链接 3 可执行文件的链接生成 主要教学目标使学生了解链接器是如何工作的 从而能够养成良好的程序设计习惯 并增加程序调试能力 通过了解可执行文件的存储器映像来进一步深入理解进程的虚拟地址空间的概念 包括以下内容链接和静态链接概念三种目标文件格式符号及符号表 符号解析使用静态库链接重定位信息及重定位过程可执行文件的存储器映像可执行文件的加载共享 动态 库链接 4 程序的链接 分以下三个部分介绍第一讲 目标文件格式程序的链接概述 链接的意义与过程ELF目标文件 重定位目标文件格式 可执行目标文件格式第二讲 符号解析与重定位符号和符号表 符号解析与静态库的链接重定位信息第三讲 动态链接动态链接的特性 程序加载时的动态链接 程序运行时的动态链接 5 一个典型程序的转换处理过程 1 include23intmain 4 5printf hello world n 6 经典的 hello c C 源程序 include n nintmain n 1046210101051101163210997105110404110123 nprintf hel10323232321121141051101161024034104101108lo world n n 10811144321191111141081009211034415910125 hello c的ASCII文本表示 计算机能够直接识别hello c源程序吗 不能 需要转换为机器语言代码 即 编译 汇编等 功能 输出 hello world 6 一个C语言程序举例 intbuf 2 1 2 voidswap intmain swap return0 main c swap c externintbuf int bufp0 1 预处理 cpp 在高级语言源程序中插入所有用 include命令指定的文件和用 define声明指定的宏 2 编译 cc1 将预处理后的源程序文件编译生成相应的汇编语言程序 3 汇编 as 由汇编程序将汇编语言源程序文件转换为可重定位目标文件 4 链接 ld 由链接器将多个可重定位目标文件及库例程 如printf o 链接起来 生成可执行文件 7 可执行文件的生成 使用GCC编译器编译并链接生成可执行程序P unix gcc O2 g opmain cswap cunix p GCC编译器的静态链接过程 8 引用符号的地址需要重定位 main main o int bufp0 buf 0 swap swap o Systemcode intbuf 2 1 2 Systemdata 可重定位目标文件 可执行目标文件 text data text data text data staticint bufp1 bss 虽然是swap的本地符号 也需在 bss节重定位 9 使用链接的优点 链接带来的好处1 模块化 1 一个程序可以分成很多源程序文件 2 可构建公共函数库 如数学库 标准C库等 链接带来的好处2 效率高 1 时间上 可分开编译只需重新编译修改的源程序文件 然后重新链接 2 空间上 无需包含共享库所有代码源文件中无需包含共享库函数的源码 只要直接调用即可可执行文件和运行时的内存中只需包含所调用函数的代码而不需要包含整个共享库 10 链接操作的步骤 Step1 符号解析 Symbolresolution 程序中有定义和引用的符号 包括变量和函数等 voidswap 定义符号swap swap 引用符号swap int xp 定义符号xp 引用符号x 编译器将定义的符号存放在一个符号表 symboltable 中 符号表是一个结构数组每个表项包含符号名 长度和位置等信息链接器将每个符号的引用都与一个确定的符号定义建立关联Step2 重定位将多个代码段与数据段分别合并为一个单独的代码段和数据段将 o文件中每个符号的相对位置重定位为可执行文件中的绝对存储位置将原来符号表中的位置信息修改为重定位后的位置信息 11 三类目标文件 可重定位目标文件 ofile 其代码和数据可和其他可重定位文件合并为可执行文件每个 o文件由对应的 c文件生成每个 o文件代码和数据地址都从0开始可执行目标文件 afile 包含的代码和数据可以被直接复制到内存并被执行代码和数据地址为虚拟地址空间中的地址共享的目标文件 sofile 特殊的可重定位目标文件 能在装入或运行时被装入到内存并自动被链接Windows中称其为DynamicLinkLibraries DLLs 12 00000000 0 55push ebp1 89e5mov esp ebp3 83ec10sub 0 x10 esp6 8b450cmov0 xc ebp eax9 8b5508mov0 x8 ebp edxc 8d0402lea edx eax 1 eaxf 8945fcmov eax 0 x4 ebp 12 8b45fcmov 0 x4 ebp eax15 c9leave16 c3ret 080483d4 80483d4 55push ebp80483d5 89e5mov esp ebp80483d7 83ec10sub 0 x10 esp80483da 8b450cmov0 xc ebp eax80483dd 8b5508mov0 x8 ebp edx80483e0 8d0402lea edx eax 1 eax80483e3 8945fcmov eax 0 x4 ebp 80483e6 8b45fcmov 0 x4 ebp eax80483e9 c9leave80483ea c3ret objdump dtest o objdump dtest main c intadd int int intmain returnadd 20 13 test c intadd inti intj intx i j returnx 13 ExecutableandLinkableFormat ELF 两种视图链接视图 Relocatableobjectfiles执行视图 Executableobjectfiles 节 section 是ELF文件中具有相同特征的最小可处理单位 text节 代码 data节 数据 rodata 只读数据 bss 未初始化数据 由不同的段 segment 组成 描述节如何映射到存储段中 可多个节映射到同一段 如 可合并 data节和 bss节 并映射到一个可读可写数据段中 14 可重定位目标文件格式 ELF头占16字节 包括字长 字节序 大端 小端 文件类型 o exec so 机器类型 如IA 32 节头表的偏移 节头表的表项大小及表项个数 text节编译后的代码部分 rodata节只读数据 如printf格式串 switch跳转表等 data节已初始化的全局变量 bss节未初始化全局变量 仅是占位符 不占据任何实际磁盘空间 目标文件格式区分初始化和非初始化是为了空间效率 15 可重定位目标文件格式 symtab节存放函数和全局变量 符号表 信息 它不包括局部变量条目 rel text节 text节的重定位信息 用于重新修改代码段的指令中的地址信息 rel data节 data节的重定位信息 用于对被模块使用或定义的全局变量进行重定位的信息 debug节调试用符号表 gcc g strtab节包含symtab和debug节中符号及节名Sectionheadertable 节头表 每个节的节名 偏移和大小 16 可执行目标文件格式 与 o文件稍有不同 ELF头中字段e entry给出执行程序时第一条指令的地址 而在可重定位文件中 此字段为0多一个 init节 用于定义 init函数 该函数用来进行可执行目标文件开始执行时的初始化工作少两 rel节 无需重定位 多一个程序头表 也称段头表 segmentheadertable 是一个结构数组 17 可执行文件的存储器映像 0 esp 栈顶 brk 0 xC00000000 0 x08048000 从可执行文件装入 程序 段 头表描述如何映射 18 可执行文件中的程序头表 typedefstruct Elf32 Wordp type Elf32 Offp offset Elf32 Addrp vaddr Elf32 Addrp paddr Elf32 Wordp filesz Elf32 Wordp memsz Elf32 Wordp flags Elf32 Wordp align Elf32 Phdr 程序头表能够描述可执行文件中的节与虚拟空间中的存储段之间的映射关系一个表项说明虚拟地址空间中一个连续的片段或一个特殊的节以下是GNUREADELF显示的某可执行目标文件的程序头表信息 19 可执行文件中的程序头表 程序头表中有8个表项 其中有两个是可装入段 type LOAD 对应表项 第一可装入段对应第0 x00000 0 x004d3字节 包括ELF头 程序头表 init text和 rodata节 映射到虚拟地址0 x8048000开始长度为0 x4d4字节的区域 按0 x1000 212 4K字节对齐 具有只读 执行权限 Flg RE 是只读代码段 read onlycode 第二可装入段对应第0 x000f0c开始长度为0 x108字节的 data节 映射到虚拟地址0 x8049f0c开始的长度为0 x110字节的存储区域 在0 x110 272字节的存储区中 前0 x108 264字节用 data节内容初始化 而后面272 264 8个字节对应 bss节 初始化为0 该段按0 x1000 4KB对齐 具有可读可写权限 Flg RW 因此 它是一个可读写数据段 read writedatasegment 20 程序的链接 分以下三个部分介绍第一讲 目标文件格式程序的链接概述 链接的意义与过程ELF目标文件 重定位目标文件格式 可执行目标文件格式第二讲 符号解析与重定位符号和符号表 符号解析与静态库的链接重定位信息第三讲 动态链接动态链接的特性 程序加载时的动态链接 程序运行时的动态链接 21 符号和符号解析 每个可重定位目标模块m都有一个符号表 它包含了在m中定义和引用的所有符号 有三种链接器符号 Globalsymbols 模块内部定义的全局符号 由模块m定义并能被其他模块引用的符号 例如 非staticC函数和非static的C全局变量 指不带static的全局变量 如 main c中的全局变量名bufExternalsymbols 外部定义的全局符号 由其他模块定义并被模块m引用的全局符号如 main c中的函数名swapLocalsymbols 本模块的局部符号 仅由模块m定义和引用的本地符号 例如 在模块m中定义的带static的C函数和全局变量如 swap c中的static变量名bufp1链接器局部符号不是指程序中的局部变量 分配在栈中的临时性变量 链接器不关心这种局部变量 22 符号和符号解析 intbuf 2 1 2 voidswap intmain swap return0 main c externintbuf int bufp0 swap c Global External External Local Global 局部变量 23 目标文件中的符号表 符号表 symtab 中每个条目的结构如下 typedefstruct intname 指向符号对应字符串在strtab节中的偏移 intvalue 在对应section中的偏移量 可执行文件中是虚拟地址 intsize 符号对应目标所占字节数 chartype 4 符号对应目标的类型 数据 函数 源文件 节 binding 4 符号对应目标是全局符号还是局部符号 charreserved charsection 符号对应目标所在的section 或其他情况 Elf Symbol 其他情况 ABS表示不该被重定位 UND表示未定义 COM表示未初始化数据 bss 此时 value表示对齐要求 size给出最小大小 24 目标文件中的符号表 main o中的符号表中最后三个条目 Num valueSizeTypeBindOtNdxName8 08DataGlobal03buf9 033FuncGlobal01main10 00NotypeGlobal0UNDswap swap o中的符号表中最后4个条目 Num valueSizeTypeBindOtNdxName8 04DataGlobal03bufp09 00NotypeGlobal0UNDbuf10 036FuncGlobal01swap11 44DataLocal0COMbufp1 buf是main o中第3节 data 偏移为0的符号 是全局变量 占8B main是第1节 text 偏移为0的符号 是全局函数 占33B swap是main o中未定义的符号 不知道类型和大小 全局的 在其他模块定义 bufp1是未分配地址且未初始化的本地变量 ndx COM 按4B对齐且占4B 25 符号解析 目的 将每个模块中引用的符号与某个目标模块中的定义符号建立关联 每个定义符号在代码段或数据段中都被分配了存储空间 将引用符号与对应定义符号建立关联后 就可在重定位时将引用符号的地址重定位为相关联的定义符号的地址 本地符号在本模块内定义并引用 因此 其解析较简单 只要与本模块内唯一的定义符号关联即可 全局符号 外部定义的 内部定义的 的解析涉及多个模块 故较复杂 符号的定义 其实质是什么 是指符号被分配了虚拟地址空间 符号为函数名即指其代码所在区 符号为变量即指其占的静态数据区 26 全局符号的符号解析 全局符号的强 弱特性函数名和已初始化的全局变量名是强符号未初始化的全局变量名是弱符号 intfoo 5 p1 intfoo p2 p1 c p2 c 以下符号哪些是强符号 哪些是弱符号 27 全局符号的符号解析 intbuf 2 1 2 voidswap intmain swap return0 main c externintbuf int bufp0 swap c 强符号 此处为引用 弱符号 本地符号 强符号 局部变量 以下符号哪些是强符号 哪些是弱符号 28 链接器对符号的解析规则 多重定义符号的处理规则Rule1 强符号不能多次定义强符号只能被定义一次 否则链接错误Rule2 若一个符号被定义为一次强符号和多次弱符号 则按强定义为准对弱符号的引用被解析为其强定义符号Rule3 若有多个弱符号定义 则任选其中一个使用命令gcc fno common链接时 会告诉链接器在遇到多个弱定义的全局符号时输出一条警告信息 29 多重定义符号的解析举例 intx 10 intp1 void intmain x p1 returnx main c intx 20 intp1 returnx p1 c main只有一次强定义p1有一次强定义 一次弱定义x有两次强定义 所以 链接器将输出一条出错信息 以下程序会发生链接出错吗 30 多重定义符号的解析举例 p1 c y一次强定义 一次弱定义z两次弱定义p1一次强定义 一次弱定义main一次强定义 includeinty 100 intz voidp1 void intmain z 1000 p1 printf y d z d n y z return0 main c inty intz voidp1 y 200 z 2000 问题 打印结果是什么 y 200 z 2000 以下程序会发生链接出错吗 该例说明 在两个不同模块定义相同变量名 很可能发生意想不到的结果 31 多重定义符号的解析举例 p1 c 该例说明 两个重复定义的变量具有不同类型时 更容易出现难以理解的结果 main c 问题 打印结果是什么 d 0 x 1072693248 以下程序会发生链接出错吗 1 include2intd 100 3intx 200 4voidp1 void 5intmain 6 7p1 8printf d d x d n d x 9return0 10 1doubled 23voidp1 4 5d 1 0 6 p1执行后d和x处内容是什么 1 0 0011111111110 0B 3FF0000000000000H 32 多重定义符号的解析举例 打印结果 d 0 x 1072693248Why 1doubled 23voidp1 4 5d 1 0 6 1intd 100 2intx 200 3intmain 4 5p1 6printf d d x d n d x 7return0 8 main cp1 c 理解该问题需要知道 机器级数据的表示与存储链接器的符号解析规则 double型数1 0对应的机器数3FF0000000000000H IA 32是小端方式 33 多重定义全局符号的问题 尽量避免使用全局变量一定需要用的话 就按以下规则使用尽量使用本地变量 static 全局变量要赋初值外部全局变量要使用extern 多重定义全局变量会造成一些意想不到的错误 而且是默默发生的 编译系统不会警告 并会在程序执行很久后才能表现出来 且远离错误引发处 特别是在一个具有几百个模块的大型软件中 这类错误很难修正 大部分程序员并不了解链接器如何工作 因而养成良好的编程习惯是非常重要的 34 头文件 h文件 的作用 include global h intf returng 1 c1 c global h ifdefINITIALIZEintg 23 staticintinit 1 elseintg staticintinit 0 endif include include global h intmain if init g 37 intt f printf Callingfyields d n t return0 c2 c 35 预处理操作 include global h intf returng 1 c1 c global h ifdefINITIALIZEintg 23 staticintinit 1 elseintg staticintinit 0 endif intg 23 staticintinit 1 intf returng 1 intg staticintinit 0 intf returng 1 定义INITIALIZE 没有定义INITIALIZE include指示被执行 插入 h文件的内容到源文件中 36 如何划分模块 许多函数无需自己写 可使用共享库函数Math I O memorymanagement stringmanipulation etc 避免以下两种极端做法将所有函数都放在一个源文件中修改一个函数需要对所有函数重新编译时间和空间两方面的效率都不高一个函数放在一个源文件中需要程序员显式地进行链接效率高 但模块太多 故太繁琐 37 静态共享库 静态库 aarchivefiles 将所有相关的目标模块打包为一个单独的文件 称为静态库文件 也称为存档文件 archive 增强链接器功能 使其能通过查找一个或多个库文件中的符号来解析符号在构建可执行文件时只需指定库文件名 链接器会自动到库中寻找那些应用程序用到的目标模块 并且只把用到的模块从库中拷贝出来在gcc命令行中无需明显指定C标准库libc a 默认库 38 静态库的创建 Translator atoi c atoi o Translator printf c printf o libc a Archiver ar Translator random c random o unix arrslibc a atoi oprintf o random o Cstandardlibrary Archiver 归档器 允许增量更新 只要重新编译需修改的源码并将其 o文件替换到静态库中 39 自定义一个静态库文件 includevoidmyfunc1 printf s Thisismyfunc1 n includevoidmyfunc2 printf s Thisismyfunc2 n gcc cmyproc1 cmyproc2 carrcsmylib amyproc1 omyproc2 o myproc1 c myproc2 c 40 链接器中符号解析的全过程 voidmyfunc1 viod intmain myfunc1 return0 main c 调用关系 main myfunc1 printf gcc cmain cgcc static omyprocmain o mylib a 开始E U D为空 首先扫描main o 把它加入E 同时把myfun1加入U main加入D 接着扫描到mylib a 将U中所有符号 本例中为myfunc1 与mylib a中所有目标模块 myproc1 o和myproc2 o 依次匹配 发现在myproc1 o中定义了myfunc1 故myproc1 o加入E myfunc1从U转移到D 在myproc1 o中发现还有未解析符号printf 将其加到U 不断在mylib a的各模块上进行迭代以匹配U中的符号 直到U D都不再变化 此时U中只有一个未解析符号printf 而D中有main和myfunc1 因为模块myproc2 o没有被加入E中 因而它被丢弃 E将被合并以组成可执行文件的所有目标文件集合U当前所有未解析的引用符号的集合D当前所有定义符号的集合 接着 扫描默认的库文件libc a 发现其目标模块printf o定义了printf 于是printf也从U移到D 并将printf o加入E 同时把它定义的所有符号加入D 而所有未解析符号加入U 处理完libc a时 U一定是空的 libc a无需明显指出 41 链接器中符号解析的全过程 main c voidmyfunc1 viod intmain myfunc1 return0 gcc cmain cgcc static omyprocmain o mylib a 问题 若命令为 gcc static omyproc mylib amain o 结果怎样 main o中的myfunc1不能被解析 故出现链接错误 42 链接顺序问题 假设调用关系如下 func o libx a和liby a中的函数libx a libz a中的函数libx a和liby a之间 liby a和libz a相互独立则以下几个命令行都是可行的 gcc static omyfuncfunc olibx aliby alibz agcc static omyfuncfunc oliby alibx alibz agcc static omyfuncfunc olibx alibz aliby a假设调用关系如下 func o libx a和liby a中的函数libx a liby a同时liby a libx a则以下命令行可行 gcc static omyfuncfunc olibx aliby alibx a 43 重定位 符号解析完成后 可进行重定位工作 分两步对节和定义符号进行重定位将集合E的所有目标模块中相同的节合并成新节 并将运行时的虚拟地址赋给每个新节中所有的定义符号 例如 所有 text节合并作为可执行文件中的 text节 并为每个 text节确定在新 text节中的绝对地址 从而为其中定义的函数确定首地址 含有多个函数时 进而确定每条指令的地址 完成这一步后 每条指令和每个全局变量都可确定地址 对节中的引用符号进行重定位修改 text节和 data节中对每个符号的引用 地址 需要用到在 rel data和 rel text节中保存的重定位信息 44 重定位信息 汇编器遇到对位置未知的目标引用时 生成一个重定位条目数据引用的重定位条目在 rel data节中指令中引用的重定位条目在 rel text节中ELF中重定位条目格式如下 有两种最基本的重定位类型R 386 PC32 使用32位PC相对地址的引用 重定位指令R 386 32 使用32位绝对地址重定位数据 typedefstruct intoffset 需重定位的引用的节偏移 intsymbol 24 需重定位的引用所指向的符号 type 8 重定位类型 即修改方式 Elf32 Rel 例如 在rel text节中有重定位条目offset 0 x12symbol swaptype R 386 PC32 说明在 text节中偏移为0 x12的地方需重定位 按PC相对地址方式修改 引用的符号为swap 45 程序的链接 分以下三个部分介绍第一讲 目标文件格式程序的链接概述 链接的意义与过程ELF目标文件 重定位目标文件格式 可执行目标文件格式第二讲 符号解析与重定位符号和符号表 符号解析与静态库的链接重定位信息第三讲 动态链接动态链接的特性 程序加载时的动态链接 程序运行时的动态链接 46 动态链接的共享库 SharedLibraries 静态库有一些缺点 静态库中的常用函数 如print
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年社区民警面试实战题库河北专版
- 宁波地铁2026招聘笔试题库
- 2026年科研失信行为调查处理规则题
- 2026年船舶制造与航运管理政策题库
- 2026年法律实务与法律职业道德知识测试题
- 2026年广东省物权法知识练习题
- 2026年行业专业英语能力测试卷
- 2026年烟草企业安全生产标准化规范及仓储消防与卷烟设备安全题库
- 2026年市场监管领域双随机一公开监管工作规范专项测试卷
- T-CZSPTXH 329-2025 潮州菜 铁板肉香芋烹饪工艺规范
- 医疗护理岗位礼仪标准
- 2025年贵州省高考化学试卷真题(含答案及解析)
- 2025贵州毕节市第四人民医院招聘编外人员23人历年真题汇编含答案解析(夺冠)
- 2025年四川成都社区工作者考试真题及答案
- 水罐环氧树脂施工技术交底
- 2025年城市特许经营停车场项目可行性研究报告及总结分析
- DBJT 13-503-2025 福建省城市口袋公园规划建设标准
- 《嵌入式实验与实践教程-基于STM32与Proteus》课件-第四章
- 《数字电路与逻辑设计基础》课件-第6章 时序逻辑电路
- 惠山高新区污水处理厂新建工程项目报告表
- 高中男女生交往课件
评论
0/150
提交评论