问题
I am trying to wrap the GLIBC fstat
function (it could be any other: it is just a proof of concept) by injecting my library to an executable. I do this by placing my library where the executable's RPATH
is pointing with the name libc.so.6
.
The source code of my library is the one below:
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>
int fstat(int fd, struct stat *buf){
typeof(fstat) *old_fstat;
// Try with a printf...
printf("HOOT! fstat wrapped!");
old_fstat = dlsym(RTLD_NEXT, "fstat");
return (*old_fstat)(fd, buf);
}
I compile it with --version-script
(to add symbol versioning) and statically link it to libgcc.
gcc -Wall -fPIC -c -o wrapperlib.o wrapperlib.c
gcc -shared -static-libgcc -fPIC -Wl,-soname -Wl,libc.so.6 -Wl,--version-script=wrapperlib.map,-Bstatic -o libc.so.6 wrapperlib.o
With wrapperlib.map
containing:
GLIBC_2.0 {
};
When I execute the target program my library gets loaded but I get the following error:
./target: relocation error: ./target: symbol __libc_start_main, version GLIBC_2.0 not defined in file libc.so.6 with link time reference
If I provide my own implementation of __libc_start_main
I don't get this error (but it crashes, of course).
int __libc_start_main(int (*main) (int, char **, char **), int argc, char *argv, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void *stack_end) {
system("echo I am in __libc_start_main");
printf("printf: I am in __libc_start_main");
fflush(stdin);
return 0;
}
Why is there a relocation error on __libc_start_main
and not on system
?
(By the way, the call to the system
does work but the call to printf
produces no output. Am I missing something obvious here?)
Thank you
Edit:
Running target with LD_DEBUG=all
outputs this:
http://pastebin.com/iVVbwf6n
回答1:
I [place] my library where the executable's
RPATH
is pointing with the namelibc.so.6
.
And therefore the process loads your library instead of GLIBC's libc.so.6
. That is surely not what you want unless you're providing an independent implementation of at least the entire C standard library. That requires your library to provide an independent implementation of everything in libc.so.6
, or else to dynamically load the real libc
. I see that you attempt to attain completeness by statically linking libgcc (I guess you mean using -lstatic-libgcc
), but
that's the wrong library. It provides functions to support GCC-compiled binaries, which may include wrappers or alternatives for some C-library functions, but it does not provide the C library itself.
even if you linked the C library statically (e.g.
-lc_nonshared
), the library you get that way will not include a dynamically loadable symbol by which you can access the wrapped function. That's a direct consequence of the static linking.your library is anyway not independent because it tries to wrap GLIBC's implementation of
fstat()
, which is unavailable to it.
Why is there a relocation error on
__libc_start_main
and not onsystem
?
There is a relocation error on __libc_start_main
because that function is provided by the glibc's libc.so.6, but not by yours, nor by your binary itself or any other library dynamically linked to your binary. (See (1) above)
If there is no relocation error for the system
or printf
functions, then it follows that either those are not external dynamic symbols in your binary, or they are satisfied by some other library dynamically linked to your binary. (Update: the linker debug information shows the former to be the case: those are not external symbols, by which I meant symbols for which no definition is provided; they are provided by your library, presumably as a result of linking in libgcc.) The details don't really matter, as the point is that your strategy is totally unworkable. Consider using LD_PRELOAD instead.
Update: an alternative might be to give your shared library a constructor function that dlopen()
s the real libc.so.6
with flag RTLD_GLOBAL
enabled. This way, your library does not have to provide a complete C library itself, but it does need to know how to find the real library. That will certainly solve the problem of the wrapped function being unavailable in the wrapper.
来源:https://stackoverflow.com/questions/41145062/wrapping-a-glibc-function-using-the-dynamic-linker