ELF学习

ELF是Executable and Linkable Format的缩写,它是一种对可执行文件、目标文件和库文件使用的文件格式。
从源代码到形成最终的目标文件,这个过程是由编译器帮助完成的;
编译器还"偷偷"增加了很多额外的代码,来完成参数入栈、保存函数返回地址等等很多工作,
这样使得最终的程序得以正常的运行。

对于库文件和最终的可执行文件,其ELF格式可能会略有不同,不过也都差不多。
ELF文件基本的布局是:
库文件             可执行文件
ELF文件头          ELF文件头
程序头表           程序头表
section1           parag1
section2           parag2
...                ...
sectionn           paragn
节头表             节头表

使用readelf -S命令可以用来查看ELF文件中有哪些section信息,比如:
.text,这个是代码段;
.data,是数据段,是已经初始化了的全局变量;
.bss,是未初始化的全局变量;
.symtab,这个节用来确定符号的名称和符号值之间的关联;
.strtab,这个节保存了字符串数组;
...

以上是程序的静态表现形式。
而程序运行时,会形成一个程序的进程地址空间。
这时共享库是动态加载的,共享库在进程虚拟地址空间中的位置是无法事先预知的。
只能确定共享库内部各个符号的相对位置。
可以通过cat /proc/pid/maps命令来查看进程号为pid的进程的动态表现形式。

这样我们就能建立静态和动态之间的关联性:根据动态的地址来计算一个符号在共享库中的相对位置。

为什么很多共享库在进程虚拟地址空间中有好几份呢?
以下以pthread为例,
40db8000-40dcd000位于这一段地址空间的应该是pthread.so的text section;
40dcd000-40dd4000位于这一段地址空间的是?
40dd4000-40dd5000位于这一段地址空间的是rodata section吗?
40dd5000-40dd6000位于这一段时间空间的是data/bss section吗?
40db8000-40dcd000 r-xp 00000000 fe:00 368        /lib/libpthread-2.12.2.so
40dcd000-40dd4000 ---p 00015000 fe:00 368        /lib/libpthread-2.12.2.so
40dd4000-40dd5000 r--p 00014000 fe:00 368        /lib/libpthread-2.12.2.so
40dd5000-40dd6000 rw-p 00015000 fe:00 368        /lib/libpthread-2.12.2.so

这个应该也是可以验证的。
首先编译好动态库,这样动态库内部的各个section的位置、内容也就能够确定下来了。

那进程的虚拟地址空间是如何形成的呢?
linux系统调用execv用来装载一个ELF可执行文件,从而就会形成进程的虚拟地址空间。
所以为什么虚拟地址空间会是这样,这都是内核来帮忙完成的。

有了以上的学习,
我们就能够通过一些能够分析ELF二进制文件的工具如nm/readelf/objdump等来查到符号和符号所在地址直接的关联。
这能够帮助我们debug。

符号(symbol)是一个程序的创建块,比如他可能是一个变量名或函数名。

符号表是所有符号及其对应地址的一个列表。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值