ELF文件概览
它是软件按照一定格式输出的文件,就比如MP3文件也是音乐编辑软件输出的文件一样,因此实际上比gcc还高一层。
包含三大块:文件头,段表,段。再继续向下学习时,就是去理解各种不同的段的设计和内容,文件头和段表了。
文件头
段表
同样是一个段,.symtab,该段的结构是一种结构体数组(许多其它段也是类似结构,只是结构体类型不同),可以设想该结构体可能的信息:名称,值,大小(不能够通过值来确定符号大小,4个字节同样可以表示一个字节大小的数字,因此直接通过此成员给出大小更方便),所在段,这四个信息是比较容易理解的;
段
字符串表
两种字符串表。那么为什么要在文件头中给出此索引呢?为何不同时给出字符串表在段表中的索引位置?
符号表
字符串表一开始给人的印象就是代表段名,变量名,函数,但这种直觉是错误的,符号表才真正代表了变量和函数以及其它一些符号,字符串表仅仅是表示名称的辅助手段,试想一下你知道了一个变量在字符串表中的索引,除了能够知道名称外,其它任何信息也或许不到,而一个符号对应的信息全都在符号表中。
重定位表
其它
还有一个比如debug调试信息的段,这是另外的一个内容,反正想添加什么功能的话,都可以向其中添加;
符号
符号,如果依面向对象的思想来审视,是ELF文件,以及编译器,链接器主要的针对对象,众多的行为以处理它的问题为目标,所以接下来一段时间,所有问题都将围绕它来进行。
符号是一种更加抽象的概念。
相比于变量和函数来说,它的覆盖范围更广,主要包括:定义在一个文件内的全局符号,外部符号(在本文件内引用,但是没有定义),段名,局部符号,行号信息。更深的理解......
目前关注在全局符号与外部符号上,它们和链接更为相关。
符号的源
我们不可能直接在一个文件面就写出 i = 2这样的语句,要让一个文件中出现的符号合法需要去定义,或者声明它(外部引用声明extern),所以一个文件中符号的源无非就是这两种,定义和外部声明,当独立的单个文件中出现的符号都有了自己的源之后,针对单个文件,编译器便认为这样的文件是合法的,可以编译通过(当其它要求均满足规则时)。
符号的汇
单个文件的编译通过之后,下面就是链接过程,当不同文件的符号表合并在一起的时候,全局符号在此时可以被其它目标文件看到,唯一性就受到了挑战,这是强符号,弱符号机制出现的因,强弱符号因此也只会针对全局符号,初始化的全局变量“源”力更强,因为为强符号,而未初始化的全局变量则相应为弱符号。规则是简单的:一山不容二虎,则两强不能同时存在;一虎和一兔,虎会吃掉兔子的;许多兔子在一块的话,只留个头最大的那个
关于强弱引用
这对概念和符号的源相关,如前所述,在一个文件中的全局变量和函数是有两种源的,一个是真源,确实有扎根的定义,还有一种是伪源,告诉编译器符号在外面,这时候符号就如水面上的浮萍,编译器认为它有根,但究竟有没有根,等到链接时才能发现,对于弱引用来说,即便最后发现没根也是可以通过的,但是强引用就不行了。这对概念主要用在函数的覆盖上面,想要掌握其各种场景下的反应还需要时间。