动态链接后ELF中的Section Name

背景

在So动态链接后,读取ELF文件,发现无法读取Section Header中的名称列表。即,无法在EShdr中根据e_shstrndx找到Section对应的名字。

可是在readelf -a lib.so中,可以根据Section Header读取到Section对应的名称。

Section Header String Table Index

而读取出来的结果如下:

Section Header

其中,shstrtabstrtab的类型都是STRTAB,但是shstrtab仅仅只保存Section Name的字符串表,而strtab则包括其他的变量名、符号名等的字符串表。

问题

  • 为什么在运行时无法通过Section Header中的sh_name来找到对应的名称?

Section Header的

  • 为什么要分为strtabshstrtab两个字符串表?

原因

从运行时的日志来看

  • 根据ELF头中的e_shoff找到ELF_SHDR
    • libart.so加载后的位置在753042b000-7530a14000
    • 加载后的基址为:753042b000PHDR的地址为:753042b040
    • 计算得到的SHDR的地址为7530b55520

运行日志:

libs line :753042b000-7530a14000 r-xp 00000000 fd:00 3439 /system/lib64/libart.so
base_addr:753042b000   PHDR :753042b040   shdr_offset:72a520
SHDR :7530b55520  shstr:7530b55ba0

运行时日志是通过/proc/self/maps中获取libart.so得到的基址,与上面通过readelf读取的ELF文件并不是同一个!该日志的基址和偏移量与上面的图无关。

运行后的结果可知: 通过e_shoff所计算的出来的SHDR的地址已经超出So加载的地址了。

SHDR- libart.so的页结束地址 = 7530b55520 - 7530a14000 = 141520

而在运行时候的动态链接是根据Segment来加载So中的文件,原因是希望尽可能小的使用内存页面,并且提升加载速度。

ELF链接与执行时视图

于是查看程序头部分,发现LOAD类型的段中,仅仅只有.dynstr这个字符串表会被加载到内存中。

程序头

也就是说:

在So动态链接到内存中时,.shstrtab.strtab这两个Table是并没有加载到内存中的。ld仅仅只会加载.dynstr这个Table就够用了。

并且从执行视图来看,ELF也不一定会有Section Header Table。

从IDA Pro打开的角度来看

从Section Headers中可以看到:

  • strtaboffset395ac,大小为170c
  • shstrtaboffset3acb8,并且大小为194

可以看到strtab之后紧接着就是shstrtab395ac+170c = 3acb8

打开IDA Pro可以看到在文件的395ac处就是strtab的字符串表:

strtab

而在文件的3acb8处,可以看到是Section Header Name的字符串:

shstrtab

结论

shstrtabstrtab这两个表仅仅只是链接后保存在So文件中的,而在链接之后的执行视图层面,这两个字符串表不会被加载到内存中。

readelf这个程序中,会在文件中根据shstrtab表的偏移量来查找Section对应的名称,然后输出文案。

并且,在执行视图中,可能没有SHDR,所以在链接完的文件中可以根据SHDR中的偏移量来找到对应的名字,而在加载到内存之后的执行视图中,不能按照SHDR来查找Section的名字了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券