Update.
authorUlrich Drepper <drepper@redhat.com>
Sat, 26 Aug 2000 23:41:19 +0000 (23:41 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 26 Aug 2000 23:41:19 +0000 (23:41 +0000)
2000-08-26  Ulrich Drepper  <drepper@redhat.com>

* elf/Makefile (distribute): Add unloadmod.c, reldepmod1.c,
reldepmod2.c, reldepmod3.c, and reldepmod4.c.
(tests): Add unload, reldep, reldep2, and reldep3.
(modules-names): Add unloadmod, reldepmod1, reldepmod2, reldepmod3,
and reldepmod4.
Add rules to build and run unload, reldep, reldep2, and reldep3.
* elf/dl-lookup.c (_dl_lookup_symbol): Add new parameter explicit.
Don't create relocation dependency if it is nonzero.
(_dl_lookup_symbol_skip): Remove relocation dependency stuff.  This
can never happen here.
(_dl_lookup_versioned_symbol): Add new parameter explicit.
Don't create relocation dependency if it is nonzero.
(_dl_lookup_versioned_symbol_skip): Remove relocation dependency
stuff.  This can never happen here.
* sysdeps/generic/ldsodefs.h: Change prototypes.
* elf/dl-reloc.c (RESOLVE_MAP): Pass 0 in explicit parameter to
_dl_lookup_up and _dl_lookup_versioned_symbol.
(RESOLV): Likewise.
* elf/dl-runtime.c (fixup): Likewise.
(profile_fixup): Likewise.
* elf/dl-libc.c (do_dlsym): Pass 1 in explicit parameter to
_dl_lookup_symbol.
* elf/dl-symbol.c (_dl_symbol_value): Likewise.
* elf/rtld.c (dl_main): Likewise.
* elf/dl-sym.c (_dl_sym): Pass 1 in explicit parameter to
_dl_lookup_symbol if handle is not RTLD_DEFAULT.  Always compute
and pass down the caller map.
(_dl_vsym): Likewise.
* elf/reldep.c: New file.
* elf/reldep2.c: New file.
* elf/reldep3.c: New file.
* elf/reldepmod1.c: New file.
* elf/reldepmod2.c: New file.
* elf/reldepmod3.c: New file.
* elf/reldepmod4.c: New file.
* elf/unload.c: New file.
* elf/unloadmod.c: New file.

* elf/do-lookup.h: Remove unused undef_name parameter.
* elf/dl-lookup.c: Adjust callers.

20 files changed:
ChangeLog
elf/Makefile
elf/dl-libc.c
elf/dl-lookup.c
elf/dl-reloc.c
elf/dl-runtime.c
elf/dl-sym.c
elf/dl-symbol.c
elf/do-lookup.h
elf/reldep.c [new file with mode: 0644]
elf/reldep2.c [new file with mode: 0644]
elf/reldep3.c [new file with mode: 0644]
elf/reldepmod1.c [new file with mode: 0644]
elf/reldepmod2.c [new file with mode: 0644]
elf/reldepmod3.c [new file with mode: 0644]
elf/reldepmod4.c [new file with mode: 0644]
elf/rtld.c
elf/unload.c [new file with mode: 0644]
elf/unloadmod.c [new file with mode: 0644]
sysdeps/generic/ldsodefs.h

index 9f4e451..6fc74a0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2000-08-26  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf/Makefile (distribute): Add unloadmod.c, reldepmod1.c,
+       reldepmod2.c, reldepmod3.c, and reldepmod4.c.
+       (tests): Add unload, reldep, reldep2, and reldep3.
+       (modules-names): Add unloadmod, reldepmod1, reldepmod2, reldepmod3,
+       and reldepmod4.
+       Add rules to build and run unload, reldep, reldep2, and reldep3.
+       * elf/dl-lookup.c (_dl_lookup_symbol): Add new parameter explicit.
+       Don't create relocation dependency if it is nonzero.
+       (_dl_lookup_symbol_skip): Remove relocation dependency stuff.  This
+       can never happen here.
+       (_dl_lookup_versioned_symbol): Add new parameter explicit.
+       Don't create relocation dependency if it is nonzero.
+       (_dl_lookup_versioned_symbol_skip): Remove relocation dependency
+       stuff.  This can never happen here.
+       * sysdeps/generic/ldsodefs.h: Change prototypes.
+       * elf/dl-reloc.c (RESOLVE_MAP): Pass 0 in explicit parameter to
+       _dl_lookup_up and _dl_lookup_versioned_symbol.
+       (RESOLV): Likewise.
+       * elf/dl-runtime.c (fixup): Likewise.
+       (profile_fixup): Likewise.
+       * elf/dl-libc.c (do_dlsym): Pass 1 in explicit parameter to
+       _dl_lookup_symbol.
+       * elf/dl-symbol.c (_dl_symbol_value): Likewise.
+       * elf/rtld.c (dl_main): Likewise.
+       * elf/dl-sym.c (_dl_sym): Pass 1 in explicit parameter to
+       _dl_lookup_symbol if handle is not RTLD_DEFAULT.  Always compute
+       and pass down the caller map.
+       (_dl_vsym): Likewise.
+       * elf/reldep.c: New file.
+       * elf/reldep2.c: New file.
+       * elf/reldep3.c: New file.
+       * elf/reldepmod1.c: New file.
+       * elf/reldepmod2.c: New file.
+       * elf/reldepmod3.c: New file.
+       * elf/reldepmod4.c: New file.
+       * elf/unload.c: New file.
+       * elf/unloadmod.c: New file.
+
+       * elf/do-lookup.h: Remove unused undef_name parameter.
+       * elf/dl-lookup.c: Adjust callers.
+
 2000-08-25  Ulrich Drepper  <drepper@redhat.com>
 
        * iconv/gconv_trans.c (__gconv_transliterate): Pass NULL instead of
index 369aaba..9f9fef9 100644 (file)
@@ -41,13 +41,14 @@ distribute  := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
                   dl-librecon.h interp.c sln.c dl-dst.h hp-timing.h \
                   do-lookup.h dl-lookupcfg.h sprof.c gen-trusted-dirs.awk \
                   testobj1.c testobj2.c testobj3.c testobj4.c testobj5.c \
-                  testobj6.c testobj1_1.c failobj.c \
+                  testobj6.c testobj1_1.c failobj.c unloadmod.c \
                   ldconfig.h ldconfig.c cache.c readlib.c readelflib.c \
                   dep1.c dep2.c dep3.c dep4.c dl-dtprocnum.h \
                   vismain.c vismod1.c vismod2.c vismod3.c \
                   constload2.c constload3.c filtmod1.c filtmod2.c \
                   nodlopenmod.c nodelete.c nodelmod1.c nodelmod2.c \
-                  nodelmod3.c nodelmod4.c nodlopen.c dl-osinfo.h
+                  nodelmod3.c nodelmod4.c nodlopen.c dl-osinfo.h \
+                  reldepmod1.c reldepmod2.c reldepmod3.c reldepmod4.c
 
 include ../Makeconfig
 
@@ -87,18 +88,19 @@ endif
 
 ifeq (yes,$(build-shared))
 tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
-       constload1 order $(tests-vis-$(have-protected)) noload filter \
-       $(tests-nodelete-$(have-z-nodelete)) \
+       constload1 order $(tests-vis-$(have-protected)) noload filter unload \
+       reldep reldep2 reldep3 $(tests-nodelete-$(have-z-nodelete)) \
        $(tests-nodlopen-$(have-z-nodlopen))
 tests-vis-yes = vismain
 tests-nodelete-yes = nodelete
 tests-nodlopen-yes = nodlopen
 endif
 modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
-               testobj1_1 failobj constload2 constload3 \
+               testobj1_1 failobj constload2 constload3 unloadmod \
                dep1 dep2 dep3 dep4 $(modules-vis-$(have-protected)) \
                $(modules-nodelete-$(have-z-nodelete)) \
-               $(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2
+               $(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2 \
+               reldepmod1 reldepmod2 reldepmod3 reldepmod4
 modules-vis-yes = vismod1 vismod2 vismod3
 modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
 modules-nodlopen-yes = nodlopenmod
@@ -319,3 +321,15 @@ $(objpfx)filtmod1.so: $(objpfx)filtmod1.os $(objpfx)filtmod2.so
                  -Wl,-rpath-link=$(rpath-link) \
                  $< -Wl,-F,$(objpfx)filtmod2.so
 $(objpfx)filter: $(objpfx)filtmod1.so
+
+$(objpfx)unload: $(libdl)
+$(objpfx)unload.out: $(objpfx)unloadmod.so
+
+$(objpfx)reldep: $(libdl)
+$(objpfx)reldep.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod2.so
+
+$(objpfx)reldep2: $(libdl)
+$(objpfx)reldep2.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod3.so
+
+$(objpfx)reldep3: $(libdl)
+$(objpfx)reldep3.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod4.so
index 8518909..7d2b360 100644 (file)
@@ -84,7 +84,7 @@ do_dlsym (void *ptr)
   struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
   args->ref = NULL;
   args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref,
-                                     args->map->l_local_scope, 0);
+                                     args->map->l_local_scope, 0, 1);
 }
 
 static void
