程序员的自我修养——链接,装载与库(三)

  • 目标文件从结构上讲,它是编译后的可执行文件格式,只是还没有经过链接的过程。其中可能有些符号或有些地址还没有被调整。其实它本身就是按照可执行文件格式存储的,只是与真正的可执行文件在结构上稍有不同。
  • 可执行文件的格式分为windows下的PE和linux下的ELF。
  • 目标文件是源代码编译后未进行链接的中间文件(windows下的.obj,linux下的.o),与可执行文件的内容和结构很相似。所以可以将目标文件和可执行文件看作一类文件。
  • 动态链接库和静态链接库也是按照可执行文件的格式存储。
  • 静态链接库是把很多的目标文件捆绑在一起形成一个文件。
  • Linux下采用ELF文件格式的有:可重定位文件,可执行文件,共享目标文件,核心转储文件。
  • 目标文件中包括编译后的机器指令代码,数据,链接时需要的信息。
  • 程序源代码编译后的机器指令经常被存放在代码段,代码段常见的名字有“.code”或“.text”。已经初始化的全局变量和局部静态变量保存在.data段。未初始化的全局变量和局部静态变量保存在.bss段。.bss段只是为未初始化的全局变量的局部静态变量预留位置而已(因为未初始化的全局变量和局部静态变量系统会默认初始化为0),它们不占内存空间。
  • ELF文件的起始段包括一个“文件头”。“文件头”描述了整个文件的属性,包括文件是否可执行,是静态链接还是动态链接及入口地址,目标硬件,目标操作系统等信息。接下来包括代码段,数据段,只读数据段,BSS段和其他段。g't
  • 源代码被编译以后分成两个段:程序指令和程序数据(因为程序被加载到内存时,首先会映射到虚拟内存,程序指令一般时只读的,程序数据一般是可读可写的,为了避免混淆和提高程序的局部性)。代码段属于程序指令,数据段和.bss属于程序数据。
  • .data段(数据段)保存的是那些已经初始化了的全局静态变量和局部静态变量.
  • .rodata段(只读数据段)存放的是只读的数据。
  • .bss段存放的是未初始化的全局变量和局部静态变量。
  • 我们知道ELF文件中有很多各种各样的段,而ELF文件中与段有关的重要的结构就是段表,段表保存了这些段的基本属性的结构。比如每个段的段名,段的长度,在文件中的偏移和读写权限。
  • 主要决定段的属性的是段的类型和段的标志位。
  • 段的标志位表示该段在进程虚拟进程地址空间的属性。
  • 重定位表:链接器在处理目标文件时,需要对目标文件中某些部位进行重定位,即代码段和数据段中那些对绝对地址的引用的位置,这些重定位的信息都记录在ELF文件的重定位表里面,对于每个需要重定位的代码段或数据段,都会有一个相应的重定位表。
  • ELF文件中用到了很多字符表。字符串表用来保存普通的字符串,比如符号的名字。段表字符串用来保存段表中用到的字符串,比如段名。
  • 链接的本质就是使不同的目标文件之间相互粘合,这些不同的目标文件之间粘合时必须要有固定的规则才可以。在链接中,目标文件之间相互拼合实际上是目标文件之间对地址的引用,即对函数和变量的地址引用。在链接中,函数和变量统称为符号(符号可以看作链接中的粘合剂)函数名或变量名称为符号名。
  • 链接阶段主要是对符号的管理,每一个目标文件都会有一个相应的符号表。符号表中记录了目标文件所用到的所有的符号。每个定义的符号都有一个符号值,对于函数和变量来说,符号值就是它们的地址。
  • 链接阶段只关心全局符号的相互粘合,局部符号,段名,行号等都是次要的。
  • 我们一般使用ld作为连接器来链接生产可执行文件。
  • 函数签名包含一个函数的全部信息。包括:函数名,函数的参数型别,函数所在的类及其他信息。函数的签名用于识别不同的函数。
  • 编译和链接阶段处理符号时,它们使用某种名称修饰的方法,对函数和变量进行修饰,得到符号名。
  • 符号重复定义:多个目标文件中含有相同名字的全局符号的定义,链接时将会出现符号重复定义的错误。
  • 编译器默认函数和初始化了的全局变量为强符号。未初始化的全局变量为弱符号。强符号和弱符号都是针对定义来说的,而不是针对符号的引用。
发布了78 篇原创文章 · 获赞 11 · 访问量 5076

猜你喜欢

转载自blog.csdn.net/qq_43145594/article/details/104235519