在没有dlsym的Linux中的函数插入

我目前正在开发一个项目,在这个项目中我需要跟踪几个系统调用和像mmapbrksbrk这样的低级函数的使用。 到目前为止,我一直在使用函数插入来做这件事:我写一个与我要replace的函数名称相同的包装函数(例如mmap ),并通过设置LD_PRELOAD环境variables将其加载到程序中。 我通过一个用dlsym加载的指针调用真正的函数。

不幸的是,我想包装的function之一, sbrk ,由dlsym内部使用,所以当我尝试加载符号时,程序崩溃。 sbrk不是Linux系统调用,所以我不能简单地使用syscall调用间接调用它。

所以我的问题是,如何不使用dlsym从同名的包装函数调用库函数? 有没有什么编译器技巧(使用gcc)让我参考原始函数?

请参阅ld的选项 – --wrap symbol 。 从手册页:

– wrap符号使用符号的包装函数。 任何未定义的符号引用将被解析为“ __wrap_symbol ”。 对“ __real_symbol ”的任何未定义的引用将被解析为符号。

这可以用来为系统功能提供包装。 包装函数应该被称为“ __wrap_symbol ”。 如果它希望调用系统函数,它应该调用“ __real_symbol ”。

这是一个微不足道的例子:

 void * __wrap_malloc (size_t c) { printf ("malloc called with %zu\n", c); return __real_malloc (c); } 

如果使用–wrap malloc链接其他代码,则所有对“ malloc ”的调用将调用函数“ __wrap_malloc ”。 调用“__real_malloc”中的
__wrap_malloc ”将调用真正的“ malloc ”函数。

你也可以提供一个“ __real_malloc ”函数,这样没有–wrap选项的链接将会成功。 如果你这样做,你不应该把“ __real_malloc ”的定义放在与“ __real_malloc ”相同的文件中; 如果这样做,汇编程序可能会在链接器有机会将其包装到“malloc”之前解析调用。

另一个选择是可能查看ltrace的源代码,或多或少做同样的事情:-P。

这是一个想法。 你可以让你的LD_PRELOAD库改变PLT条目来指向你的代码。 这在技术上, sbrk()函数仍然可以从您的代码本身调用。

您可以使用以下工具轻松地检查函数调用:

  • GDB
  • ltrace
  • SystemTap的

这些工具允许监视器程序在调用函数时通知您,并允许您询问参数。

主要区别是:

  • gdb是交互式的,但功能强大
  • ltrace使用简单,但只能打印函数名称
  • systemtap不是互动的,但它可以非常快速,而且功能强大。

如果您正在运行一个包含glibc的主机系统,那么libc的某些内部后端就是我之前使用的运行时动态链接程序。 如果我记得正确,我认为它被称为“__libc_dlsym”。 (要检查,“$ readelf -s /usr/lib/libc.a | grep dlsym”应该有帮助。)将它声明为外部链接的函数,它具有与dlsym相同的参数和返回值,并用它来包装dlsym本身。

truss不能在你的系统上工作吗? 它在Solaris上适用于这种类型的东西。