index f1ec98e..2b58ff3 100644 (file)
@@ -190,7 +190,7 @@ lookup_t
 internal_function
 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
                   const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
-                  int reloc_type)
+                  int reloc_type, int explicit)
 {
   const char *reference_name = undef_map ? undef_map->l_name : NULL;
   const unsigned long int hash = _dl_elf_hash (undef_name);
@@ -204,8 +204,8 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 
   /* Search the relevant loaded objects for a definition.  */
   for (scope = symbol_scope; *scope; ++scope)
-    if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
-                  *scope, 0, NULL, noexec, noplt))
+    if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
+                  noexec, noplt))
       {
        /* We have to check whether this would bind UNDEF_MAP to an object
           in the global scope which was dynamically loaded.  In this case
@@ -215,12 +215,15 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
            && (__builtin_expect (current_value.m->l_type, lt_library)
                == lt_loaded)
            && undef_map != current_value.m
+           /* Don't do this for explicit lookups as opposed to implicit
+              runtime lookups.  */
+           && __builtin_expect (! explicit, 1)
            /* Add UNDEF_MAP to the dependencies.  */
            && add_dependency (undef_map, current_value.m) < 0)
          /* Something went wrong.  Perhaps the object we tried to reference
             was just removed.  Try finding another definition.  */
          return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
