tags:

views:

98

answers:

3

I need to write a little library, to be loaded by setting LD_PRELOAD, and which will override some functions in the standard C library but also call those functions in the standard library. Specifically, I want my shiny new library to let users provide their own resolv.conf so they can, eg, specify their default domain, or set aliases in it for long hostnames. I'm going to need a good understanding of how the linker works if I'm to do this, so can anyone point me at some good documentation, that doesn't assume that I know it all already and just need a reference, but also doesn't assume that I'm a complete idiot?

+1  A: 

It sounds like your interested in dynamic loading rather than linking in general. That's how ODBC finds and uses a particular driver at run time, like what you want to do with your resolver.

Rather than google you up a random link, I'll give you some keywords on dynamic linking:

Concepts: "dynamic loading" "Position Independent Code" soname

Tools: LD_DEBUG ldconfig ldd nm objdump

The C API for dynamic loading: dlfcn.h dlopen dlsym dlerror dlclose

I did find one good tutorial, which I remember being helpful when I was working with ODBC: http://www.ibm.com/developerworks/library/l-shobj/

However, it recommends calling ld directly, which is a no-no with gcc. Instead use the -shared option:

g++ -shared -fPIC foo.c -o libfoo.so.1.0 -Wl,soname,libfoo.so.1

Also: You should look for solutions that do not involve LD_PRELOAD or LD_LIBRARY_PATH, which are basically debug tools, and libraries that require them in production are flawed: Why LD_LIBRARY_PATH is bad LD_LIBRARY_PATH Is Not The Answer LD_LIBRARY_PATH - just say no

ODBC avoids it with an odbc.ini config file where you specify the full path to the .so to use.

olooney
Doesn't this assume that I have some control over the innards of the applications in use, so that they can search for and dynamically load the library? While I *could* patch all the apps, and rebuild them, and keep them in my home directory, I'd rather not do that. Yeah, it's a nasty hack, but I think that using LD_PRELOAD to shim something in between, for example, Firefox and the resolver is the right tool in this case.
DrHyde
Nope. You can, and should, use ldconfig to define the .so search path in production systems. For one thing, it does caching. The paths in LD_PRELOAD must be searched at runtime... for EVERY dynamically linked library. Check out 'man ldconfig'; it's an enlightening look at how Linux is glued together.
olooney
ldconfig only looks useful when run by root, because otherwise it can't update the cache. And I'm not root in all the places I want to use this.
DrHyde
+2  A: 

If you are using the GNU linker, one thing you need to know about is RTLD_NEXT. This allows you to "find the next occurrence of a function in the search order after the current library".

This way, you can override a standard function and still be able to call the original version.

I used this function in a version of malloc that tracks allocation stats. I needed to override malloc to collect the stats but I still wanted the original version of malloc to do the allocation:

static void *(*next_malloc)(size_t) = NULL;

__attribute__ ((constructor))
static void
bootstrap() 
{
    next_malloc = dlsym(RTLD_NEXT, "malloc");
}

void *
malloc(size_t size)
{
    void *ptr = next_malloc(size);

    // collect some stats

    return ptr;
}
R Samuel Klatchko
That looks like exactly what I needed - thanks!
DrHyde
+1  A: 

Several good answers, but no one's mentioned the one resource that led me through this: Building library interposers for fun and profit.

pra