ELF的.gnu.hash节
之前说过要专门写一篇分析ELF.gnu.hash节的文章,看过其它类似的文章要么是直接翻译要么就是模糊带过,直接翻译成中文后对新手来说很多地方晦涩难懂,模糊带过是不利于深入的,经过研究之后我特意写一篇来弥补他们的不足,希望可以给新手起到参考作用。
ELF的.gnu.hash节是对原生的.hash节的增强和改进,目的是用于快速查找符号的。该节保存的是一个哈希散列表,我们继续拿之前的示例文件来分析,根据示例文件我们已经知道了.gnu.hash节在节头表中的索引,现在让我们继续看看.gnu.hash节的描述信息,即节头表中的描述条目
图中可知.gnu.hash节的位置和大小,位置即通过文件中的偏移量去定位,偏移量是0x308,十进制是776,大小是0x24,十进制是36
只知道该节保存的是一个哈希散列表,那么我们看看这个哈希散列表的结构是什么样的,让我们一起拆分一下。
.gnu.hash节由4部分构成:
第1部分是:Header。谨记:header的内容决定下面3部分内容的大小。header又分别由4个条目构成,每个条目大小是固定的4个字节(因此header大小实际是16个字节,切莫被翻译搞混了),这4个条目分别是:
nbuckets。4个字节,决定了第3部分即Hash Buckets的条目数量,1个Hash Buckets占4个字节,如果nbuckets是2,则Hash Bucekts就占8个字节,依次类推,所以说nbuckets的值决定了Hash Bucekts的大小。如上图我的示例文件nbuckets是2。
symndx。4个字节,symndx是动态符号表中可通过哈希表访问的第一个符号的索引。symndx决定了第4部分即Hash Values的条目数量,1个Hash Values占4个字节,(dynsymcount – symndx)*4的结果就是Hash Values的实际大小,dynsymcount如果有人不清楚是什么,这里我明确告诉你们,dynsymcount表示的是动态符号表的条目数量。如上图我的示例文件symndx是6,dyncsymcount是多少呢?是7,在ELF的.dynsym节这篇文章已经给出了。
maskwords。4个字节,决定了第2部分即Bloom Filter的条目数量,1个Bloom Filter在32位系统占4个字节,在64位系统占8个字节,我是64位系统所以是8个字节,maskwords如果是1,那么Bloom Filter就是8个字节,如果maskwords是2,那么Blooom Filter就是2*8=16,那么Bloom Filter的实际大小就是16个字节,以此类推,所以说maskwords的值决定了Bloom Filter的大小。如上图我的示例文件maskwords是1。
shift2。4个字节,Bloom Filter使用的移位计数。如上图我的示例文件是6
第2部分是:Bloom Filter。32位系统单个条目占4个字节,64位系统占8个字节,条目数量由第一部分即header里的maskwords的值决定,我这儿是64位系统,Bloom Filter的大小是maskwords * 8。如上图maskwords是1,1*8=8,所以我这里Bloom Filter占8个字节。
第3部分是:Hash Buckets。单个条目占4个字节,条目数量由第一部分即header里的nbuckets的值决定,Hash Buckets的大小是nbuckets * 4。如上图nbuckets是2,2*4=8,所以我这里示例文件Hash Buckets占8个字节。
第4部分是:Hash Values。单个条目占4个字节,条目数量由第一部分即header里的symndx的值决定(准确说是由dynsymcount和symndx的值决定)。Hash Values的大小是(dynsymcount – symndx) * 4。如上图symndx是6,dynsymcount根据ELF的.dynsym节分析已经知道是7,(7-6)*4=4,所以我这里的示例文件Hash Values占4个字节。