dlsym(RTLD_NEXT) and weak symbols
Maxim Sobolev
sobomax at FreeBSD.org
Wed Oct 8 22:33:50 UTC 2008
Maxim Sobolev wrote:
> Hi,
>
> I am not sure if it has even worked correctly, but calling
> dlsym("dlopen", RTLD_NEXT) returns reference to the dlopen() function in
> the libc, not reference to dlopen() function in the ld-elf.so. The
> attempt to call this function then fails, since dlopen() in libc is just
> a stub to make static linking happy.
>
> #pragma weak dlopen
> void *
> dlopen(const char *name, int mode)
> {
> _rtld_error(sorry);
> return NULL;
> }
>
> IMHO this is incorrect and is probably part of the bigger problem. The
> dlsym(3) should return first non-weak symbol instead.
The following patch fixes the issue for me:
--- rtld.c 2008-08-18 13:24:19.000000000 -0700
+++ rtld.c 2008-10-08 15:28:47.000000000 -0700
@@ -1871,10 +1871,25 @@
if (handle == RTLD_NEXT)
obj = obj->next;
for (; obj != NULL; obj = obj->next) {
- if ((def = symlook_obj(name, hash, obj, true)) != NULL) {
+ if ((def = symlook_obj(name, hash, obj, true)) != NULL &&
+ ELF_ST_BIND(def->st_info) != STB_WEAK) {
defobj = obj;
break;
}
+ def = NULL;
+ }
+ /*
+ * Search the dynamic linker itself, and possibly resolve the
+ * symbol from there. Only the values listed in the "exports"
+ * array can be resolved from the dynamic linker.
+ */
+ if (def == NULL) {
+ def = symlook_obj(name, hash, &obj_rtld, true);
+ if (def != NULL && is_exported(def)) {
+ defobj = &obj_rtld;
+ } else {
+ def = NULL;
+ }
}
} else {
assert(handle == RTLD_DEFAULT);
-Maxim
More information about the freebsd-current
mailing list