-                                   reloc_type);
+                                   reloc_type, 0);
 
        break;
       }
@@ -262,8 +265,8 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
       struct sym_val protected_value = { NULL, NULL };
 
       for (scope = symbol_scope; *scope; ++scope)
-       if (do_lookup (undef_name, undef_map, hash, *ref,
-                      &protected_value, *scope, 0, NULL, 0, 1))
+       if (do_lookup (undef_name, hash, *ref, &protected_value, *scope, 0,
+                      NULL, 0, 1))
          break;
 
       if (protected_value.s == NULL || protected_value.m == undef_map)
@@ -303,47 +306,13 @@ _dl_lookup_symbol_skip (const char *undef_name,
   for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
     assert (i < (*scope)->r_nduplist);
 
-  if (i < (*scope)->r_nlist
-      && do_lookup (undef_name, undef_map, hash, *ref, &current_value,
-                   *scope, i, skip_map, 0, 0))
-    {
-      /* We have to check whether this would bind UNDEF_MAP to an object
-        in the global scope which was dynamically loaded.  In this case
-        we have to prevent the latter from being unloaded unless the
-        UNDEF_MAP object is also unloaded.  */
-      if (current_value.m->l_global
-         && (__builtin_expect (current_value.m->l_type, lt_library)
-             == lt_loaded)
-         && undef_map != current_value.m
-         /* Add UNDEF_MAP to the dependencies.  */
-         && add_dependency (undef_map, current_value.m) < 0)
-       /* Something went wrong.  Perhaps the object we tried to reference
-          was just removed.  Try finding another definition.  */
-       return _dl_lookup_symbol_skip (undef_name, undef_map, ref,
-                                      symbol_scope, skip_map);
-    }
-  else
+  while (i >= (*scope)->r_nlist
+        || ! do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
+                        skip_map, 0, 0))
     while (*++scope)
