最是那一低头的温柔,像一朵水莲花不胜凉风的娇羞,道一声珍重,道一声珍重,那一声珍重里有蜜甜的忧愁 —— 徐志摩
符号表 (symbol table) 中保存着符号的定义或者引用信息。对于 android so 文件来说,.dynsym 符号表保存着库文件的导入和导出符号。
用 readelf 看一下 android liblog.so 的 .dynsym 动态符号表:
符号 __cxa_finalize 的 Ndx(st_shndx) 为 UND,表明该符号在本 so 中未定义,需要去 liblog.so 的依赖库中去找。那 liblog.so 依赖哪些库?可以从 .dynamic 中找到。
符号 __cxa_finalize 的定义应该在 libc.so 中。
符号 __android_log_vprint 的 Ndx(st_shndx) 为 8,表示该符号在本 so 中有定义,并且定义该符号的 section 在 section header table 中的索引是 8。看一下 section header table:
可以看到,符号 __android_log_vprint 定义在 .text section 中,这也是理所当然。所以 __android_log_vprint 是一个导出符号,由那些需要打印日志的程序调用。
因为符号 __android_log_vprint 是在本 so 中定义的,所以看到其 Value(st_value) 不为 0。android linker 在做符号重定位工作时,就是由这个 st_value 找到该符号定义在内存中的地址。不过 0x00001539 当然不是符号的最终的内存地址,linker 会再加上 liblog.so 在内存中的基址,所以 st_value 相当于一个地址偏移。
回过头再看一下,符号表其实就是一个结构体数组,每个结构体描述一个符号的信息。结构体的定义如下:
其中 st_value 和 st_shndx ,上面已经有所介绍。
st_name 是符号的名字,这里保存的只是一个引用字符串表的索引值。
st_size 对于导入符号来说,根本不知道人家有多大,所以为 0。对于导出符号,则会明确标明大小。
st_info 包含了符号的类型和绑定属性等信息,后续笔记再具体写。
st_other 保留未用,不必关心。