编码学习笔记 ——目标文件

参考:《程序员的自我修养》第3章

真正了不起的程序员对自己的程序的每一个字节都了如指掌。

学习笔记,我就是个搬运工。
ELF:Executable Linkable Format。
PE-COFF:Portable Executable Common File Format。
查看目标文件内部结构的工具:
objdump -h file.o             // 将elf文件各个段的基本信息打印出来
objdump -x file.o             // 将elf文件各个段的基本信息打印出来,更详细
objdump -s file.o             // 将段的内容以16进制打印出来
objdump -d file.o             // 反汇编
readelf -h file.o             // 查看elf文件头信息
readelf -S file.o             // 查看elf文件段表结构
nm file.o                     // 查看elf文件的符号表

查看elf文件代码段、数据段、BSS长度:
size file.o
1. 什么是目标文件

源代码编译后但未进行链接的中间文件,Linux下的.o,Windows下的.obj。
目标文件与可执行文件采用相同的文件格式,主流是Linux为ELF,Windows为PE-COFF。
 

2. 可执行文件格式在这里插入图片描述
3. ELF文件结构

ELF文件结构大致可分为ELF文件头、段表、字符串表、符号表等。

  • ELF头
    在这里插入图片描述
    ELF魔数: ELF头中的Magic,是ELF魔数,16个字节,对应class到ABI version的内容,用于标识ELF文件的平台属性,如ELF字长,字节序,ELF版本等。
    0x7f 45 4c 46:对应的ASCII码为 DEL控制符,E,L,F。
    文件类型:系统通过文件类型常量来判断ELF的真正文件类型,而非后缀名。REL(1)—可重定位文件,EXEC(2)—可执行文件,DYN(3)—共享目标文件。
    机器类型:表示该ELF文件的平台属性,即可以在什么平台下运行。

  • 段表:描述了ELF文件各个段的信息,如段名、段的长度、在文件中的偏移、读写权限等。主要确定段属性的是段的类型和段的标志位。
    在这里插入图片描述在这里插入图片描述
    段类型
    在这里插入图片描述
    段标志位 :表示该段在进程虚拟地址空间中的属性,可读可写可执行,分配空间等。

  • 重定位表:链接器在处理目标文件时,需对目标文件中的某些部位进行重定位,即代码段和数据段那些绝对地址的引用的位置。重定位表里记录着这些重定位信息。

  • 字符串表:由于字符串长度不固定,所以用固定结构来表示比较困难,所以把字符串集中起来存放到一个表,用字符串在表中的偏移来引用字符串。
    .strtab :字符串表,保存普通的字符串。
    .shstrtab :段表字符串表,保存段表中用到的字符串,如段名。
     

4. 链接

目标文件相互拼合实质是目标文件之间对地址的引用,即对函数和变量地址的引用

  • 符号:函数和变量。
  • 符号名:函数名和变量名。
  • 符号表:每一个目标文件都有一个对应的符号表,记录了目标文件中用到的所有符号。
  • 符号值:对于函数和变量而言,就是它们的地址。
    在这里插入图片描述

ELF符号表结构
在这里插入图片描述

  • Num:表示符号表数组的下标。
  • Value:符号值。
  • Size:符号大小。
  • Type:符号类型。NOTYPE,未知类型;OBJECT,数据对象;FUNC,函数或其它可执行代码;SECTION,段;FILE,文件。
  • Bind:符号绑定信息。LOCAL,局部符号,对目标文件外的符号不可见;GLOBAL:全局符号,外部可见;WEAK:弱引用。
  • Ndx:表示该符号所属的段。
  • Name:符号名称。

函数签名:用于识别不同的函数,包含了函数名、参数类型、所在类、名称空间及其它。

弱符号和强符号:弱符号和强符号是针对定义来说,而非引用。

  • 编译器默认函数和已初始化的全局变量为强符号,未初始化的全局变量为弱符号。
  • 可用__attributte__((weak))来定义任何一个强符号为弱符号。
  • 链接器处理多次定义的全局符号:
    ❤❤ 不允许强符号被多次定义,即不同的目标文件不能有相同的强符号;如果有,就报错。
    ❤❤ 如果一个符号在某个目标文件中是强符号,其它是弱符号,那么选择强符号。
    ❤❤ 如果一个符号在所有目标文件中都是弱符号,选占用空间最大的那个。

弱引用和强引用:强引用,链接器发现某个符号未定义就会报未定义的错误。弱引用,链接器发现某个符号未定义不报错,默认其为0或者一个特定的值。

  • 可用__attributte__((weakref))来申明对一个外部函数的引用为弱引用。
发布了103 篇原创文章 · 获赞 41 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/u012800825/article/details/103071845