2010-10-14 76 views
2

我试图找到一种方法来知道哪个共享库正在调用我的共享lib函数。情景就是这样。确定哪些共享lib调用到我的共享中

我已经使用LD_PRELOAD来覆盖malloc。在我的malloc里面,我直接将调用转发给真正的malloc,但是如果调用来自特定的共享库,我希望在转发该调用之前进行一些处理。

现在,我想要处理的malloc调用的共享库在一种插件体系结构中被外部可执行文件加载和调用。我可以通过检查全局程序_invocation_short_name变量来告诉哪个可执行文件称为我的malloc,但我不想处理来自提供插件体系结构的可执行文件的malloc调用,但仅处理来自插件共享库的可执行文件。

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

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

Regards,

Alex。

编辑:我忘了提。这是在Linux上。我的糟糕之处在于,我认为LD_PRELOAD会将其告知。

+0

+1有趣。 – karlphillip 2010-10-14 16:24:34

+0

在什么平台上? – ruslik 2010-10-14 16:25:06

回答

0

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

每个这样的库将驻留在结构MODULEENTRY32modBaseAddrmodBaseSizemodBaseSize成员指定的存储器范围内。

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

+0

我正在寻找使用相同的方法,但在Linux上,但目前为止找不到同样的系统调用运气。有任何想法吗? – Alex 2010-10-18 05:55:41

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。所以:出口,简单地调用一个函数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) 

和应用程序,因为我们需要它,这样会挂在那里。我们将检查进程内存映射,并确保应用程序都加载了我们的两个库。

因此,现在就离开它并打开另一个终端。当您在进程列表中搜索此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号的任何应用程序返回到您。接下来,我们将检查进程内存并验证是否加载了两个out库。

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 ,并加载它的库(即libmiddle_man.so)的索引节点实际上是2921103 + 1 ,这是。

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