据我所知,由于共享库不知道动态加载器将在何处放置它们,因此它们必须依赖GOT来解析对全局数据的所有引用。例如,一个共享库有一个名为globe
的全局变量,访问这个变量的可能方法就像这个mov eax,DWORD PTR [ecx-0x10]
,假设ecx
包含GOT的地址,globe
的偏移量是0x10
。现在,假设进程A使用此共享库,紧接着是进程B.我知道共享库的代码可以在进程之间共享,但数据不能,因为每个进程都可能根据其执行情况更改数据。因此,每个进程都将获得它自己的GOT,这意味着,由于虚拟内存,地址ecx + 0x10
将指向完全两个不同的GOT,具体取决于运行该段代码的进程。但随后说其中一个进程在其GOT中的偏移量0x10
上加载了第二个共享库,其中包含一个不同的全局数据成员。如果两个库都在同一个虚拟地址,那么使用这两个库的进程究竟能够访问每个库的全局数据吗?
但随后说其中一个进程在其GOT中的偏移量0x10处加载第二个共享库,其中包含不同的全局数据成员。如果两个库都在同一个虚拟地址,那么使用这两个库的进程究竟能够访问每个库的全局数据吗?
答案有三个部分:
理解这一点的最好方法是编译两个普通的库和一个主二进制文件,然后检查各种GOT
部分,观察它们何时发生变化以及以何种方式变化。
您混淆的根源似乎是假设只有一个GOT
。事实并非如此:每个库都有自己的.got
部分,编译器和运行时加载器将安排它,以便ecx
指向正确的.got
。
对于主可执行文件,答案是“复制重定位”。
这是关于这个主题的good article。