-      if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
-                    *scope, 0, skip_map, 0, 0))
-       {
-         /* We have to check whether this would bind UNDEF_MAP to an object
-            in the global scope which was dynamically loaded.  In this case
-            we have to prevent the latter from being unloaded unless the
-            UNDEF_MAP object is also unloaded.  */
-         if (__builtin_expect (current_value.m->l_global, 0)
-             && (__builtin_expect (current_value.m->l_type, lt_library)
-                 == lt_loaded)
-             && undef_map != current_value.m
-             /* Add UNDEF_MAP to the dependencies.  */
-             && add_dependency (undef_map, current_value.m) < 0)
-           /* Something went wrong.  Perhaps the object we tried to reference
-              was just removed.  Try finding another definition.  */
-           return _dl_lookup_symbol_skip (undef_name, undef_map, ref,
-                                          symbol_scope, skip_map);
-
-         break;
-       }
+      if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
+                    skip_map, 0, 0))
+       break;
 
   if (__builtin_expect (current_value.s == NULL, 0))
     {
@@ -370,16 +339,16 @@ _dl_lookup_symbol_skip (const char *undef_name,
     }
   else
     {
-      /* It is very tricky. We need to figure out what value to
-         return for the protected symbol */
+      /* It is very tricky.  We need to figure out what value to
+         return for the protected symbol */
       struct sym_val protected_value = { NULL, NULL };
 
       if (i >= (*scope)->r_nlist
-         || !do_lookup (undef_name, undef_map, hash, *ref, &protected_value,
-                        *scope, i, skip_map, 0, 1))
+         || !do_lookup (undef_name, hash, *ref, &protected_value, *scope, i,
+                        skip_map, 0, 1))
        while (*++scope)
-         if (do_lookup (undef_name, undef_map, hash, *ref, &protected_value,
-                        *scope, 0, skip_map, 0, 1))
+         if (do_lookup (undef_name, hash, *ref, &protected_value, *scope, 0,
+                        skip_map, 0, 1))
            break;
 
       if (protected_value.s == NULL || protected_value.m == undef_map)
@@ -404,7 +373,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
                             struct link_map *undef_map, const ElfW(Sym) **ref,
                             struct r_scope_elem *symbol_scope[],
                             const struct r_found_version *version,
-                            int reloc_type)
+                            int reloc_type, int explicit)
 {
   const char *reference_name = undef_map ? undef_map->l_name : NULL;
   const unsigned long int hash = _dl_elf_hash (undef_name);
@@ -419,9 +388,8 @@ _dl_lookup_versioned_symbol (const char *undef_name,
   /* Search the relevant loaded objects for a definition.  */
   for (scope = symbol_scope; *scope; ++scope)
     {
-      int res = do_lookup_versioned (undef_name, undef_map, hash, *ref,
-                                    &current_value, *scope, 0, version, NULL,
-                                    noexec, noplt);
+      int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
+                                    *scope, 0, version, NULL, noexec, noplt);
       if (res > 0)
        {
          /* We have to check whether this would bind UNDEF_MAP to an object
@@ -432,13 +400,16 @@ _dl_lookup_versioned_symbol (const char *undef_name,
              && (__builtin_expect (current_value.m->l_type, lt_library)
                  == lt_loaded)
              && undef_map != current_value.m
+             /* Don't do this for explicit lookups as opposed to implicit
+                runtime lookups.  */
+             && __builtin_expect (! explicit, 1)
              /* Add UNDEF_MAP to the dependencies.  */
              && add_dependency (undef_map, current_value.m) < 0)
            /* Something went wrong.  Perhaps the object we tried to reference
               was just removed.  Try finding another definition.  */
            return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
                                                symbol_scope, version,
-                                               reloc_type);
+                                               reloc_type, 0);
 
          break;
        }
@@ -502,9 +473,8 @@ _dl_lookup_versioned_symbol (const char *undef_name,
       struct sym_val protected_value = { NULL, NULL };
 
       for (scope = symbol_scope; *scope; ++scope)
-       if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
-                                &protected_value, *scope, 0, version, NULL,
-                                0, 1))
+       if (do_lookup_versioned (undef_name, hash, *ref, &protected_value,
+                                *scope, 0, version, NULL, 0, 1))
          break;
 
       if (protected_value.s == NULL || protected_value.m == undef_map)
@@ -543,50 +513,13 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
   for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
     assert (i < (*scope)->r_nduplist);
 
-  if (i < (*scope)->r_nlist
-      && do_lookup_versioned (undef_name, undef_map, hash, *ref,
-                             &current_value, *scope, i, version, skip_map,
-                             0, 0))
-    {
-      /* We have to check whether this would bind UNDEF_MAP to an object
-        in the global scope which was dynamically loaded.  In this case
-        we have to prevent the latter from being unloaded unless the
-        UNDEF_MAP object is also unloaded.  */
-      if (__builtin_expect (current_value.m->l_global, 0)
-         && (__builtin_expect (current_value.m->l_type, lt_library)
-             == lt_loaded)
-         && undef_map != current_value.m
-         /* Add UNDEF_MAP to the dependencies.  */
-         && add_dependency (undef_map, current_value.m) < 0)
-       /* Something went wrong.  Perhaps the object we tried to reference
-          was just removed.  Try finding another definition.  */
-       return _dl_lookup_versioned_symbol_skip (undef_name, undef_map, ref,
-                                                symbol_scope, version,
-                                                skip_map);
-    }
-  else
+  if (i >= (*scope)->r_nlist
+      || ! do_lookup_versioned (undef_name, hash, *ref, &current_value,
+                               *scope, i, version, skip_map, 0, 0))
     while (*++scope)
