elf .got .plt 表以及共享库加载原理,在没有mmu的单片机上实现共享库

    之前研究了在没有mmu的单片机上实现动态加载,因为之前使用的是keil编译工具,它使用的是arm公司自己开发的编译器,很多地方不好研究。其实使用gcc也是可以开发Stm32的,最近发现一个开发工具叫tureStudio,是一个利用Eclipse与gcc组合起来的开发工具,特点是使用了gcc编译器,资料多呀,特别是对于elf文件格式的与linux下基本一模一样。下面就总结一下最近研究到的东西。

    elf文件格式大致可以分两种,一种是执行程序,一种是动态库。可执行程序的elf文件内的地址是固定地址,代码在加载的时候都必须被加载到固定位置的地址上,如果单片机有mmu,就必须加载到固定位置的虚拟地址上。动态库的elf文件内的符号地址都是可以重定向的,下面我们就具体研究一下这个动态库,这对于单片机上进行动态加载是非常重要的。

    介绍两个工具:readelf.exe 以及 objdump.exe    前者可以对elf文件的各个段内信息等进行分析,后者对于段内代码可以进行反汇编等。对于研究elf文件非常有用

    解释:符号:函数,变量都叫符号

    一般来说一个elf文件分为,elf头,程序表,section等 部分。一切elf内的数据都可以通过这个elf头得到。在elf文件中程序头表如下图:


上面的load段代表了需要被加载进内存的代码位置等信息,dynamic代码动态段的位置,下面会单独说动态段。


elf文件中section段一般如下:

    

一般来说关注.got .got.plt .rel.dyn表,这几个表对于重定向来说比较重要,对于在不同文件内进行重定向.dynamic段比较重要。

    在这里.got表存放了被重定向的符号的地址,一般在.rel.dyn表内会给出需要修改的.got表的位置。

    在.got.plt表中存放了间接访问的代码,用于延迟加载。什么意思呢?意思是在程序中去访问某一个函数时并不会立刻去访问到那个函数的地址上去,而是通过了先去访问这个.got.plt表中的一小段代码,然后这一小段代码再去从.got表中得到函数被重定向后的地址去访问。这样的好处是不用去修改代码,只需要修改.got表中的内容就行了。.got.plt表中的内容像下面一样:

    

上面红色框内的就是一个.got.plt中的一项,当一个函数被执行时,先执行.got.plt表中的代码吗,这段代码会去.got表中找到真实的函数地址,然后进行访问。可以看到,其实这样会降低一些运行效率。

    下面说说重定向是怎么实现的,其实就是对.rel.dyn表进行遍历,先看下面这张表:


这里我们只关系R_ARM_GLOB_DATA 与R_ARM_JUMP_SLOT这两个类型的数据,可以看到一个offset项,这个就是其在内存中的偏移,执行观察会发现指向的其实是.got表中的内容,通过这个偏移去改变其地址,就实现动态加载,注意这里只是简单实现,真正要做的有很多。

    说完了重定向,说下动态库之间是如何重定向的,其实就是我们之前说的dynamic中的数据,这张表中包含了一些段内信息,同时也包含了需要使用到的共享库,我们看看下面这张图:

    

从上面我们可以看到,一个类型为NEEDED的项,这一项包含了我们需要使用到的共享库,当我们在编译器中包含了共享库的时候,编译器就会在这里增加一项,当我们动态链接这一个程序的时候,程序就会在指定目录下去找这一个共享库,并与当前共享库进行重定向。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值