elf动态库加载和符号解析

转自:elf动态库加载和符号解析 - 简书

1、动态符号表包含了动态库的函数签名

  • .dynsym(动态符号表)
    这里面主要存放了函数名称,保存了导入和导出等函数名字信息,符号表里将包含进程中所有的动态链接所需要的符号。dynsym会被全部加载到内存。
  • .dynstr(动态字符串表)
    So文件里面包含全部的字符串,dynsym只是该字段的一部分
  • .hash
    这个是字符串表的一个hash序列,主要用于快速索引对应字符串,如果修改So文件里面的字符串,该字段也需要进行修改。这也就是为什么So文件直接修改字符串会出现崩溃等问题。

2. 动态链接器的符号查找

  • 当一个新的共享对象被装载进来的时候,它的符号表会被合并到全局符号表中,所以当所有的共享对象都被装载进来的时候,全局符号表里面将包含进程中所有的动态链接所需要的符号。
    关于全局符号介入这个问题,实际上Linux下的动态链接器是这样处理的:它定义了一个规则,那就是当一个符号需要被加入全局符号表时,如果相同的符号名已经存在,则后加入的符号被忽略。从动态链接器的装载顺序可以看到,它是按照广度优先的顺序进行装载的,首先是main,然后是b1.so、b2.so、a1.so,最后是a2.so。当a2.so中的函数a要被加入全局符号表时,先前装载a1.so时,a1.so中的函数a已经存在于全局符号表,那么a2.so中的函数a只能被忽略。所以整个进程中,所有对于符合“a”的引用都会被解析到a1.so中的函数a。所以当程序使用大量共享对象时应该非常小心符号的重名问题。

  • 资料上用到的一个概念是“全局符号表“,其实这是一个伪概念,内存中并不存在这样一个表,libdl.so或者ld-linux.so会将所有已加载到内存中的可执行模块(主程序或动态库)的相关指针放入一个全局的链表中,通过这个全局链表可以访问到所有可执行模块的动态符号表,仅此而以。我们可以假定这个全局链表是一个“全局符号表“,但其存储的内容远远不止符号表这么简单,而是可执行模块的所有相关信息,如重定位信息、代码段地址、got段地址等。

  • ld-linux.so的工作是在程序运行前把程序需要的so找到并进行连接.然后程序才开始运行
    libdl.so的工作是在程序运行时找到指定的so并连接,函数包括dlopen,dlclose,dlsym,dlerror.

你可能感兴趣的:(linux,app,linux)