问题
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?
回答1:
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.
回答2:
You can examine function invocation unobtrusively using tools such as:
- gdb
- ltrace
- systemtap
These tools allow a monitor program to inform you when a function is called, and allow you to interrogate the arguments.
The main differences are:
- gdb is interactive, but powerful
- ltrace simple to use, but you can only print the function name
- systemtap is not interactive, but it can be very fast, and is powerful.
回答3:
If you are running a host system with glibc, the libc has some internal back end to the runtime dynamic linker that I used some time ago. If I recall correctly, I think it's called '__libc_dlsym'. (To check, "$ readelf -s /usr/lib/libc.a | grep dlsym" should help.) Declare it as an externally linked function with the same arguments and return value that dlsym has and use it to wrap dlsym itself.
回答4:
Does truss
not work on your system? It works perfectly for this kind of things here on Solaris.
来源:https://stackoverflow.com/questions/998464/function-interposition-in-linux-without-dlsym