summaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-08-26 23:41:19 +0000
committerUlrich Drepper <drepper@redhat.com>2000-08-26 23:41:19 +0000
commit2b7238dda8a0675577701d59f655029c55c60bfe (patch)
tree1c3bd9a230657021690ce38bfff4bbb42164f209 /elf
parent36466e64f0f8cbf1a915070f3f071b9360926cae (diff)
Update.
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.
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile26
-rw-r--r--elf/dl-libc.c2
-rw-r--r--elf/dl-lookup.c149
-rw-r--r--elf/dl-reloc.c8
-rw-r--r--elf/dl-runtime.c9
-rw-r--r--elf/dl-sym.c48
-rw-r--r--elf/dl-symbol.c2
-rw-r--r--elf/do-lookup.h7
-rw-r--r--elf/reldep.c111
-rw-r--r--elf/reldep2.c101
-rw-r--r--elf/reldep3.c101
-rw-r--r--elf/reldepmod1.c7
-rw-r--r--elf/reldepmod2.c7
-rw-r--r--elf/reldepmod3.c17
-rw-r--r--elf/reldepmod4.c34
-rw-r--r--elf/rtld.c2
-rw-r--r--elf/unload.c65
-rw-r--r--elf/unloadmod.c4
18 files changed, 545 insertions, 155 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 369aaba693..9f9fef99bc 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -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
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index 8518909b25..7d2b3608b2 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -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
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index f1ec98e74b..2b58ff32aa 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -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)
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index f840f3c802..643885e95b 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -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"
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 57746092f1..01beb19633 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -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)
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index e54ed808b2..873865698c 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -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)
diff --git a/elf/dl-symbol.c b/elf/dl-symbol.c
index bdd7615e48..5c12df7bff 100644
--- a/elf/dl-symbol.c
+++ b/elf/dl-symbol.c
@@ -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;
}
diff --git a/elf/do-lookup.h b/elf/do-lookup.h
index 4511ef6289..932c385168 100644
--- a/elf/do-lookup.h
+++ b/elf/do-lookup.h
@@ -29,10 +29,9 @@
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
index 0000000000..44b239b6c7
--- /dev/null
+++ b/elf/reldep.c
@@ -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
index 0000000000..aadb0cbfdb
--- /dev/null
+++ b/elf/reldep2.c
@@ -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
index 0000000000..b051c41dbc
--- /dev/null
+++ b/elf/reldep3.c
@@ -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
index 0000000000..26f67b3d0d
--- /dev/null
+++ b/elf/reldepmod1.c
@@ -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
index 0000000000..f511755444
--- /dev/null
+++ b/elf/reldepmod2.c
@@ -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
index 0000000000..e56b19d499
--- /dev/null
+++ b/elf/reldepmod3.c
@@ -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
index 0000000000..7036af832e
--- /dev/null
+++ b/elf/reldepmod4.c
@@ -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;
+}
diff --git a/elf/rtld.c b/elf/rtld.c
index 41cf5c36d5..4f92844e54 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -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
index 0000000000..2789abd5bb
--- /dev/null
+++ b/elf/unload.c
@@ -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
index 0000000000..3aa5403edf
--- /dev/null
+++ b/elf/unloadmod.c
@@ -0,0 +1,4 @@
+struct testdat
+{
+ void *next;
+} testdat;