动态链接(一) .got与fPIC

来源:互联网 发布:知乎广告文案 编辑:程序博客网 时间:2024/06/03 13:47

1>动态链接过程的关键:在需要的时候装入,如果其他程序同样需要这个模块,则用动态链接器链接即可,即地址重定位找到所需的函数入口

 

2>动态链接库的最终装载地址不是在编译时确定的

 

3>共享对象在建立时,不能假设自己在虚拟地址空间的具体位置,在装载时会进行基址重置

 

4>与此不同的时,可执行文件基本可以确定自己在虚拟地址空间中的起始位置,它可以选择一块固定的空间地址,比如linux下0x08040000 windows 0x0040000

 

5>装载时重定位:思路是在连接时,对所有绝对地址的引用不做重定位,而把它推导装载时来完成,一旦装载地址确定,则系统才对绝对地址重定位

 

6>链接时重定位,装载时重定位windows有叫基址重置

 

7>地址无关代码:希望程序中共享指令部分在装载时不需要因为装载地址的改变而改变,所以实现的基本思想:把指令中那些修改的部分分离出来,跟数据放在一起,这样指令部分就可以保持不变,而数据部分可以在每个进程中拥有一个备份,(PIC)

 

8>把共享对象中的模块分为模块内部引用和模块外部引用;按照不同的引用方式又可以分为指令引用和数据数据访问

 

9>call __i686.get_pc_thunk.cx 汇编码:mov %(esp) %(ecx)  的到当前的指令pc

 

10>模块间数据访问:elf的做法是在数据段里面建立一个指向全局变量的指针数组,也称全局偏移表(GOT).当访问全局变量时,程序首先找到GOT,然后根据GOT中变量所对应的地址索引。

 

11>动态链接器,链接器会在装载模块的时候查找每个变量所在的地址,然后填充GOT表象。由于.GOT是放在数据段,由于.GOT段本身放在数据段,所以他可以再模块被装载时被修改,并且每个进程都有独立的副本,相互不受影响

 

12>ELF共享库在编译时,默认把模块内部的全局变量当做定义在其他模块的全局变量,然后通过.got来实现变量的访问(注意:.got段在elf可执行文件里)当elf需要的共享模块被装载时,如果某个全局变量在可执行文件中拥有副本,那么动态链接器就会把GOT中的相应地址指向该副本

 

13>-PIC地址无关 ,-fPIC按照跨模块模式产生代码。

 

14>当动态链接文件被elf加载并被动态链接器链接,填充elf中的.got项时,它的数据段部分在每个进程中都有独立的副本,共享对象中的全局变量实际上和定义在程序内部的全局变量没什么区别,任何一个进程。只能访问自己的那个副本。而不会影响其他的进程。

 

15>gcc -shared xxx.c -o xxx.so这个命令会产生一个不使用地址无关代码,而使用装载时重定位共享对象,但是由于不是地址无关,所以不能被多个进程所共享