/hust_chen/blog/item/54a8c516231d0c0ec93d6d3e.html
linux下动态链接库的加载及解析过程(ZZ)
-12-18 15:19
表面上看,动态链接库(dll)的加载及解析是一个十分繁复的过程,其中牵涉到的数据结构及其之间的关系也让人望而生畏。Whatever,学习这 事情,说到底是没有捷径可走的,除了死啃仅有的一些资料,如ELF format、Loaders and Linkers,借用objdump及gdb来跟踪程序的执行流程,对于理解过程也是颇有帮助的,anyway,不嫌烦就好了。
在不同的体系下,dll的加载及解析过程是有差别的,这是因为不同体系下生成的ELF文件不尽相同,譬如说,在IA32下,会生成.plt这个dynamic section,但到了MIPS下,便成了.MIPS.stubs。
尽管如此,排除表面上的差异,其本质却是一致的。先说说ELF文件的format,ELF实质是可执行文件的一种格式,对于机器而言,所有的可执行文件不 过是二进制代码的流水罢了,但为了方便管理这些二进制代码,编译器便将这些机器码分为几个段,并统计出相关的信息,通俗地说,也就是对机器码包装包装而 已。Technically speaking, 每个ELF文件都有一个ELF header,保存的是program header与section header的偏移量。关于program header与section header,以后再说呗。
如果某个文件是动态编译的,那么其对应的ELF文件中肯定会有一个.dynamic section,这个section包含了dll的加载与解析所需要的信息。.dynamic中的entry因类型不同而被赋予不同的含义,最为常用的是下面几种类型的entry:
·DT_NEEDED:d_tag=1,d_val中的值为needed library的name在string table中偏移量。如果所需要动态库的数量为n个,则相应类型为DT_NEEDED的entry也应该有n条;
·DT_PLTGOT:d_tag=3,d_ptr中的值为.plt(procedure linkage table)或.got(global offset table)的起始地址,在MIPS体系下,这个值是指向.got的起始地址;
·DT_HASH:d_tab=4,d_ptr中的值为hash table的起始地址;
·DT_STRTAB:d_tab=5,d_ptr中的值为string table的起始地址;
·DT_SYMTAB:d_tab=6,d_ptr中的值为symbol table的起始地址;
·DT_RPATH:d_tab=15,d_val中的值为needed library所在的路径名称(注:needed library不一定就会在这个路径下,detail参见dll的加载过程)在string table中的起始地址。
这里面牵涉到了一些重要的数据结构:
(1) hash table:其作用是根据symbol name