【问题标题】:How can each process have it's own copy of global data in a shared library每个进程如何在共享库中拥有自己的全局数据副本
【发布时间】:2019-07-17 03:20:23
【问题描述】:

我了解由于共享库不知道动态加载器会将它们放置在哪里,它们必须依靠 GOT 来解析对全局数据的所有引用。例如,一个共享库有一个名为globe的全局变量,访问该变量的可能方式是mov eax,DWORD PTR [ecx-0x10],假设ecx包含GOT的地址,globe的偏移量为0x10。现在,假设进程 A 使用此共享库,紧随其后的是进程 B。我知道共享库的代码可以在进程之间共享,但数据不能,因为每个进程都可能根据其执行情况更改数据。因此,每个进程都将获得自己的 GOT,这意味着,由于有了虚拟内存,地址ecx + 0x10 将指向完全不同的两个 GOT,具体取决于运行该代码的进程。但是然后说其中一个进程在其 GOT 中的偏移量 0x10 处加载了具有不同全局数据成员的第二个共享库。如果两个库都在同一个虚拟地址,那么使用这两个库的进程如何访问每个库的全局数据?

【问题讨论】:

  • 动态加载和共享对象是相当复杂的野兽。你只需要相信正确的事情会发生[tm]。如何?除非有人的目的是编写自己的动态加载器,否则我看不出有人关心的理由。 C++ 指定了事物的工作方式。只要代码满足所有要求并且不引入未定义的行为,共享库之类的东西就会像宣传的那样工作,而无需任何人担心 CPU 寄存器如何映射。您根本没有提到的另一件事是虚拟内存和 MMU,它在其中发挥了重要作用。
  • 如果我想让别人告诉我要有信心,我会等到周日礼拜。
  • 我认为你得到的答案可能是“写时复制”。见this answer

标签: linux shared-libraries dynamic-linking got


【解决方案1】:

然后说其中一个进程在其 GOT 中的偏移量 0x10 处加载了具有不同全局数据成员的第二个共享库。如果两个库都在同一个虚拟地址,那么使用这两个库的进程如何访问每个库的全局数据?

答案分为三部分:

  1. 每个库如何访问自己的全局变量?
  2. 每个库如何访问其他库的全局变量?
  3. 主可执行文件如何访问任一库中的全局变量?

理解这一点的最佳方法是编译两个普通库和一个主二进制文件,然后检查各个 GOT 部分并观察它们何时以及以何种方式发生变化。

您的困惑的根源似乎是假设只有一个GOT。情况并非如此:每个库都有自己的.got 部分,编译器和运行时加载程序将安排它,使ecx 指向右侧.got

对于主可执行文件,答案是“复制重定位”。

这是一个关于这个主题的good article

【讨论】:

  • 嗯,我认为主可执行文件也使用了 PIC 而不是加载时间重定位? (我的意思是它必须使用加载时间重定位来将全局变量的地址放在 GOT 中,仅此而已)
猜你喜欢
  • 2019-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-06
相关资源
最近更新 更多