4

我正在编写一个库,它通过运行程序来拦截对malloc和在运行时的调用。freeLD_PRELOAD=mylib myexe

malloc对和的调用可以free很好地拦截。我的问题是 mylib 中还有另一个函数,我也想在LD_PRELOAD使用时拦截它,我无法弄清楚为什么它不像调用mallocand那样“正常工作” free

在 mylib.c 中:

void* malloc(size_t s)
{
    return doMyMalloc();
}

void free(void* p)
{
    doMyFree(p);
}

void otherThing(size_t)
{
    doThing();
}

在 myexe.cpp 中:

#include <malloc.h>

extern "C" void otherThing(size_t);  // Compile with -Wl,--unresolved-symbols=ignore-all

int main(int argc, char* argv[])
{
    void* x = malloc(1000);   // Successfully intercepted.
    free(x);  // Successfully intercepted.
    otherThing(1);  // Segfault.
}

我设法让它工作的一种方法是:

typedef void (*FUNC)(size_t);
FUNC otherThing = NULL;

int main(int argc, char* argv[])
{
    otherThing = (FUNC)dlsym(RTLD_NEXT, "otherThing");
    otherThing(1);  // Successfully calls mylib's otherThing().
}

但我不想写所有这些代码;我不必为mallocand这样做freeLD_PRELOAD如果缺少前缀,程序崩溃也没关系。

4

2 回答 2

0

这有点棘手。互联网上有几篇与此相关的帖子,但我会尝试将其分解为“让它发挥作用”。

如果这是在 Linux 下,那么发生的情况是应用程序已被编译为无法使用外部符号。最快的解决方案是向主应用程序添加与库中使用的相同的编译标志,即将标志添加到主应用程序-fPIC的编译中,就像对库所做的那样。

而不是使用-Wl,--unresolved-symbols=ignore-all标志,您应该使用__attribute__ ((weak))for 函数,例如:

extern "C" void otherThing(size_t) __attribute__ ((weak);

并在运行时检查它是否为 NULL,这将允许您确定它是否已设置。

通过以与 a 相同的方式编译主应用程序,您可以通过手册页.so隐式地将其本身用作 as 的目标:LD_PRELOAD

LD_PRELOAD

要在所有其他共享库之前加载的附加的、用户指定的 ELF 共享库的列表。列表中的项目可以用空格或冒号分隔。这可用于选择性地覆盖其他共享库中的函数

于 2013-04-21T09:34:45.703 回答
0

我觉得您正在应用一个解决方案 ( LD_PRELOAD) 来解决两个不同的问题。首先,您要修补malloc()free(). 你已经得到了那个工作 - 太棒了。接下来,您希望拥有一个运行时“插件”系统,在该系统中,您在构建时不链接任何库,而仅在运行时链接。这通常使用dlopen()and来完成dlsym(),我建议您使用它们。

这个想法是你不想otherThing()在构建时指定一个特定的实现,但你确实需要在运行时有一些实现(或者你理所当然地期望崩溃)。所以让我们明确一下,并dlsym()在运行时使用它来解析函数名称,当然还有错误检测,以防找不到它。

至于在哪里定义otherThing(),它可以在一个完全独立的文件中dlopen(),或者在mylib(在这种情况下将 NULL 作为文件名传递给dlopen())。

于 2013-04-21T06:03:26.007 回答