-      if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
-                              &current_value, *scope, 0, version, skip_map,
-                              0, 0))
-       {
-         /* We have to check whether this would bind UNDEF_MAP to an object
-            in the global scope which was dynamically loaded.  In this case
-            we have to prevent the latter from being unloaded unless the
-            UNDEF_MAP object is also unloaded.  */
-         if (current_value.m->l_global
-             && (__builtin_expect (current_value.m->l_type, lt_library)
-                 == lt_loaded)
-             && undef_map != current_value.m
-             /* Add UNDEF_MAP to the dependencies.  */
-             && add_dependency (undef_map, current_value.m) < 0)
-           /* Something went wrong.  Perhaps the object we tried to reference
-              was just removed.  Try finding another definition.  */
-           return _dl_lookup_versioned_symbol_skip (undef_name, undef_map,
-                                                    ref, symbol_scope,
-                                                    version, skip_map);
-         break;
-       }
+      if (do_lookup_versioned (undef_name, hash, *ref, &current_value, *scope,
+                              0, version, skip_map, 0, 0))
+       break;
 
   if (__builtin_expect (current_value.s == NULL, 0))
     {
@@ -631,13 +564,11 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
       struct sym_val protected_value = { NULL, NULL };
 
       if (i >= (*scope)->r_nlist
-         || !do_lookup_versioned (undef_name, undef_map, hash, *ref,
-                                  &protected_value, *scope, i, version,
-                                  skip_map, 0, 1))
+         || !do_lookup_versioned (undef_name, hash, *ref, &protected_value,
+                                  *scope, i, version, skip_map, 0, 1))
        while (*++scope)
-         if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
-                                  &protected_value, *scope, 0, version,
-                                  skip_map, 0, 1))
+         if (do_lookup_versioned (undef_name, hash, *ref, &protected_value,
+                                  *scope, 0, version, skip_map, 0, 1))
            break;
 
       if (protected_value.s == NULL || protected_value.m == undef_map)
index f840f3c..643885e 100644 (file)
@@ -75,17 +75,17 @@ cannot make segment writable for relocation"));
     (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL                            \
      ? ((version) != NULL && (version)->hash != 0                            \
        ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref),    \
-                                      scope, (version), (flags))             \
+                                      scope, (version), (flags), 0)          \
        : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope,       \
-                            (flags)))                                        \
+                            (flags), 0))                                     \
      : l)
 #define RESOLVE(ref, version, flags) \
     (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL                            \
      ? ((version) != NULL && (version)->hash != 0                            \
        ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref),    \
-                                      scope, (version), (flags))             \
+                                      scope, (version), (flags), 0)          \
        : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope,       \
-                            (flags)))                                        \
+                            (flags), 0))                                     \
      : l->l_addr)
 
 #include "dynamic-link.h"
index 5774609..01beb19 100644 (file)
@@ -89,13 +89,13 @@ fixup (
                result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
                                                      l, &sym, l->l_scope,
                                                      version,
-                                                     ELF_MACHINE_JMP_SLOT);
+                                                     ELF_MACHINE_JMP_SLOT, 0);
                break;
              }
          }
        case 0:
          result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
-                                     l->l_scope, ELF_MACHINE_JMP_SLOT);
+                                     l->l_scope, ELF_MACHINE_JMP_SLOT, 0);
        }
 
       /* Currently result contains the base load address (or link map)
@@ -181,13 +181,14 @@ profile_fixup (
                    result = _dl_lookup_versioned_symbol(strtab + sym->st_name,
                                                         l, &sym, l->l_scope,
                                                         version,
-                                                        ELF_MACHINE_JMP_SLOT);
+                                                        ELF_MACHINE_JMP_SLOT,
+                                                        0);
                    break;
                  }
              }
            case 0:
              result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
-                                         l->l_scope, ELF_MACHINE_JMP_SLOT);
+                                         l->l_scope, ELF_MACHINE_JMP_SLOT, 0);
            }
 
          /* Currently result contains the base load address (or link map)
index e54ed80..8738656 100644 (file)
@@ -31,22 +31,21 @@ _dl_sym (void *handle, const char *name, void *who)
 {
   const ElfW(Sym) *ref = NULL;
   lookup_t result;
+  ElfW(Addr) caller = (ElfW(Addr)) who;
+  struct link_map *match;
+  struct link_map *l;
+
+  /* Find the highest-addressed object that CALLER is not below.  */
+  match = NULL;
+  for (l = _dl_loaded; l; l = l->l_next)
+    if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
+      match = l;
 
   if (handle == RTLD_DEFAULT)
     /* Search the global scope.  */
