Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 08 Oct 2008 15:33:41 -0700
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        Alexander Kabaev <kan@FreeBSD.org>
Cc:        "current@freebsd.org" <current@FreeBSD.org>
Subject:   Re: dlsym(RTLD_NEXT) and weak symbols
Message-ID:  <48ED3545.6030609@FreeBSD.org>
In-Reply-To: <48ED27EA.9020407@FreeBSD.org>
References:  <48ED27EA.9020407@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?48ED3545.6030609>