库用于将相似函数打包在一个单元中。Linux支持两种类型的库:静态库(在编译时静态绑定到程序)和动态库(在运行时绑定到程序)。Linux系统使用的动态库是ELF格式,后缀名为so。
1 加载
动态库内部划分为段,段分为不同的类型:
-
PT_LOAD段:包含代码或数据,是需要被映射到内存中的,每个段有不同的访问权限(读、些、执行);
-
PT_DYNAMIC段:包含动态链接信息,如符号表、重定位表、引用的其他库等。
其他段类型暂不说明。
加载器将库文件第一个PT_LOAD段和最后一个PT_LOAD段之间的内容映射到一段连续的内存地址空间(好处是任意代码和数据的相对地址固定),其首地址称为基地址(如图)。
库的加载只是把文件内容映射到内存地址,但没有真正读取文件数据,在发生内存缺页异常时才由操作系统读入对应的文件数据到内存。延迟读取文件可以加快库的加载速度。
1.1 预链接
一般来说,映射的基地址是不固定的,但如果动态库使用了预链接(prelink)技术,则会被映射到预定的地址(保存在文件上)。如果预定的地址范围已经被占用了,则加载失败(Androidlinker是这样,其他加载器可能不同)。Prelink的好处是简化重定位,加快加载速度。