首页 > 解决方案 > 在运行时有条件地修改重定位

问题描述

TL;博士

我想覆盖 .got, .got.plt,...以指向正确的地址,因为链接器做出错误的决定。


我需要在代码中使用两个不同的动态分配函数(即malloc(),...)。在程序执行过程中,将根据某些条件选择合适的。因此,我提供了两个glibc实例并使用了这个LD_PRELOAD技巧。该LD_PRELOAD值类似于以下内容:

LD_PRELOAD=multiplexer_library.so:glibc1.so:glibc2.so

其中,multiplexer_library.so选择正确的库。glibc1.so使用 访问dlsym(RTLD_NEXT, "malloc")并且glibc2.so使用dlopen()后跟访问dlsym()。这同样适用于calloc(),...

问题是第二个 malloc 会干扰第一个。发生这种情况是因为后者的所有动态重定位都将由链接器映射前者。例如,当调用全局函数指针时,它将被映射到及其目标,即. 这个全局变量的重定位入口如下:glibc2.somorecoremorecore__default_morecore()glibc1.soglibc2.so

0000003addc0  085600000006 R_X86_64_GLOB_DAT 00000000003af4d8 __morecore@@GLIBC_2.2.5 + 0

我在Pin. 在动态分配期间,在我的代码中访问1370多个重定位条目中的125个。例如,一个重要的条目是确定动态分配边界的全局变量(请注意,我在系统调用级别为每个库提供了一个隔离的brk 区域)。这显然会破坏分配,因为两个分配器使用相同的. in的重定位条目如下所示:__curbrkbrk__curbrk__curbrkglibc1.so

0000003adeb8  044400000006 R_X86_64_GLOB_DAT 00000000003b10b8 __curbrk@@GLIBC_2.2.5 + 0

我试图重命名这些冲突的名称,但125是一个巨大的数字,而且代码很难掌握。因为它充满了嵌套的宏,这使得手动重命名解决方案实际上是不可行的。

IIUC,对于每个重定位条目,都存在一个内存地址(例如,在 中的某处.got,...),链接器将在其中放置目标重定位地址,并且该地址是每个共享库独有的。我将该地址称为目标持有人。例如,在这种情况下,链接器将变量的运行时地址放置在目标持有者中。如果这是正确的,在运行,我将不得不更新__curbrk__curbrkglibc1.so__curbrk glibc1.soglibc2.so__curbrkin的目标持有者glibc2.so保存变量的运行时地址。为了彻底解决问题,应该对. _ _ 可能吗?__curbrkglibc2.somalloc(),...

任何帮助表示赞赏!

标签: linkerelfglibcld-preloadrelocation

解决方案


因此,我提供了两个 glibc 实例并使用了 LD_PRELOAD 技巧。

这些 答案解释了为什么 usingLD_PRELOAD=glibc.so不能工作(至少不可靠)。

我决定使用两个单独的 glibc 库并将它们中的每一个用于一个专用区域。该区域在每个库中都是隔离的。

这不可能,因为 GLIBC 的设计者不支持这种方法。你需要做点别的


推荐阅读