如何从动态库中检测主要可执行文件的函数定义 - 尤其是malloc

时间:2018-03-08 19:23:27

标签: c linux gcc

因此libgcc将使用应用程序的malloc和free,如果已经定义了一个,则为了满足应用程序在某些库调用之后调用free()的需要,例如realpath。

在我的动态库中,我真的不想使用该应用程序malloc / free,因为我不太信任它 - 我很高兴使用libgcc的实现malloc,这是大多数应用程序使用的,所以我声明了我自己的malloc()函数,它通过dlsym()调用libgcc的实现。

一切进展顺利直到......我想打电话给realpath(也许还有其他人)!作为一个简单的修复,我需要一种方法来执行相当于dlsym()但是在主可执行文件(我不拥有)上,以获得应用程序的免费实现(如果有的话)。这样的事情存在吗?

我知道这一定是必须的,因为动态链接器"做了正确的事情",但仅仅是致命的程序员可以访问,以及如何?

在realpath的特定情况下,我知道我可以提供一个缓冲区,但它有自己未知的缓冲区大小危险。对于其他一些电话,我无法做到。

我也可以使用objcopy进行符号重命名的蜿蜒路径,但如果可能,我不愿意。

[laters]
我确实认为malloc可能是由另一个动态库定义的,我希望使用该版本,而应用程序仍然使用其编译版本(我已经看到它确实继续使用它,即使tcmalloc是预加载的,例如。

我想这扩展了问题,询问是否有任何库定义了malloc,如果应用程序已经定义了malloc,我想挑选我在代码中的每个地方使用哪个版本的malloc / free来匹配行为libgcc在必要时,而不是在没有时,所以我希望能够获得对它们的引用。

在短期内,我已经解决了我当前的问题,在调用libgcc实现之前,使用我的malloc替换预定义缓冲区的版本的代码中的realpath(),但我觉得这是一个很大的乐队 - 助手。

1 个答案:

答案 0 :(得分:1)

插入malloc可以来自任何地方,而不仅仅是可执行文件。它可以是另一个对象的动态部分中的DT_NEEDED条目引用的共享对象,也可以是使用LD_PRELOAD注入到过程映像中的库。

通常,许多库都具有分配某些东西的功能,然后必须使用free解除分配。移植到Windows的软件不会这样做(因为DLL在那里有单独的堆),但除此之外,它并不罕见。不仅realpath,还有strdupasprintf,可能还有一些我不记得的其他功能。

在您的情况下,您应该在这样的指针上调用free,并为您自己的内存释放函数使用不同的名称。一旦malloc被插入,就无法安全地使用原始的libc分配器,因为它尚未正确初始化。例如,如果在使用不同的插入malloc的进程中调用glibc malloc函数,则malloc将不是线程安全的:初始化不是线程安全的,因为实现知道pthread_create在创建第一个新线程之前将调用malloc,从而在进程是单线程时初始化malloc。这就是初始化代码中没有同步的原因。

(顺便说一句,libgcc不提供malloc。它来自libc / glibc。)