我目前正在开发一个项目,在这个项目中我需要跟踪几个系统调用和像mmap
, brk
, sbrk
这样的低级函数的使用。 到目前为止,我一直在使用函数插入来做这件事:我写一个与我要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()
函数仍然可以从您的代码本身调用。
您可以使用以下工具轻松地检查函数调用:
这些工具允许监视器程序在调用函数时通知您,并允许您询问参数。
主要区别是:
如果您正在运行一个包含glibc的主机系统,那么libc的某些内部后端就是我之前使用的运行时动态链接程序。 如果我记得正确,我认为它被称为“__libc_dlsym”。 (要检查,“$ readelf -s /usr/lib/libc.a | grep dlsym”应该有帮助。)将它声明为外部链接的函数,它具有与dlsym相同的参数和返回值,并用它来包装dlsym本身。
truss
不能在你的系统上工作吗? 它在Solaris上适用于这种类型的东西。