-    result = _dl_lookup_symbol (name, NULL, &ref, _dl_global_scope, 0);
+    result = _dl_lookup_symbol (name, match, &ref, _dl_global_scope, 0, 0);
   else
     {
-      struct link_map *l;
-      struct link_map *match;
-      ElfW(Addr) caller = (ElfW(Addr)) who;
-
-      /* Find the highest-addressed object that CALLER is not below.  */
-      match = NULL;
-      for (l = _dl_loaded; l; l = l->l_next)
-       if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
-         match = l;
-
       if (handle != RTLD_NEXT)
        {
          /* Search the scope of the given object.  */
@@ -58,7 +57,7 @@ _dl_sym (void *handle, const char *name, void *who)
            match = _dl_loaded;
 
          result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
-                                     0);
+                                     0, 1);
        }
       else
        {
@@ -88,6 +87,9 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
   const ElfW(Sym) *ref = NULL;
   struct r_found_version vers;
   lookup_t result;
+  ElfW(Addr) caller = (ElfW(Addr)) who;
+  struct link_map *match;
+  struct link_map *l;
 
   /* Compute hash value to the version string.  */
   vers.name = version;
@@ -96,22 +98,18 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
   /* We don't have a specific file where the symbol can be found.  */
   vers.filename = NULL;
 
+  /* Find the highest-addressed object that CALLER is not below.  */
+  match = NULL;
+  for (l = _dl_loaded; l; l = l->l_next)
+    if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
+      match = l;
+
   if (handle == RTLD_DEFAULT)
     /* Search the global scope.  */
-    result = _dl_lookup_versioned_symbol (name, NULL, &ref, _dl_global_scope,
-                                         &vers, 0);
+    result = _dl_lookup_versioned_symbol (name, match, &ref, _dl_global_scope,
+                                         &vers, 0, 0);
   else if (handle == RTLD_NEXT)
     {
-      struct link_map *l;
-      struct link_map *match;
-      ElfW(Addr) caller = (ElfW(Addr)) who;
-
-      /* Find the highest-addressed object that CALLER is not below.  */
-      match = NULL;
-      for (l = _dl_loaded; l; l = l->l_next)
-       if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
-         match = l;
-
       if (! match)
        _dl_signal_error (0, NULL, N_("\
 RTLD_NEXT used in code not dynamically loaded"));
@@ -129,7 +127,7 @@ RTLD_NEXT used in code not dynamically loaded"));
       /* Search the scope of the given object.  */
       struct link_map *map = handle;
       result = _dl_lookup_versioned_symbol (name, map, &ref,
-                                           map->l_local_scope, &vers, 0);
+                                           map->l_local_scope, &vers, 0, 1);
     }
 
   if (ref)
index bdd7615..5c12df7 100644 (file)
@@ -28,6 +28,6 @@ _dl_symbol_value (struct link_map *map, const char *name)
 {
   const ElfW(Sym) *ref = NULL;
   lookup_t result;
-  result = _dl_lookup_symbol (name, map, &ref, map->l_local_scope, 0);
+  result = _dl_lookup_symbol (name, map, &ref, map->l_local_scope, 0, 1);
   return (result ? LOOKUP_VALUE_ADDRESS (result) : 0) + ref->st_value;
 }
index 4511ef6..932c385 100644 (file)
    found the symbol, the value 0 if nothing is found and < 0 if
    something bad happened.  */
 static inline int
