[英]Linking functions with LD_PRELOAD at runtime
我写拦截到的调用一个lib malloc
和free
与正在运行的程序在运行时LD_PRELOAD=mylib myexe
。
对malloc
和free
的调用是很好的拦截。 我的问题是,在使用LD_PRELOAD
时我还想要拦截mylib中的另一个函数,我无法弄清楚它为什么不像调用malloc
和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().
}
但我不想写所有这些代码; 我没有必要为malloc
和free
做这件事。 如果程序在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.