[音乐] 本课程以ELF标准来介绍目标文件格式。
ELF格式强调目标文件的两种视图,一种是链接视图,
即可重定位目标文件格式,另一种是执行视图,即可执行目标文件格式。
本讲主要介绍ELF链接视图, 也就是可重定位目标文件格式。
除了给出各主要信息块的含义外, 我们着重介绍其中两个重要的部分,
ELF头和节头表。
前面我们
讲过ELF的链接视图,实际上它是把一个点c文件 经过预处理、
编译、 汇编 然后生成一个链接视图,也就是点o文件。
这个点o文件里面实际上是把相应的代码部分 组成一个.text节,相应的这些
全局变量,或者是静态变量分成
两部分,一部分是已经初始化的那些数据,构成一个.data节。
还有就是未初始化的那些全局变量或者静态变量构成一个
.bss节,此外,还有像符号表,可重定位信息等等
构成相应的节,这样生成一个点o文件,就是可重定位目标文件。
可重定位目标文件当中是由若干 个节构成的,这些节就是一个一个的section。
在所有的这些节开头是ELF头,也就是一个
文件的头,任何一个文件实际上它都有一个头。
这个头如果是ELF这种目标文件格式的话,就
称为ELF头,在这个里面它包含一些信息。
最开始的是一个16字节的一些标识信息, 然后是一些文件类型、
机器类型 还有节头表的偏移位置,也就是
节头表在这个文件当中的偏移位置,还有
节头表的表项大小,以及表项的个数等等,这样的一些信息。
也就是说在ELF文件头当中。
有指向节头表的指针,然后呢,紧接着就是
代码节,.text节,就是编译以后生成的代码部分。
然后是只读数据节,也就是在 程序当中,比如像printf的格式串,
还有我们以前讲过switch...case语句。
它有可能会生成跳转表,像这种跳转表信息,以前我们讲过switch...case语句
它编译以后可能会生成这样的这个跳转表。
就在这个跳转表里面,它会放上 跳转的一个一个的地址。
就是跳转到的这地址,通过一条jmp指令来实现。
这个跳转表里面的这些地址是一些只读信息,
是不再改变的,所以它是在只读节里面, .rodata这个.section里面,像这样的只读信息
也是在ELF这个文件当中相应的节里面描述的,就是叫.rodata
这个只读.data节,此外呢还有 所以已初始化的这个数据在
.data节里面,还有未初始化的数据 在.bss节里面,.bss节里面
实际上仅仅只是一个占位符,也就是说 它在这个文件当中,它不占任何的空间,
不占任何的这个磁盘空间,它仅是在节头表里面, 会说有这么一个节,长度是多少。
把这个可执行文件装到内存的时候,会在内存里面给它分配空间。
但是在磁盘里面,这一节里面是不占空间的,而在节头表里面指出了它的长度。
就是它区分了初始化和未初始化的 两种数据,初始化以后的数据在.data节里面,未初始化的
在.bss节里面,.bss节里面实际上是不占磁盘空间。
所以使得空间效率更好,这个就是.bss节。
.bss节因为它 放的都是未初始化的全局变量和静态的变量。
因为它的默认的初始值都是0,所以我们不需要在磁盘里面占空间给它
分配相应的初始值。
只要我们把它的初始值设置0就行了,所以我们不需要让它占空间。
这样我们就把未初始化的变量和已经初始化的变量就分开来了。
已经初始化的变量因为它需要给它具体的这个初始化的值,所以这些初始化的这些
值叫初始值吧,它需要占磁盘空间,我们在磁盘空间里面把这些初始值存放好。
那么到时候我们直接分配给这些变量,而.bss节呢 它就不需要放初始值了,因为我们总是默认的让它等于
0,所以呢,这个节当中的每一个变量它在执行的
时候占几个字节,我们只要把它占用的字节长度给它记录下来,
而不需要在磁盘当中记录它的初始 值。
所以提高了磁盘的利用率,所有未初始化的这些全局变量和局部变量
都汇总到这个地方,在节头表里面说明这个节
一共占多大的空间,最后映射到存储器里面去的时候, 把这空间留出来就可以了。
BSS这个名称 实际上最初是某个汇编程序当中
用到的一个伪指令,这个伪指令的目的也是为符号预留一块内存空间的,
所以可以看出它的意思和我们现在这个意思是一样的。
所以在ELF格式当中呢就沿用了这个BSS这样的一个名称, 称为.bss节。
在ELF的可 重定位目标文件格式当中呢,除了刚才我们讲的这些节以外,
还有剩下来的其它的节,比如说这个节, 这个叫符号表节,就是
符号表的这个节,存放的是所有的函数名 和全局变量,就是函数的名称对应
的,函数名是一种符号,全局变量的名称也是一种符号。
所有这些符号,实际上都有相应的信息,比如说每个函数有它的一些信息,
全局变量有它的一些特征信息,这些特征信息都记录在这个符号 表当中。
然后呢,还有可重定位的节。
这个节,重定位的节,它是对.text节当中的一些重定位信息进行描述的。
用于修改代码段中指令中的地址信息,也就是说我们对
.text这个代码段当中的指令进行重定位的时候,
要用到的一些信息,全部在这个节里面。
相应的下面这个节呢,就是在.data节当中,
要进行重定位的时候,所用到的一些重定位信息 就放在这个节里面。
还有呢debug节,主要是调试用的一些
符号表,就是在这个命令当中用了-g这个选项的时候,
会生成调试用的信息,这个信息都在.debug节里面保存。
另外还有字符串 这个表,字符串表里面包含的
都是字符串,也就是节的名称。
还有那些符号,这个符号表示,比如说这个符号是函数名
或者是变量名,这些变量名或者函数名就是一种符号,在符号表
里面出现的,这些符号当然都是一个字符串,所以这些字符串的信息
是在这个里面出现的,包含在这个
符号表当中和.debug中的一些符号和节名 都是在这个里面表示。
最后呢是一个节头表。
这个节头表非常重要,它里面记录了每一个节的节名,就是记录了
这个.text、 .rodata这个节名,以及每一个节
它在文件当中的起始位置,相对于这个0的起始位置。
每一个节的名称以及起始位置 还有每一个节占的大小等等,都在节头表里面
描述,这样的话我们去读这个ELF的头。
就可以找到节头表,然后在节头表里面呢,根据 节的偏移,就可以找到这个节,然后把这个节的信息读进来,进行处理。
然后每一个节,它的节名以及起始位置等等 都在这个节头表里面记录了。
后面呢我们会详细的介绍, 并且会举些例子来说明。
这儿呢只是大概的看一下 一个可重定位目标文件,它到底包含哪些信息。
[音乐] [音乐]