-FCT (const char *undef_name, struct link_map *undef_map,
-     unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result,
-     struct r_scope_elem *scope, size_t i, ARG struct link_map *skip,
-     int noexec, int noplt)
+FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
+     struct sym_val *result, struct r_scope_elem *scope, size_t i, ARG
+     struct link_map *skip, int noexec, int noplt)
 {
   struct link_map **list = scope->r_list;
   size_t n = scope->r_nlist;
diff --git a/elf/reldep.c b/elf/reldep.c
new file mode 100644 (file)
index 0000000..44b239b
--- /dev/null
@@ -0,0 +1,111 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  int (*fp) (void);
+  int *vp;
+
+  mtrace ();
+
+  /* Open the two objects.  */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so: %s\n", dlerror ());
+      exit (1);
+    }
+  h2 = dlopen ("reldepmod2.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldepmod2.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the address of the variable in reldepmod1.so.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  *vp = 42;
+
+  /* Get the function `call_me' in the second object.  This has a
+     dependency which is resolved by a definition in reldepmod1.so.  */
+  fp = dlsym (h2, "call_me");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of \"call_me\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Call the function.  */
+  if (fp () != 0)
+    {
+      puts ("function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the first object.  If must still be around since we have
+     a implicit dependency.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Try calling the function again.  This will fail if the first object
+     got unloaded.  */
+  if (fp () != 0)
+    {
+      puts ("second call of function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the second file as well.  */
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Finally, open the first object again.   */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* And get the variable address again.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\" the second time: %s\n",
+             dlerror ());
+      exit (1);
+    }
+
+  /* The variable now must have its originial value.  */
+  if (*vp != 0)
+    {
+      puts ("variable \"some_var\" not reset");
+      exit (1);
+    }
+
+  /* Close the first object again, we are done.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/elf/reldep2.c b/elf/reldep2.c
new file mode 100644 (file)
index 0000000..aadb0cb
--- /dev/null
@@ -0,0 +1,101 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  int (*fp) (void);
+  int *vp;
+
+  mtrace ();
+
+  /* Open the two objects.  */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so: %s\n", dlerror ());
+      exit (1);
+    }
+  h2 = dlopen ("reldepmod3.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldepmod3.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the address of the variable in reldepmod1.so.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  *vp = 42;
+
+  /* Get the function `call_me' in the second object.  This has a
+     dependency which is resolved by a definition in reldepmod1.so.  */
+  fp = dlsym (h2, "call_me");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of \"call_me\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Call the function.  */
+  if (fp () != 0)
+    {
+      puts ("function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the first object.  If must still be around since we have
+     a implicit dependency.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Open the first object again.   */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the variable address again.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\" the second time: %s\n",
+             dlerror ());
+      exit (1);
+    }
+
+  /* The variable now must have its originial value.  */
+  if (*vp != 42)
+    {
+      puts ("variable \"some_var\" reset");
+      exit (1);
+    }
+
+  /* Close the first object again, we are done.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/elf/reldep3.c b/elf/reldep3.c
new file mode 100644 (file)
index 0000000..b051c41
--- /dev/null
@@ -0,0 +1,101 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h1;
+  void *h2;
+  int (*fp) (void);
+  int *vp;
+
+  mtrace ();
+
+  /* Open the two objects.  */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so: %s\n", dlerror ());
+      exit (1);
+    }
+  h2 = dlopen ("reldepmod4.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      printf ("cannot open reldepmod4.so: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the address of the variable in reldepmod1.so.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  *vp = 42;
+
+  /* Get the function `call_me' in the second object.  This has a
+     dependency which is resolved by a definition in reldepmod1.so.  */
+  fp = dlsym (h2, "call_me");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of \"call_me\": %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Call the function.  */
+  if (fp () != 0)
+    {
+      puts ("function \"call_me\" returned wrong result");
+      exit (1);
+    }
+
+  /* Now close the first object.  If must still be around since we have
+     a implicit dependency.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Open the first object again.   */
+  h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (h1 == NULL)
+    {
+      printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ());
+      exit (1);
+    }
+
+  /* Get the variable address again.  */
+  vp = dlsym (h1, "some_var");
+  if (vp == NULL)
+    {
+      printf ("cannot get address of \"some_var\" the second time: %s\n",
+             dlerror ());
+      exit (1);
+    }
+
+  /* The variable now must have its originial value.  */
+  if (*vp != 0)
+    {
+      puts ("variable \"some_var\" not reset");
+      exit (1);
+    }
+
+  /* Close the first object again, we are done.  */
+  if (dlclose (h1) != 0)
+    {
+      printf ("closing h1 failed: %s\n", dlerror ());
+      exit (1);
+    }
+  if (dlclose (h2) != 0)
+    {
+      printf ("closing h2 failed: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/elf/reldepmod1.c b/elf/reldepmod1.c
new file mode 100644 (file)
index 0000000..26f67b3
--- /dev/null
@@ -0,0 +1,7 @@
+int some_var;
+
+int
+foo (void)
+{
+  return some_var;
+}
diff --git a/elf/reldepmod2.c b/elf/reldepmod2.c
new file mode 100644 (file)
index 0000000..f511755
--- /dev/null
@@ -0,0 +1,7 @@
+extern int foo (void);
+
+int
+call_me (void)
+{
+  return foo () - 42;
+}
diff --git a/elf/reldepmod3.c b/elf/reldepmod3.c
new file mode 100644 (file)
index 0000000..e56b19d
--- /dev/null
@@ -0,0 +1,17 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+
+int
+call_me (void)
+{
+  int (*fp) (void);
+
+  fp = dlsym (RTLD_DEFAULT, "foo");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of foo in global scope: %s\n", dlerror ());
+      exit (1);
+    }
+
+  return fp () - 42;
+}
diff --git a/elf/reldepmod4.c b/elf/reldepmod4.c
new file mode 100644 (file)
index 0000000..7036af8
--- /dev/null
@@ -0,0 +1,34 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+
+int
+call_me (void)
+{
+  void *h;
+  int (*fp) (void);
+  int res;
+
+  h = dlopen ("reldepmod1.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      printf ("cannot open reldepmod1.so in %s: %s\n", __FILE__, dlerror ());
+      exit (1);
+    }
+
+  fp = dlsym (h, "foo");
+  if (fp == NULL)
+    {
+      printf ("cannot get address of foo in global scope: %s\n", dlerror ());
+      exit (1);
+    }
+
+  res = fp () - 42;
+
+  if (dlclose (h) != 0)
+    {
+      printf ("failure when closing h in %s: %s\n", __FILE__, dlerror ());
+      exit (1);
+    }
+
+  return res;
+}
index 41cf5c3..4f92844 100644 (file)
@@ -910,7 +910,7 @@ of this helper program; chances are you did not intend to run this program.\n\
 
            result = _dl_lookup_symbol (_dl_argv[i], _dl_loaded,
                                        &ref, _dl_loaded->l_scope,
-                                       ELF_MACHINE_JMP_SLOT);
+                                       ELF_MACHINE_JMP_SLOT, 1);
 
            loadbase = LOOKUP_VALUE_ADDRESS (result);
 
diff --git a/elf/unload.c b/elf/unload.c
new file mode 100644 (file)
index 0000000..2789abd
--- /dev/null
@@ -0,0 +1,65 @@
+/* Test for unloading (really unmapping) of objects.  By Franz Sirl.
+   This test does not have to passed in all dlopen() et.al. implementation
+   since it is not required the unloading actually happens.  But we
+   require it for glibc.  */
+
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct
+{
+  void *next;
+} strct;
+
+int
+main (void)
+{
+   void *sohandle;
+   strct *testdat;
+   int ret;
+   int result = 0;
+
+   mtrace ();
+
+   sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL);
+   if (sohandle == NULL)
+     {
+       printf ("first dlopen failed: %s\n", dlerror ());
+       exit (1);
+     }
+
+   testdat = dlsym (sohandle, "testdat");
+   testdat->next = (void *) -1;
+
+   ret = dlclose (sohandle);
+   if (ret != 0)
+     {
+       puts ("first dlclose failed");
+       result = 1;
+     }
+
+   sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL);
+   if (sohandle == NULL)
+     {
+       printf ("second dlopen failed: %s\n", dlerror ());
+       exit (1);
+     }
+
+   testdat = dlsym (sohandle, "testdat");
+   if (testdat->next == (void *) -1)
+     {
+       puts ("testdat->next == (void *) -1");
+       result = 1;
+     }
+
+   ret = dlclose (sohandle);
+   if (ret != 0)
+     {
+       puts ("second dlclose failed");
+       result = 1;
+     }
+
+   return result;
+}
diff --git a/elf/unloadmod.c b/elf/unloadmod.c
new file mode 100644 (file)
index 0000000..3aa5403
--- /dev/null
@@ -0,0 +1,4 @@
+struct testdat
+{
+  void *next;
+} testdat;
index ceb2b87..4cb4472 100644 (file)
@@ -307,7 +307,7 @@ extern lookup_t _dl_lookup_symbol (const char *undef,
                                   struct link_map *undef_map,
                                   const ElfW(Sym) **sym,
                                   struct r_scope_elem *symbol_scope[],
-                                  int reloc_type)
+                                  int reloc_type, int explicit)
      internal_function;
 
 /* Lookup versioned symbol.  */
@@ -316,7 +316,7 @@ extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
                                             const ElfW(Sym) **sym,
                                             struct r_scope_elem *symbol_scope[],
                                             const struct r_found_version *version,
-                                            int reloc_type)
+                                            int reloc_type, int explicit)
      internal_function;
 
 /* For handling RTLD_NEXT we must be able to skip shared objects.  */