tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: lib/39986: libmapper_zone.so is trying to call undefined weak symbol
hi, all
> While running mail/sylpheed it exits with the following line on my terminal
> at random occasions (when opening mail):
>
> /usr/lib/i18n/libmapper_zone.so.4.4: Trying to call undefined weak symbol
> `__deregister_frame_info'
>
this is not mapper_zone(which is part of Citrus iconv)'s problem.
i suspect C/C++ runtime problem on NetBSD.
[background]
GTK+2 have so called gtkimmodule, own input method framework
that doesn't depend on X Window System's XIM protocol.
it isn't apply server/client style remote procedule call,
simply and directly depends on dlopen(3).
and some 3rd party gtkimmodule(AFAIK pkgsrc-wip/scim) is C++ ABI.
but NetBSD's dlopen(3), dynamic loading C++ shared library from C application
may causes crash.
[reproduce the problem]
1. build C++ shared library
$ cat >foo.h
#if defined(__cplusplus)
extern "C" {
#endif
void foo(void);
#if defined(__cplusplus)
}
#endif
^D
$ cat >foo.cpp
#include <string>
#include <iostream>
#include "foo.h"
void
foo(void)
{
std::basic_string<char> msg;
msg = std::basic_string<char>("hello, C++ world.\n");
std::cout << msg;
}
^D
$ g++ -shared -g -o libfoo.so foo.cpp
$ cat >bar.h
void bar(void);
^D
2. build C shared library.
$ cat >bar.c
#include <stdio.h>
#include "bar.h"
void
bar(void)
{
printf("hello, C world.\n");
}
^D
$ gcc -shared -g -o libbar.so bar.c
3. build application that dlopen(3) both C/C++ libraries.
$ cat >buzz.c
#include <dlfcn.h>
typedef void (*func_t)(void);
int
main(void)
{
void *foo, *foo_func, *bar, *bar_func;
foo = dlopen("libfoo.so", RTLD_GLOBAL);
foo_func = dlsym(foo, "foo");
((func_t)foo_func)();
bar = dlopen("libbar.so", RTLD_GLOBAL);
bar_func = dlsym(bar, "bar");
((func_t)bar_func)();
dlclose(foo);
dlclose(bar);
return 0;
}
^D
$ gcc -g -o buzz buzz.c
4. run it.
$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./buzz
hello, C++ world.
hello, C world.
./libbar.so: Trying to call undefined weak symbol `__deregister_frame_info'
this problem happen only following order:
dlclose(foo) /* C++ library */
dlclose(bar) /* C library */
following order no harm:
dlclose(bar) /* C library */
dlclose(foo) /* C++ library */
[why this problem occur?]
C++ throws exception via stack frame by __(de)register_frame_info().
this function exists in libgcc_s.so:
$ nm /usr/lib/libgcc_s.so | egrep "__(de)?register_frame_info$"
00007e00 T __deregister_frame_info
00007c60 T __register_frame_info
and crtbeginS.o has weak reference for it;
$ nm /usr/lib/crtbeginS.o | egrep "__(de)?register_frame_info$"
w __deregister_frame_info
w __register_frame_info
so that both C++ and C library refer it too:
$ nm libfoo.so | egrep "__(de)?register_frame_info"
w __deregister_frame_info@@GCC_3.0
w __register_frame_info@@GCC_3.0
$ nm libbar.so | egrep "__(de)?register_frame_info"
w __deregister_frame_info
w __register_frame_info
but, dependency for libgcc_s.so is recoreded only C++ library.
$ ldd libfoo.so
libfoo.so:
-lc.12 => /usr/lib/libc.so.12
-lstdc++.7 => /usr/lib/libstdc++.so.7
-lm.0 => /usr/lib/libm.so.0
-lgcc_s.1 => /usr/lib/libgcc_s.so.1
libbar.so:
-lc.12 => /usr/lib/libc.so.12
so if dlclose(3) libfoo before libbar, can't resolve real
__deregistered_frame_info() because libgcc_s has been unloaded.
(if only load/unload C library, __deregister_frame_info is fake
symbol, no problem)
$ LD_DEBUG=1 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./buzz
...
_rtld_call_fini_functions(0)
_rtld_initlist_tsort
calling fini function ./libfoo.so at 0xbbadd900
calling fini function /usr/lib/libgcc_s.so.1 at 0xbb9de140
calling fini function /usr/lib/libm.so.0 at 0xbb9f6880
calling fini function /usr/lib/libstdc++.so.7 at 0xbbab2ce0
_rtld_call_fini_functions(0)
_rtld_initlist_tsort
calling fini function ./libbar.so at 0xbb9d4430
./libbar.so: Trying to call undefined weak symbol `__deregister_frame_info'
rtld_exit()
_rtld_call_fini_functions(1)
_rtld_initlist_tsort
calling fini function /usr/lib/libc.so.12 at 0xbbbc51e0 (DF_1_INITFIRST)
[how to fix]
i'm not toolchain and elf guru, so i can't decided my mind:
1. don't use __(de)?register_frame_info but .eh_frame section instead
by adding --eh-frame-hdr option. it seems that Linux/glibc2 now using it,
also FreeBSD, OpenBSD too
$ /usr/pkg/emul/linux/usr/bin/gcc -### -shared -o libbar.so bar.c
... "--eh-frame-hdr" ...
2. clarify application using dlopen(3) must add -lgcc_s option.
same approach of non ptheaded application loading ptheaded library.
see following discussion:
http://mail-index.netbsd.org/pkgsrc-users/2009/01/17/msg009088.html
3. hack ld.elf_so
re-add fake symbol to undefined weak symbol.
ummmm, i think bad idea.
any idea?
very truly yours.
--
Takehiko NOZAKI <tnozaki%NetBSD.org@localhost>
Home |
Main Index |
Thread Index |
Old Index