8

I'm currently working on a project where I need to track the usage of several system calls and low-level functions like mmap, brk, sbrk. So far, I've been doing this using function interposition: I write a wrapper function with the same name as the function I'm replacing (mmap for example), and I load it in a program by setting the LD_PRELOAD environment variable. I call the real function through a pointer that I load with dlsym.

Unfortunately, one of the functions I want to wrap, sbrk, is used internally by dlsym, so the program crashes when I try to load the symbol. sbrk is not a system call in Linux, so I can't simply use syscall to call it indirectly.

So my question is, how can I call a library function from a wrapper function of the same name without using dlsym? Is there any compiler trick (using gcc) that lets me refer to the original function?

4

4 回答 4

15

see ld's option --wrap symbol. From the man page:

--wrap symbol Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to "__wrap_symbol". Any undefined reference to "__real_symbol" will be resolved to symbol.

This can be used to provide a wrapper for a system function. The wrapper function should be called "__wrap_symbol". If it wishes to call the system function, it should call "__real_symbol".

Here is a trivial example:

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

If you link other code with this file using --wrap malloc, then all calls to "malloc" will call the function "__wrap_malloc" instead. The call to "__real_malloc" in
"__wrap_malloc" will call the real "malloc" function.

You may wish to provide a "__real_malloc" function as well, so that links without the --wrap option will succeed. If you do this, you should not put the definition of "__real_malloc" in the same file as "__wrap_malloc"; if you do, the assembler may resolve the call before the linker has a chance to wrap it to "malloc".

The other option is to possibly look at the source for ltrace, it is more or less does the same thing :-P.

Here's an idea though. You could have your LD_PRELOAD'ed library change the PLT entries to point to your code. This you technically the sbrk() function is still callable from your code nativly.

于 2009-06-15T21:28:12.610 回答
2

您可以使用以下工具不显眼地检查函数调用:

  • 数据库
  • ltrace
  • 系统点击

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

主要区别在于:

  • gdb 是交互式的,但功能强大
  • ltrace 使用简单,但只能打印函数名
  • systemtap 不是交互式的,但它可以非常快且功能强大。
于 2009-06-15T21:36:31.327 回答
0

如果您使用 glibc 运行主机系统,那么 libc 有一些内部后端连接到我前一段时间使用的运行时动态链接器。如果我没记错的话,我认为它被称为“__libc_dlsym”。(要检查,“$ readelf -s /usr/lib/libc.a | grep dlsym”应该会有所帮助。)将其声明为具有与 dlsym 相同的参数和返回值的外部链接函数,并使用它来包装 dlsym 本身。

于 2009-08-14T03:34:44.507 回答
0

truss不能在您的系统上运行?它非常适合 Solaris 上的此类事情。

于 2011-06-21T19:32:23.483 回答