[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