[uClibc]bug in dynamic loader

Tero Lyytikäinen tero at paravant.fi
Wed Sep 18 17:40:24 UTC 2002


First I'd like you to know, that I know nothing about elf or dynamic
loading. So I cannot provide a patch and I'm not really sure if this is
really a bug. But this is what I found out:

When a program compiled with uClibc dlopens a library that is linked with
another library, uClibc's dlopen cannot resolve the symbols of the
"another library". I'll try to illustrate this:

test program:
dlopen("testlib.so");  --------> testlib.so is linked with -ltest2
					|
					|
					v
				should also load libtest2.so


Now dlopen will load testlib.so but it cannot load libtest2.so. (It will
fail with dlerror() as "File not found". This is a trivial bug, but
strange. At uClibc-0.9.15/ldso/libdl/dlib.c around line 176:

  if(dpnt->d_tag == DT_NEEDED)
    {
      lpnt = tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
	dpnt->d_un.d_val;
      if(!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpnt)))
	goto oops;


Here lpnt doesn't get a correct value. It might be a bug in the compiler
(I'm using gcc 3.1.1) as gdb will say lpnt is "(unsigned long *)"!!
(Strangely the same type of line works in ldso/ldso.c)
Well, the following change works for me:

      lpnt = tcurr->loadaddr;
      lpnt += (int)tcurr->dynamic_info[DT_STRTAB];
      lpnt += (int)dpnt->d_un.d_val;


So this might not affect all of you. But the next one will:

When the module(s) are loaded with _dl_load_shared_library their
"tpnt->symbol_scope" is set to _dl_symbol_tables which is
incorrect (I think!) because the loaded modules are not part of the main
program symbol table. This causes do_fixup call fail with

./test: symbol '__register_frame_info_bases': can't resolve symbol

type messages (that causes a segfault with uClibc-0.9.15 as I explained
in my previous mail) So the line

if (!tpnt1->symbol_scope) tpnt1->symbol_scope = dyn_chain;

should be

tpnt1->symbol_scope = ????

Where "????" is something I really don't know. Trying

tpnt1->symbol_scope = dyn_chain;

seems reasonable and works. But not in all cases :(

As you might not understand any of my feeble efforts in explaining this I
have deviced a simple test case!

It can be found at http://www.anemic.org/dltest.tar.gz (8kb)

If you could run the testcase and tell if you are experiencing the
same problems as I.

When this is compiled with uClibc it will produce unresolved symbols, but
when compiled with glibc based system it will run fine. Note that when
compiling with glibc you need to remove the call to _dlinfo() in test.c.

Well, not many programs use dlopen but mozilla will, and it will fail like
my test case. But I have not been able to produce a fix that can make the
mozilla run correctly. Setting tpnt1->symbol_scope = dyn_chain that works
with the testcase will cause mozilla to fail with "libdl library not
correctly linked". Which is _very_ interesting. I've been investigating
this for a week and a half now and I'm about to give up.

(Note that doing a LD_PRELOAD=libtest2.so ./test will run the application
correctly as preloading will place the library in the main
_dl_symbol_tables and do_fixup will find them. The same method can be used
to load mozilla correctly (only about a dozen libraries need to be
preloaded..). Mozilla will still assert and quit, but it's very,very close
to opening a window!)





More information about the uClibc mailing list