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.
This commit is contained in:
Ulrich Drepper 2000-08-26 23:41:19 +00:00
parent 36466e64f0
commit 2b7238dda8
20 changed files with 590 additions and 157 deletions

View File

@ -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

View 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

View 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

View 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);
if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
skip_map, 0, 0))
break;
}
if (__builtin_expect (current_value.s == NULL, 0))
{
@ -371,15 +340,15 @@ _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 */
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);
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)

View 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"

View 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)

View File

@ -31,15 +31,9 @@ _dl_sym (void *handle, const char *name, void *who)
{
const ElfW(Sym) *ref = NULL;
lookup_t result;
if (handle == RTLD_DEFAULT)
/* Search the global scope. */
result = _dl_lookup_symbol (name, NULL, &ref, _dl_global_scope, 0);
else
{
struct link_map *l;
struct link_map *match;
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;
@ -47,6 +41,11 @@ _dl_sym (void *handle, const char *name, void *who)
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, match, &ref, _dl_global_scope, 0, 0);
else
{
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;
if (handle == RTLD_DEFAULT)
/* Search the global scope. */
result = _dl_lookup_versioned_symbol (name, NULL, &ref, _dl_global_scope,
&vers, 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 (handle == RTLD_DEFAULT)
/* Search the global scope. */
result = _dl_lookup_versioned_symbol (name, match, &ref, _dl_global_scope,
&vers, 0, 0);
else if (handle == RTLD_NEXT)
{
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)

View 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;
}

View File

@ -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;

111
elf/reldep.c Normal file
View File

@ -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;
}

101
elf/reldep2.c Normal file
View File

@ -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;
}

101
elf/reldep3.c Normal file
View File

@ -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;
}

7
elf/reldepmod1.c Normal file
View File

@ -0,0 +1,7 @@
int some_var;
int
foo (void)
{
return some_var;
}

7
elf/reldepmod2.c Normal file
View File

@ -0,0 +1,7 @@
extern int foo (void);
int
call_me (void)
{
return foo () - 42;
}

17
elf/reldepmod3.c Normal file
View File

@ -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;
}

34
elf/reldepmod4.c Normal file
View File

@ -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;
}

View 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);

65
elf/unload.c Normal file
View File

@ -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;
}

4
elf/unloadmod.c Normal file
View File

@ -0,0 +1,4 @@
struct testdat
{
void *next;
} testdat;

View 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. */