我正在编写一个lib,它通过运行malloc
的程序来拦截在运行时对free
和LD_PRELOAD=mylib myexe
的调用。
对malloc
和free
的调用是正确的。我的问题是,在使用LD_PRELOAD
时我还想要拦截mylib中的另一个函数,我无法弄清楚为什么它不像调用malloc
和{{1}那样“正常工作” }。
在mylib.c中:
free
在myexe.cpp中:
void* malloc(size_t s)
{
return doMyMalloc();
}
void free(void* p)
{
doMyFree(p);
}
void otherThing(size_t)
{
doThing();
}
我设法让它发挥作用的一种方法是:
#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
前缀丢失的情况下崩溃,则可以。
答案 0 :(得分:0)
我觉得你正在应用一个解决方案(LD_PRELOAD
)来解决两个不同的问题。首先,您要修补malloc()
和free()
。你有这个工作 - 很棒。接下来,您希望拥有一个运行时“插件”系统,在该系统中,您不会在构建时链接任何库,而只能在运行时进行链接。这通常使用dlopen()
和dlsym()
完成,我建议您使用这些。
这个想法是你不想在构建时指定otherThing()
的特定实现,但是你需要在运行时有一些实现(或者你正确地期望崩溃)。因此,让我们明确一点,并使用dlsym()
在运行时解析函数名称,当然还有错误检测,以防它找不到。
至于定义otherThing()
的位置,它可以位于dlopen()
或mylib
中的完全独立的文件中(在这种情况下,将NULL作为文件名传递给{{1} }})。
答案 1 :(得分:0)
这有点儿了。在互联网上有几个与此相关的帖子,但我会尝试将其分解为“让它工作”。
如果这是在Linux下,那么发生的事情是该应用程序已被编译为无法使用外部符号。最快的解决方案是向主应用程序添加与库中使用的相同的编译标志,即将-fPIC
标志添加到主应用程序的编译中,就像为库完成一样。
您应该使用-Wl,--unresolved-symbols=ignore-all
作为函数,而不是使用__attribute__ ((weak))
标志,例如:
extern "C" void otherThing(size_t) __attribute__ ((weak);
在运行时检查它是否为NULL,这将允许您确定它是否已设置。
通过以与.so
相同的方式编译主应用程序,您隐含地允许将其自身用作LD_PRELOAD
的目标,如手册页所示:
<强> LD_PRELOAD 强>
要包含的其他用户指定的ELF共享库的列表 在所有其他人之前加载列表中的项目可以分隔 空格或冒号。这可以用于有选择地覆盖 其他共享库中的函数。