elf文件逻辑解析

        以下只是个人版本的,对elf文件的相关格式的理解,不是官方版本的,而且因为喜欢举例子,所以是通过举例子的版本来的

        首先是我们的shdr 是section header的简称,换句话说,我们这是一个节头,但是一个elf中是一堆节(section),所以是一个elf多个节,每一个节都有一个节头

        然后是我们的节头的内容,这里我们以一种名为动态节的头开始,首先节头这种数据结构的名称为:shdr

        而我们是怎么确定这个节头表的呢,事实上,节头表是一个数组,他不是通过节头表-节这样的线性结构,而是节头表是一个数组,这个数组中记载了所有的节头,这样的形式来实现的。所以这样的节头表是一个数组,我们怎么确定这个数组呢,答案是数组肯定有地址,我们的节头表是一个数组,数组中记载了一堆节头,我们这个地址在哪里记载呢?答案是elf头,这是另一个头,它里边有一个叫做e_shoff的属性,记载的就是他的地址,也就是sh表的地址

        通过节头表,我们就得到了一堆节头,这些节头怎么看呢?既然是数组,除了起始地址,一定还有别的东西,这些东西之一就是数量,之二就是大小,这些照样是在elf头中定义的,对应的属性是

e_shnum, e_shentsize,这样的话,节头表这个数组就成功制作了。

        然后我们就要看这个节头中的内容,比方说我们想找一个节,比方说动态节,然后我们就要有这个节的名称sh_name,这个玩意实际上是一个偏移量,并且这个偏移量对应着一个节的名字,然而我们必须知道这个名字到底是多少,这时我们有一个方法,那就是我们将所有的名字都存放在一个表中,这个表里就是所有的名字了。此时我们就有了e_shstridx,这个stridx是一个索引,索引的其实是一个节头,叫.shstrtab,我们只是获得了这个索引的位置,而这个索引对应的节中记载的东西却很重要,其里边就是所有的表的名字,因此通过sh_name我们就可以知道偏移量,而偏移量知道了,根据shstrtab中对应的索引和名字的一一对应关系,就可以知道他的名字了。

           现在我们知道的是这样的:

            elf头记载了节头表,节头表可以索引到节头,节头中记载的是节的信息,举个例子就是e_shoff为6376,e_shnum为29 e_shentsize为64,我们并不知道现在这个节是什么,所以我们循环搜索,看到了一个节头,然后这个节头是第idx个节头,比方说1,所以6376+1*64 = 6440,这就是第二个节头的偏移地址了,根据他的信息我们可以知道节的偏移地址,以及节叫什么名字。

        而关于他的名字叫什么,因为我们有一个e_shstridx,所以我们知道了这个叫做.shstrtab的节头在节头表中的位置,然后我们继续看,因为这玩意得到的最终的结果是相对于文件头的偏移地址,所以我们自然找到了这个表,又因为每一个表项的大小是64,所以可以知道节头是什么了,又因为节头中有一个属性叫做sh_offset,这是相对于elf文件的地址,所以我们知道了节在elf文件中的位置为0x17e1,而sh_name则是我们的某个节头中给出的一个值,这个值是多少呢,很简单是0x1b,并且直到遇到字节值为00才退出。所以其之间对应的ascii码名字即为该节头中的节的名字,这样我们就可以知道每个节的名字了,这是通过节头中的索引和我们亲爱的.shstrtab得到的。

        然后我们好奇的事情是flags,其对应了这个节是否在进程中占用了内存单元,然后是sh_addr是映射的对应起始地址,根据sh_offset得到节的位置,然后sh_size显示节的大小,sh_entsize表示了每一个表项的大小,而如果有值,说明是线性存储的,且每一个项大小固定,否则表示是非线性存储的,可以不用考虑这个属性。

        一件事需要注意的是,我们的strtab和shstrtab都是字符串表,但是储存的等级不同,strtab存储符号而shstrtab存储的是段名等信息。

        下面对一些具体的段进行分析,其中一个就是符号段,因为变量和函数统称为符号,并且函数名和变量名统称为符号名,所以有了符号就可以更好的链接了。因此每一个elf文件都会有一个符号表,表中记载了所有的符号,自然这个表可以通过段头表得到,其实就是说这就是一个段。由于这是一个特殊的段,所以我们会将这个段以一种数据结构方式展示出来。所以我们首先会有name,这就是他的名字,然后是符号的值,对于一个符号来说,如果不是common块,则st_value是符号在段中的偏移量,现在只是有了偏移量,还得知道符号在哪个段中,这是通过属性st_shndx得到的。对于common块则表示其对其属性,而在可执行文件中则表示符号的虚拟地址。对于包含一个数据的符号,st_size表示这个符号的大小,比方说double就是8(字节),而num则是我们的符号在符号表中的下标,之后是name,也就是符号的名称,那么这个名字怎么获得呢,这就要说明为什么字符串表二符号表都必须有了,原因之一就是我们的name其实是偏移,谁的偏移,答案是strtab的偏移量,相对于strtab的基准的偏移就是我们的name的本质了。所以这样我们就将elf文件头eh,段表头sh,特殊段(字符串段strtab和符号表symtbl表示出来了)

              

 

   

             

          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值