获取函数指针在共享库中运行我没有直接加载

时间:2011-01-04 23:54:41

标签: linux shared-libraries function-pointers dlopen

我的Linux应用程序(A)链接到我没有源代码的第三方共享库(B)。该库使用了另一个我没有(C)源代码的第三方共享库。我相信(B)使用dlopen访问(C)而不是直接链接。我的理由是(B)上的'ldd'没有显示(C),objdump -X(B)显示对dlopen / dlclose / dlsym的引用。

我的要求是我需要在我的代码中为(A)获取一个函数指针,该函数指向位于(C)中的函数foo()。通常我会使用dlsym,但是我需要传递它从dlopen返回的句柄,这是我没有的,因为(B)没有公开它。

-

对于更大的上下文:我需要修改(C)中的函数,以便每次调用其辅助函数bar()(也位于(C)中)时,它还调用具有相同签名的函数( A)具有相同的参数(基本上将我的代码注入到(C)foo()的代码路径中 - > bar()。我相信我已经找到了使用gdb实现此目的的方法,但是为了移植我的gdb命令列表,但我仍然坚持获取函数指针的步骤。我也愿意接受完成相同任务的替代方案,而不是如上所述的确切问题

编辑:写完之后我意识到我可能只是在我的代码中对文件执行另一个dlopen,并且通过该句柄上的dlsym返回的符号应该与通过原始dlopen接收的符号相同,如果我正在正确阅读dlopen手册页。然而,我仍然对我的大背景下的建议或帮助感兴趣,如果有更好的方法来解决这个问题

2 个答案:

答案 0 :(得分:2)

如果您知道函数foobar的原型,则可以在应用环境中使用LD_PRELOAD(由您创建的库)并调用下一个可用函数(foo或完成所需任务后bar

/*
 * gcc -shared -fPIC my_lib.c -ldl -Wl,-init,init_lib -o lib_my_name.so
 *
 * LD_PRELOAD this library in the environment of the target executable
 *
 */

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

#ifndef RTLD_NEXT
#define RTLD_NEXT ((void *)-1)
#endif

int init_lib(void)
{
    return 0;
}

void *foo (params here...)
{
    /* your required task here */

    return ((void* (*)(size_t))(dlsym(RTLD_NEXT, "foo")))(params here);
}

(我假设您为了某些调试目的而这样做,因为您已经使用gdb来完成此操作,否则这不是修改客户端计算机上某些功能的好方法)

答案 1 :(得分:1)

您可以轻松掌握(C)的句柄;只是dlopen正确的文件。您已经知道要打开哪个文件(因为您需要符号“foo”),或者您在(A)上运行strace -e open,mmap,mmap2并查看它碰巧打开的共享库。

当创建(C)时,对“bar”的任何引用(例如来自“foo”中的jmp指令)通常在创建时已经部分解析,因为(C)本身具有“bar”。因此,对bar的调用不会通过PLT,换句话说,通过简单的hack覆盖bar是无效的,并且需要像gdb那样的asm级别的惩罚。

所有这些听起来过于紧张,以至于它引出了一个问题,即它是否值得工作,或者是否抛弃闭源组件可能会更好。