[sldev] ELF .so relocation problem?

Alissa Sabre alissa_sabre at yahoo.co.jp
Tue Apr 14 06:51:44 PDT 2009


Dear Developers,

I'm having a problem apparently related to ELF relocation mechanism of
.so on Linux.  I have no idea what causes it, and spent a whole
weekend with no success.  Any hint or suggestion is appreciated.

THE PROBLEM

A standalone viewer build apparently succeeded, but, when started, it
crushed after the initial black screen appeared.  The log says:

    ** ERROR **: g_thread_init() must be called before dbus_threads_init()

OBSERVATION

No-standalone viewer built from the same source runs fine.

The message is from the function dbus_threads_init(), defined in
libdbus-glib-1.so.

In glib, there is a global variable, g_threads_got_initialized to
indicate whether g_thread_init() has been called.  Because Linux uses
ELF and the variable is defined in a .so, the main executable,
secondlife-bin, has a copy of the variable, and all references to the
variable should be directed to the one in secondlife-bin upon
relocation.

However, for whatever reason, dbus_threads_init()'s access to the
variable is directed to the one in libglib-2.0.so.  Hence, the above
message.

I have no idea why the reloc for libdbus-glib-1.so makes the reference
to the variable g_threads_got_initialized to point to the _prototype_
in libglib-2.0.so and not the copy in the main executable.

DETAILS

The viewer was crushing inside the function dbus_thread_init().

After some examination with gdb, I found that the message was wrong,
i.e., g_thread_init() was surely called before dbus_threads_init(),
but the dbus_threads_init() aborted with the above message.

The source of the function looks as:


and g_thread_availabe() is a macro defined as:


where g_threads_got_initialized is declared as:


I also found that the variable g_threads_got_initialized was set to 1
during the call to g_thread_init(), and was kept to the value 1
immediately before the dbus_threads_init() was first invoked.

And it still aborted.

I disassembled the function (fortunately it is small) and single
stepped over machine instructions.

Then, I found the particular if statement examined a different
location than g_threads_got_initialized.  WoW!  The location was, the
_prototype_ location for the variable g_thread_got_initialized in
libglib.so.

I have no idea what caused the particular reloc entry to fix up to
refer to the prototype location instead of the actual variable
location in the secondlife-bin executable.  A suspicious fact is that
the SL viewer loads libdbus-glib-1.so in an unusual way through
apr_dso_load.  I'm afraid it caused a strange effects, although the
no-standalone built viewer should do exactly the same thing and still
runs fine.

ENVIRONMENT

I'm using Fedora 10 x86.  It contains:

kernel 2.6.27.21
glibc 2.9-3
dbus-glib 0.76-3
glib 1.2.10-30

    Alissa Sabre
--------------------------------------
Power up the Internet with Yahoo! Toolbar.
http://pr.mail.yahoo.co.jp/toolbar/


More information about the SLDev mailing list