Click to See Complete Forum and Search --> : way to change initialization order of libraries


maccorin
06-01-2004, 06:43 PM
does anybody know a way to change the order that libraries are initialized, as in any function w/ the __attribute__((constructor)) is run.

My problems is this, i have a library with some initialization code that looks like


char*(*___libc_strcpy)(char *, const char *) = NULL;
char*(*___libc_strncpy)(char *, const char *, size_t) = NULL;
int(*___libc_strcmp)(const char *, const char *) = NULL;
size_t(*___libc_strlen)(const char *) = NULL;
char*(*___libc_strstr)(const char *, const char *) = NULL;

....

void __attribute__((constructor)) constructor ( )
{

....

___libc_strstr = dlsym(RTLD_NEXT, "strstr");
___libc_strcpy = dlsym(RTLD_NEXT, "strcpy");
___libc_strncpy = dlsym(RTLD_NEXT, "strncpy");
___libc_strcmp = dlsym(RTLD_NEXT, "strcmp");
___libc_strlen = dlsym(RTLD_NEXT, "strlen");

....

}


i use the library by the LD_PRELOAD env var, I _thought_ that LD_PRELOAD was loaded before anything (except maybe libc). Well, it works fine for most programs. But when I run a program that it is linked to libpthread ('ls' for instance), it segfaults. Looking in gdb i found


Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
(gdb) bt
#0 0x00000000 in ?? ()
#1 0x40016d7f in strstr (a=0xbffff23c "#4 Sun May 16 18:38:24 EDT 2004",
b=0x40177624 "SMP") at trace.c:98
#2 0x401716a1 in longjmp () from /lib/libpthread.so.0
#3 0x401775b5 in pthread_atfork () from /lib/libpthread.so.0
#4 0x4016dbd9 in ?? () from /lib/libpthread.so.0
#5 0x40014d80 in ?? () from /lib/ld-linux.so.2
#6 0x40000aa4 in ?? () from /lib/ld-linux.so.2
#7 0xbffff5b4 in ?? ()
#8 0x4000a98e in _dl_catch_error () from /lib/ld-linux.so.2
Previous frame identical to this frame (corrupt stack?)


so obviously libpthread is being initialized first, and calling _my_ strstr(), but that calls ___libc_strstr(), which is still NULL...

Does anyone know of a decent workaround for this?

maccorin
06-02-2004, 02:21 AM
sorry for the bump, but this is _really_ pissing me off. Theres got be some ENV var or something i can set that I'm missing.

bwkaz
06-02-2004, 06:00 PM
I don't know how to do that, but I think I remember something about how they're called in an indeterminate order (though I don't remember for sure).

Maybe you could check in strstr() whether the pointer is NULL, and if so, either set it to what it needs to be, or do something else?

(Also, the " = NULL" at the beginning isn't needed -- static lifetime variables get initialized to zero by the compiler. Not that it's hurting anything, though...)

Does it help to put your library into /etc/ld.so.preload (and rerun ldconfig) instead of using LD_PRELOAD?

maccorin
06-02-2004, 06:14 PM
yea, i know the = NULL isn't needed, it's just their for aesthetics ;p

as far as putting it in ld.so.conf, i'll try that, but it's not a very practical solution, because my my lib does is it sends a _lot_ of extra output to stderr, (for instance 'ifconfig' sends about 300 lines to stderr w/ it preloaded) so i don't want it to be loaded normally, just when i run a program w/ LD_PRELOAD=./libstrtrace.so

but yea....

I also tried just hardcoding the address of strstr on my system since i've thrown portability out the window w/ other things anyways (see my runtime array size checking thread for that), but then i get a segfault in longjmp in glibc on initialization, i haven't really gone through the src and gdb for that yet though. I may just end up _not_ overwriting strstr(), because it's not really important for tracing a certain string through a program anyways

bwkaz
06-02-2004, 09:37 PM
Hmm... it's been quite a while since I had to deal with setjmp and longjmp. I think longjmp takes an intiialized jump buffer as its argument, right? Maybe that never got set up properly...

Or, maybe it would be better to ignore strstr. ;p

maccorin
06-03-2004, 03:56 AM
Originally posted by bwkaz
Hmm... it's been quite a while since I had to deal with setjmp and longjmp. I think longjmp takes an intiialized jump buffer as its argument, right? Maybe that never got set up properly...

Or, maybe it would be better to ignore strstr. ;p

yea, my temporary solution is just to ignore it (I've never dealt w/ longjmp and setjmp, shows my inexperience :/) but i hate doing that because who knows what other functions i'll hit the same issue w/?

oh well, the other string functions seem to work pretty well, now i gotta think of a creative way to find all the inlined string functions :D