This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Force specified function to be linked to a specified lib whencompiling/linking
On Thu, Jul 20, 2017 at 02:26:22PM -0400, Carlos O'Donell wrote:
> On 07/20/2017 12:28 PM, Yubin Ruan wrote:
> > Hi,
> >
> > I am wondering whether it is possible to force the linker to use some
> > specified function to link to when compiling/linking.
> >
> > I am using the LD_PRELOAD environment variable to hook some specified
> > functions but I am not so familiar with linker so there are some
> > troubles. I am hooking the standard `open' system call to add some
> > functionalities, so that when users use the `open' system call, I can
> > collect some data. Basically I am doing something like this:
> >
> > int open(int fd, int flags, ...) { /* (1) */
> > ...
> > /* add some functionalities here */
> > ...
> >
> > return open(...); /* (2) return the original open function call */
> > }
> >
> > Obviously, this cannot work, as it would call into a infinite loop...
> > So I am wondering whether I can force the linker to link some function
> > to some specified dynamic library so that it would not cause infinite
> > loop. In the example above, it would be perfect for the `open()'
> > system call at (2) to be linked to the standard library, rather than
> > the one that I hook.
> >
> > As for now, because I set the LD_PRELOAD as:
> >
> > export LD_PRELOAD=/path/to/my_open.so
> >
> > whenever a program that have a `open()' function inside is loaded, the
> > dynamic linker would link that `open()' to my ``my_open.so''. And that
> > is the same for my ``open'': when the linker try to link the `open()'
> > at (2), it would also try to link that to my `open()' at (1),
> > resulting in a infinite loop.
> >
> > Any idea?
>
> (1) Use ld's --wrap=symbol.
>
> See the man page for details.
ld's --wrap=symbol is almost perfect, but it is also almost useless, because
it requires users of the .so file to be aware of the "wrapped" function and
pass in a --wrap=symbol when compiling. For example, imagine that we want to
"wrap" the standard malloc function like this:
void *
__wrap_malloc(size_t size)
{
printf("in __wrap_malloc");
return __real_malloc(size);
}
and creat a .so from it:
$ gcc -shared -fPIC my-wrap-malloc.c -o my-wrap-malloc -Wl,--wrap-malloc
and then user can create a program, say:
int main()
{
int *ptr = malloc(100);
if (ptr)
puts("malloc success");
return 0;
}
but, to use the "my-wrap-malloc.so" we created before, users also have to
pass in the --wrap=malloc when compiling:
$ gcc main.c -o main -Wl,--wrap=malloc
and that is not transparent. It require that users are aware of the customized
malloc function (because they have to pass in --wrap=malloc). It is as if to
tell users "hey, we created a customized malloc that is really fast, to use it,
just pass in a "--wrap=malloc" flag when compiling. But, if we have to notify
users, why don't we just create something like "fmalloc":
void * fmalloc(size_t size)
{
/* do something here */
return malloc(size);
}
and tell users to use the new `fmalloc', which is more clear.
What I want to do here is to have the internal standard malloc linked to the
right place, not the one we created:
void *
malloc(size_t size)
{
/* do something here */
return __real_malloc(size);
}
as you see, I want the `__real_malloc' to be linked to the standard malloc
implementation. And in this situation, user don't know any internal changes.
They just use it as usual.
> (2) Use libdl's dlopen().
>
> Use dlopen to get the real open() from libc.so.6, and then
> call that through the handle returned from dlsym().
This works for some libc functions such as "malloc", but it doesn't work for
`open()'. open() is a system call, and dlopen(), which is a libc function, use
open internally, so you still have infinite loop here.
--
Yubin