本篇文章以linux为平台为例,演示elf动态解析符号的过程
【相关文章:第一次装Redhat!】本篇文章以linux为平台为例,演示elf动态解析符号的过程。 【扩展阅读:linux 终端支持中文和透明】
【扩展信息:libpam-modules出错及修复】不正之处,还请斧正。 通常,elf解析符号方式称为lazy mode装载的。这种装载技术是elf平台上 默认的方式。在不同的体系平台在实现这种机制也是不同的。但是i386与sparc 在大部分上是相同的。 动态连接器(rtld)提供符号的动态连接,装载共享objects与解析标号的引用。 通常是ld.so,它可以是一个共享object也可以是个可执行的文件。 ★★ 符号表(symbol table) 每个object要想使它对其他的elf文件可用,就要用到符号表(symbol table)中 symbol entry.事实上,一个symbol entry 是个symbol结构,它描述了这个 symbol的名字与该symbol的value.symbol name被编码作为dynamic string table的索引(index). the value of a symbol是在elf object文件内该 symbol的地址。该地址通常需要被重新定位(加上该object装载到内存的基地址 (base load address)). 从而构成该symbol在内存中的绝对地址。 一个符号表入口有如下的格式: typedef struct { elf32_word st_name; /* symbol name (string tbl index) */ elf32_addr st_value; /* symbol value */ elf32_word st_size; /* symbol size */ unsigned char st_info; /* symbol type and binding */ unsigned char st_other; /* no defined meaning, 0 */ elf32_section st_shndx; /* section index */ } elf32_sym; 可执行文件他们知道运行时刻他们的地址,所以他们内部的引用符号在编译时候就已 经被重定位了。 ★★ got(global offset table) got是一个数组,存在elf image的数据段中,他们是一些指向objects的指针(通常 是数据objects).动态连接器将重新修改那些编译时还没有确定下来地址的符号的 got入口。所以说got在i386动态连接中扮演着重要的角色。 ★★ plt(procedure linkage table) plt是一个这样的结构,它的entries包含了一些代码片段用来传输控制到外部的过程。 在i386体系下,plt与他的代码片段entries有如下格式: plt0: push got[1] ; word of identifying information jmp got[2] ; pointer to rtld function nop ... pltn: jmp got[x + n] ; got offset of symbol address push n ; relocation offset of symbol jmp plt0 ; call the rtld pltn + 1 jmp got[x +n +1]; got offset of symbol address push n +1 ; relocation offset of symbol jmp plt0 ; call the rtld 当传输控制到一个外部的函数时,它传输执行到plt 中跟该symbol相关的那个entry (是在编译时候连接器安装的)。在plt entry中第一条指令将jump到一个存储在got 中的一个指针地址;假如符号还没有被解析,该got中存放着的是该plt entry中的 下一条指令地址。该指令push一个在重定位表中的偏移量到stack,然后下一条指令 传输控制到plt[0]入口。该plt[0]包含了调用rtld解析符号的函数代码。该 ... 下一页