确定哪些共享库调用我的共享

时间:2010-10-14 16:03:27

标签: c shared-libraries

我试图找到一种方法来了解哪个共享lib正在调用我的共享lib函数。场景就是这样。

我使用LD_PRELOAD来覆盖malloc。在我的malloc中,我将调用直接转发到真正的malloc,但如果调用来自特定的共享库,我想在转发调用之前进行一些处理。

现在,我想要处理的malloc调用的共享库是由一种插件架构中的外部可执行文件加载和调用的。我可以通过检查全局program_invocation_short_name变量来判断哪个可执行文件叫做我的malloc,但是我不想处理来自提供插件体系结构的可执行文件的malloc调用,而只是处理来自插件共享库的那些。

我已经尝试过使用backtrace()和backtrace_symbols()来查看我是否可以从后面跟踪中获取插件库名称或部分内容,但是没有运气。我从来没有得到那个名字。

有人可以建议如何做到这一点吗?

此致

亚历。

编辑:我忘了提。这是在Linux上。我的坏,我原以为LD_PRELOAD就把它拿走了。

2 个答案:

答案 0 :(得分:1)

没有简单的方法可以做到这一点,但这种方法可能适合您的需求。

我编写了3个小应用程序,因此您可以按照我的指示操作。他们是:

  • app :将在您的系统上运行的二进制文件。调用libmiddleman.so中的函数,该函数尝试通过malloc()
  • 分配一些内存

源代码:gcc app.c -o app -L. -lmiddle_man

//File: app.c
#include "libmiddle_man.h"    
#include <stdio.h>

int main()
{
    do_something();

    return 0;
}
  • libmiddle_man.so :导出一个只调用malloc()的函数

源代码:gcc libmiddle_man.c -o libmiddle_man.so -shared

//File: libmiddle_man.c
void do_something()
{
    int* tmp = malloc(sizeof(int));
}

还有:

//File: libmiddle_man.h
void do_something();
  • libfake_malloc.so :实现并导出我们在终端上打印内容的malloc()版本

源代码:gcc lbfake_malloc.c -o libfake_malloc.so -shared

//File: libfake_malloc.c
#include <stdio.h>
#include <unistd.h>

void* malloc(size_t size)
{
    printf("fake malloc()\n");

    printf("Process ID: %d\n", getpid());

    while(1)
    {
    }

    return NULL;
}

当您使用LD_PRELOAD=libfake_malloc.so ./app执行应用程序时,它将输出以下内容:

fake malloc()
Process ID: 14230    (the PID will be different each time you run the application)

并且应用程序将挂起,因为我们需要它。我们将检查进程内存映射,并确保 app 都加载了我们的两个库。

所以暂时把它留在那里然后打开另一个终端。当您在进程列表中搜索此PID时,它将显示哪个应用程序正在使用libfake_malloc.so。这不是我们的目标,但这是一个有趣的信息。

ps -aux | grep 14230

输出:

karl     14230 97.3  0.0   1648   396 pts/9    R+   13:57  10:20 ./app

请记住将应用程序返回给您的任何数字更改为14230。接下来,我们将检查进程内存并验证是否已加载两个库。

cat /proc/14230/maps

显示:

00110000-00263000 r-xp 00000000 08:06 2158492    /lib/tls/i686/cmov/libc-2.11.1.so
00263000-00264000 ---p 00153000 08:06 2158492    /lib/tls/i686/cmov/libc-2.11.1.so
00264000-00266000 r--p 00153000 08:06 2158492    /lib/tls/i686/cmov/libc-2.11.1.so
00266000-00267000 rw-p 00155000 08:06 2158492    /lib/tls/i686/cmov/libc-2.11.1.so
00267000-0026a000 rw-p 00000000 00:00 0 
00584000-00585000 r-xp 00000000 08:07 2921104    /home/karl/workspace/shared_libs/who_called_my_shared/libmiddle_man.so
00585000-00586000 r--p 00000000 08:07 2921104    /home/karl/workspace/shared_libs/who_called_my_shared/libmiddle_man.so
00586000-00587000 rw-p 00001000 08:07 2921104    /home/karl/workspace/shared_libs/who_called_my_shared/libmiddle_man.so
00605000-00606000 r-xp 00000000 08:07 2921103    /home/karl/workspace/shared_libs/who_called_my_shared/libfake_malloc.so
00606000-00607000 r--p 00000000 08:07 2921103    /home/karl/workspace/shared_libs/who_called_my_shared/libfake_malloc.so
00607000-00608000 rw-p 00001000 08:07 2921103    /home/karl/workspace/shared_libs/who_called_my_shared/libfake_malloc.so
007e6000-007e7000 r-xp 00000000 00:00 0          [vdso]
0096a000-00985000 r-xp 00000000 08:06 2142529    /lib/ld-2.11.1.so
00985000-00986000 r--p 0001a000 08:06 2142529    /lib/ld-2.11.1.so
00986000-00987000 rw-p 0001b000 08:06 2142529    /lib/ld-2.11.1.so
08048000-08049000 r-xp 00000000 08:07 2921106    /home/karl/workspace/shared_libs/who_called_my_shared/app
08049000-0804a000 r--p 00000000 08:07 2921106    /home/karl/workspace/shared_libs/who_called_my_shared/app
0804a000-0804b000 rw-p 00001000 08:07 2921106    /home/karl/workspace/shared_libs/who_called_my_shared/app
b77b0000-b77b2000 rw-p 00000000 00:00 0 
b77c9000-b77cc000 rw-p 00000000 00:00 0 
bfb69000-bfb7e000 rw-p 00000000 00:00 0          [stack]

您会注意到libfake_malloc.so的inode是 2921103 ,加载它的库的inode(即libmiddle_man.so)实际上是2921103 + 1, 2921104 < /强>

我有机会在一些机器和一些运行Linux的嵌入式设备上进行测试。总而言之,通过解析 / proc / pid / maps 上可用的信息,似乎可以发现哪个库加载了你的。

答案 1 :(得分:0)

在Windows上,您可以使用CreateToolhelp32Snapshot()Module32First()等特殊API来获取进程中加载​​的所有共享库的列表。

每个此类库都将驻留在由modBaseAddr结构的modBaseSizeMODULEENTRY32成员指定的内存范围内。

通过检查调用者的返回地址(可以通过一些简单的内联汇编来完成),您可以将其与范围进行比较,这样可以准确识别调用者。