在So动态链接后,读取ELF文件,发现无法读取Section Header中的名称列表。即,无法在EShdr
中根据e_shstrndx
找到Section对应的名字。
可是在readelf -a lib.so
中,可以根据Section Header读取到Section对应的名称。
Section Header String Table Index
而读取出来的结果如下:
Section Header
其中,shstrtab
和strtab
的类型都是STRTAB
,但是shstrtab
仅仅只保存Section Name的字符串表,而strtab
则包括其他的变量名、符号名等的字符串表。
Section Header
中的sh_name
来找到对应的名称?
Section Header的
strtab
和shstrtab
两个字符串表?e_shoff
找到ELF_SHDR
libart.so
加载后的位置在753042b000
-7530a14000
753042b000
,PHDR
的地址为: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。
从Section Headers中可以看到:
strtab
的offset
为395ac
,大小为170c
。shstrtab
的offset
为3acb8
,并且大小为194
。可以看到strtab
之后紧接着就是shstrtab
:
395ac
+170c
= 3acb8
打开IDA Pro可以看到在文件的395ac
处就是strtab
的字符串表:
strtab
而在文件的3acb8
处,可以看到是Section Header Name的字符串:
shstrtab
shstrtab
与strtab
这两个表仅仅只是链接后保存在So文件中的,而在链接之后的执行视图层面,这两个字符串表不会被加载到内存中。
在readelf
这个程序中,会在文件中根据shstrtab
表的偏移量来查找Section对应的名称,然后输出文案。
并且,在执行视图中,可能没有SHDR
,所以在链接完的文件中可以根据SHDR
中的偏移量来找到对应的名字,而在加载到内存之后的执行视图中,不能按照SHDR
来查找Section的名字了。