views:

39

answers:

2

I am using GNU ld's "-wrap" option to intercept calls in applications, but have ran into a scenario where the code implementing the wrapper indirectly calls the wrapped function, creating a circular reference.

Example

The goal is to wrap read calls that occur in Program Foo. This code can be recompiled/relinked, but not modified.

Program Foo

main() {
    ...
    read(fd, buf, size);
    ...
}

The wrapper here will intercept calls to libc's read in Program Foo when using "-wrap read".

Wrapper

extern int __real_read(...);
int __wrap_read(...) {
    bar();
    __real_read(...);
}

However, Library Bar, called from the wrapper needs to use libc's read() function without going through the wrapper (thus causing the circular dependency).

Library Bar

void bar(void) {
    read(fd, buf, size)
}

Changing all wrapped routines in Library Bar to use __real_read() is not an option because the level of indirections that exist inside additional calls to external libraries in Library Bar are arbitrary.

Avoiding Flags

One way to solve this is to use per-thread flags to prevent wrapped reads originating from Library Bar reentering the library. Although I would prefer to not use this solution, I'm also open to suggestions on how to implement this with minimal code change in the wrapper and bar libraries.

Ideal Solution

??? That is why I'm asking the question :)

Thanks... -n

+1  A: 

As Nathon said, it should be possible to wrap fhe read() calls only for specific object files. Not sure about linux, but in windows wrapping an imported function in a DLL will not affect that imported function in other modules, so putting Bar in separate DLL with unwrapped read() would solve the problem.

ruslik
Your solution is equivalent to manually renaming all read() calls to __real_read() in the files that compose the object file which should not be subject to wrapping. And as I pointed out, this is not sufficient because of calls to read() that occurs through unknown levels of indirection.I am certainly not claiming your idea won't work, but I'm not sure it covers all the bases.
Noah Watkins
A: 

The basics of solving this problem are detailed at:

http://okmij.org/ftp/syscall-interpose.html

However, depending on the exact situation things will differ. Anyone interested can request from me to put up more information from a more complex case that I've constructed based on the ideas presented at the above URL.

Noah Watkins