繁体   English   中英

在运行时将函数与LD_PRELOAD链接

[英]Linking functions with LD_PRELOAD at runtime

我写拦截到的调用一个lib mallocfree与正在运行的程序在运行时LD_PRELOAD=mylib myexe

mallocfree的调用是很好的拦截。 我的问题是,在使用LD_PRELOAD时我还想要拦截mylib中的另一个函数,我无法弄清楚它为什么不像调用mallocfree那样“正常工作”。

在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().
}

但我不想写所有这些代码; 我没有必要为mallocfree做这件事。 如果程序在LD_PRELOAD前缀丢失时崩溃,则可以。

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

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

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

这有点儿了。 在互联网上有几个与此相关的帖子,但我会尝试将其分解为“让它工作”。

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

而不是使用-Wl,--unresolved-symbols=ignore-all标志,你应该使用__attribute__ ((weak))来实现这个功能,例如:

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

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

通过以与.so相同的方式编译主应用程序,您隐式允许将其自身用作LD_PRELOAD的目标,如手册页所示:

LD_PRELOAD

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM