mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 13:30:06 +00:00
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.
This commit is contained in:
parent
36466e64f0
commit
2b7238dda8
43
ChangeLog
43
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>
|
2000-08-25 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* iconv/gconv_trans.c (__gconv_transliterate): Pass NULL instead of
|
* iconv/gconv_trans.c (__gconv_transliterate): Pass NULL instead of
|
||||||
|
26
elf/Makefile
26
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 \
|
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 \
|
do-lookup.h dl-lookupcfg.h sprof.c gen-trusted-dirs.awk \
|
||||||
testobj1.c testobj2.c testobj3.c testobj4.c testobj5.c \
|
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 \
|
ldconfig.h ldconfig.c cache.c readlib.c readelflib.c \
|
||||||
dep1.c dep2.c dep3.c dep4.c dl-dtprocnum.h \
|
dep1.c dep2.c dep3.c dep4.c dl-dtprocnum.h \
|
||||||
vismain.c vismod1.c vismod2.c vismod3.c \
|
vismain.c vismod1.c vismod2.c vismod3.c \
|
||||||
constload2.c constload3.c filtmod1.c filtmod2.c \
|
constload2.c constload3.c filtmod1.c filtmod2.c \
|
||||||
nodlopenmod.c nodelete.c nodelmod1.c nodelmod2.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
|
include ../Makeconfig
|
||||||
|
|
||||||
@ -87,18 +88,19 @@ endif
|
|||||||
|
|
||||||
ifeq (yes,$(build-shared))
|
ifeq (yes,$(build-shared))
|
||||||
tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
constload1 order $(tests-vis-$(have-protected)) noload filter \
|
constload1 order $(tests-vis-$(have-protected)) noload filter unload \
|
||||||
$(tests-nodelete-$(have-z-nodelete)) \
|
reldep reldep2 reldep3 $(tests-nodelete-$(have-z-nodelete)) \
|
||||||
$(tests-nodlopen-$(have-z-nodlopen))
|
$(tests-nodlopen-$(have-z-nodlopen))
|
||||||
tests-vis-yes = vismain
|
tests-vis-yes = vismain
|
||||||
tests-nodelete-yes = nodelete
|
tests-nodelete-yes = nodelete
|
||||||
tests-nodlopen-yes = nodlopen
|
tests-nodlopen-yes = nodlopen
|
||||||
endif
|
endif
|
||||||
modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
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)) \
|
dep1 dep2 dep3 dep4 $(modules-vis-$(have-protected)) \
|
||||||
$(modules-nodelete-$(have-z-nodelete)) \
|
$(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-vis-yes = vismod1 vismod2 vismod3
|
||||||
modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
|
modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
|
||||||
modules-nodlopen-yes = nodlopenmod
|
modules-nodlopen-yes = nodlopenmod
|
||||||
@ -319,3 +321,15 @@ $(objpfx)filtmod1.so: $(objpfx)filtmod1.os $(objpfx)filtmod2.so
|
|||||||
-Wl,-rpath-link=$(rpath-link) \
|
-Wl,-rpath-link=$(rpath-link) \
|
||||||
$< -Wl,-F,$(objpfx)filtmod2.so
|
$< -Wl,-F,$(objpfx)filtmod2.so
|
||||||
$(objpfx)filter: $(objpfx)filtmod1.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
|
||||||
|
@ -84,7 +84,7 @@ do_dlsym (void *ptr)
|
|||||||
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
|
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
|
||||||
args->ref = NULL;
|
args->ref = NULL;
|
||||||
args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref,
|
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
|
static void
|
||||||
|
143
elf/dl-lookup.c
143
elf/dl-lookup.c
@ -190,7 +190,7 @@ lookup_t
|
|||||||
internal_function
|
internal_function
|
||||||
_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
||||||
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
|
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 char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
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. */
|
/* Search the relevant loaded objects for a definition. */
|
||||||
for (scope = symbol_scope; *scope; ++scope)
|
for (scope = symbol_scope; *scope; ++scope)
|
||||||
if (do_lookup (undef_name, undef_map, hash, *ref, ¤t_value,
|
if (do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0, NULL,
|
||||||
*scope, 0, NULL, noexec, noplt))
|
noexec, noplt))
|
||||||
{
|
{
|
||||||
/* We have to check whether this would bind UNDEF_MAP to an object
|
/* We have to check whether this would bind UNDEF_MAP to an object
|
||||||
in the global scope which was dynamically loaded. In this case
|
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)
|
&& (__builtin_expect (current_value.m->l_type, lt_library)
|
||||||
== lt_loaded)
|
== lt_loaded)
|
||||||
&& undef_map != current_value.m
|
&& 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 UNDEF_MAP to the dependencies. */
|
||||||
&& add_dependency (undef_map, current_value.m) < 0)
|
&& add_dependency (undef_map, current_value.m) < 0)
|
||||||
/* Something went wrong. Perhaps the object we tried to reference
|
/* Something went wrong. Perhaps the object we tried to reference
|
||||||
was just removed. Try finding another definition. */
|
was just removed. Try finding another definition. */
|
||||||
return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
|
return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
|
||||||
reloc_type);
|
reloc_type, 0);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -262,8 +265,8 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
|||||||
struct sym_val protected_value = { NULL, NULL };
|
struct sym_val protected_value = { NULL, NULL };
|
||||||
|
|
||||||
for (scope = symbol_scope; *scope; ++scope)
|
for (scope = symbol_scope; *scope; ++scope)
|
||||||
if (do_lookup (undef_name, undef_map, hash, *ref,
|
if (do_lookup (undef_name, hash, *ref, &protected_value, *scope, 0,
|
||||||
&protected_value, *scope, 0, NULL, 0, 1))
|
NULL, 0, 1))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
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)
|
for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
|
||||||
assert (i < (*scope)->r_nduplist);
|
assert (i < (*scope)->r_nduplist);
|
||||||
|
|
||||||
if (i < (*scope)->r_nlist
|
while (i >= (*scope)->r_nlist
|
||||||
&& do_lookup (undef_name, undef_map, hash, *ref, ¤t_value,
|
|| ! do_lookup (undef_name, hash, *ref, ¤t_value, *scope, i,
|
||||||
*scope, i, skip_map, 0, 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 (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 (*++scope)
|
while (*++scope)
|
||||||
if (do_lookup (undef_name, undef_map, hash, *ref, ¤t_value,
|
if (do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0,
|
||||||
*scope, 0, skip_map, 0, 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;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (__builtin_expect (current_value.s == NULL, 0))
|
if (__builtin_expect (current_value.s == NULL, 0))
|
||||||
{
|
{
|
||||||
@ -371,15 +340,15 @@ _dl_lookup_symbol_skip (const char *undef_name,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* It is very tricky. We need to figure out what value to
|
/* 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 };
|
struct sym_val protected_value = { NULL, NULL };
|
||||||
|
|
||||||
if (i >= (*scope)->r_nlist
|
if (i >= (*scope)->r_nlist
|
||||||
|| !do_lookup (undef_name, undef_map, hash, *ref, &protected_value,
|
|| !do_lookup (undef_name, hash, *ref, &protected_value, *scope, i,
|
||||||
*scope, i, skip_map, 0, 1))
|
skip_map, 0, 1))
|
||||||
while (*++scope)
|
while (*++scope)
|
||||||
if (do_lookup (undef_name, undef_map, hash, *ref, &protected_value,
|
if (do_lookup (undef_name, hash, *ref, &protected_value, *scope, 0,
|
||||||
*scope, 0, skip_map, 0, 1))
|
skip_map, 0, 1))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
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 link_map *undef_map, const ElfW(Sym) **ref,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const struct r_found_version *version,
|
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 char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
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. */
|
/* Search the relevant loaded objects for a definition. */
|
||||||
for (scope = symbol_scope; *scope; ++scope)
|
for (scope = symbol_scope; *scope; ++scope)
|
||||||
{
|
{
|
||||||
int res = do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
int res = do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
|
||||||
¤t_value, *scope, 0, version, NULL,
|
*scope, 0, version, NULL, noexec, noplt);
|
||||||
noexec, noplt);
|
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
{
|
{
|
||||||
/* We have to check whether this would bind UNDEF_MAP to an object
|
/* 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)
|
&& (__builtin_expect (current_value.m->l_type, lt_library)
|
||||||
== lt_loaded)
|
== lt_loaded)
|
||||||
&& undef_map != current_value.m
|
&& 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 UNDEF_MAP to the dependencies. */
|
||||||
&& add_dependency (undef_map, current_value.m) < 0)
|
&& add_dependency (undef_map, current_value.m) < 0)
|
||||||
/* Something went wrong. Perhaps the object we tried to reference
|
/* Something went wrong. Perhaps the object we tried to reference
|
||||||
was just removed. Try finding another definition. */
|
was just removed. Try finding another definition. */
|
||||||
return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
|
return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
|
||||||
symbol_scope, version,
|
symbol_scope, version,
|
||||||
reloc_type);
|
reloc_type, 0);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -502,9 +473,8 @@ _dl_lookup_versioned_symbol (const char *undef_name,
|
|||||||
struct sym_val protected_value = { NULL, NULL };
|
struct sym_val protected_value = { NULL, NULL };
|
||||||
|
|
||||||
for (scope = symbol_scope; *scope; ++scope)
|
for (scope = symbol_scope; *scope; ++scope)
|
||||||
if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
if (do_lookup_versioned (undef_name, hash, *ref, &protected_value,
|
||||||
&protected_value, *scope, 0, version, NULL,
|
*scope, 0, version, NULL, 0, 1))
|
||||||
0, 1))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
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)
|
for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
|
||||||
assert (i < (*scope)->r_nduplist);
|
assert (i < (*scope)->r_nduplist);
|
||||||
|
|
||||||
if (i < (*scope)->r_nlist
|
if (i >= (*scope)->r_nlist
|
||||||
&& do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
|| ! do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
|
||||||
¤t_value, *scope, i, version, skip_map,
|
*scope, i, version, skip_map, 0, 0))
|
||||||
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
|
|
||||||
while (*++scope)
|
while (*++scope)
|
||||||
if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
if (do_lookup_versioned (undef_name, hash, *ref, ¤t_value, *scope,
|
||||||
¤t_value, *scope, 0, version, skip_map,
|
0, version, skip_map, 0, 0))
|
||||||
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;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (__builtin_expect (current_value.s == NULL, 0))
|
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 };
|
struct sym_val protected_value = { NULL, NULL };
|
||||||
|
|
||||||
if (i >= (*scope)->r_nlist
|
if (i >= (*scope)->r_nlist
|
||||||
|| !do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
|| !do_lookup_versioned (undef_name, hash, *ref, &protected_value,
|
||||||
&protected_value, *scope, i, version,
|
*scope, i, version, skip_map, 0, 1))
|
||||||
skip_map, 0, 1))
|
|
||||||
while (*++scope)
|
while (*++scope)
|
||||||
if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
if (do_lookup_versioned (undef_name, hash, *ref, &protected_value,
|
||||||
&protected_value, *scope, 0, version,
|
*scope, 0, version, skip_map, 0, 1))
|
||||||
skip_map, 0, 1))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
if (protected_value.s == NULL || protected_value.m == undef_map)
|
||||||
|
@ -75,17 +75,17 @@ cannot make segment writable for relocation"));
|
|||||||
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
||||||
? ((version) != NULL && (version)->hash != 0 \
|
? ((version) != NULL && (version)->hash != 0 \
|
||||||
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref), \
|
? _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, \
|
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope, \
|
||||||
(flags))) \
|
(flags), 0)) \
|
||||||
: l)
|
: l)
|
||||||
#define RESOLVE(ref, version, flags) \
|
#define RESOLVE(ref, version, flags) \
|
||||||
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
||||||
? ((version) != NULL && (version)->hash != 0 \
|
? ((version) != NULL && (version)->hash != 0 \
|
||||||
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref), \
|
? _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, \
|
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope, \
|
||||||
(flags))) \
|
(flags), 0)) \
|
||||||
: l->l_addr)
|
: l->l_addr)
|
||||||
|
|
||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
|
@ -89,13 +89,13 @@ fixup (
|
|||||||
result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
|
result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
|
||||||
l, &sym, l->l_scope,
|
l, &sym, l->l_scope,
|
||||||
version,
|
version,
|
||||||
ELF_MACHINE_JMP_SLOT);
|
ELF_MACHINE_JMP_SLOT, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 0:
|
case 0:
|
||||||
result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
|
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)
|
/* 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,
|
result = _dl_lookup_versioned_symbol(strtab + sym->st_name,
|
||||||
l, &sym, l->l_scope,
|
l, &sym, l->l_scope,
|
||||||
version,
|
version,
|
||||||
ELF_MACHINE_JMP_SLOT);
|
ELF_MACHINE_JMP_SLOT,
|
||||||
|
0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 0:
|
case 0:
|
||||||
result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
|
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)
|
/* Currently result contains the base load address (or link map)
|
||||||
|
38
elf/dl-sym.c
38
elf/dl-sym.c
@ -31,15 +31,9 @@ _dl_sym (void *handle, const char *name, void *who)
|
|||||||
{
|
{
|
||||||
const ElfW(Sym) *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
lookup_t result;
|
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;
|
ElfW(Addr) caller = (ElfW(Addr)) who;
|
||||||
|
struct link_map *match;
|
||||||
|
struct link_map *l;
|
||||||
|
|
||||||
/* Find the highest-addressed object that CALLER is not below. */
|
/* Find the highest-addressed object that CALLER is not below. */
|
||||||
match = NULL;
|
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))
|
if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
|
||||||
match = l;
|
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)
|
if (handle != RTLD_NEXT)
|
||||||
{
|
{
|
||||||
/* Search the scope of the given object. */
|
/* Search the scope of the given object. */
|
||||||
@ -58,7 +57,7 @@ _dl_sym (void *handle, const char *name, void *who)
|
|||||||
match = _dl_loaded;
|
match = _dl_loaded;
|
||||||
|
|
||||||
result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
|
result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
|
||||||
0);
|
0, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -88,6 +87,9 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
|
|||||||
const ElfW(Sym) *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
struct r_found_version vers;
|
struct r_found_version vers;
|
||||||
lookup_t result;
|
lookup_t result;
|
||||||
|
ElfW(Addr) caller = (ElfW(Addr)) who;
|
||||||
|
struct link_map *match;
|
||||||
|
struct link_map *l;
|
||||||
|
|
||||||
/* Compute hash value to the version string. */
|
/* Compute hash value to the version string. */
|
||||||
vers.name = version;
|
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. */
|
/* We don't have a specific file where the symbol can be found. */
|
||||||
vers.filename = NULL;
|
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. */
|
/* Find the highest-addressed object that CALLER is not below. */
|
||||||
match = NULL;
|
match = NULL;
|
||||||
for (l = _dl_loaded; l; l = l->l_next)
|
for (l = _dl_loaded; l; l = l->l_next)
|
||||||
if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
|
if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
|
||||||
match = l;
|
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)
|
if (! match)
|
||||||
_dl_signal_error (0, NULL, N_("\
|
_dl_signal_error (0, NULL, N_("\
|
||||||
RTLD_NEXT used in code not dynamically loaded"));
|
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. */
|
/* Search the scope of the given object. */
|
||||||
struct link_map *map = handle;
|
struct link_map *map = handle;
|
||||||
result = _dl_lookup_versioned_symbol (name, map, &ref,
|
result = _dl_lookup_versioned_symbol (name, map, &ref,
|
||||||
map->l_local_scope, &vers, 0);
|
map->l_local_scope, &vers, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ref)
|
if (ref)
|
||||||
|
@ -28,6 +28,6 @@ _dl_symbol_value (struct link_map *map, const char *name)
|
|||||||
{
|
{
|
||||||
const ElfW(Sym) *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
lookup_t result;
|
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;
|
return (result ? LOOKUP_VALUE_ADDRESS (result) : 0) + ref->st_value;
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,9 @@
|
|||||||
found the symbol, the value 0 if nothing is found and < 0 if
|
found the symbol, the value 0 if nothing is found and < 0 if
|
||||||
something bad happened. */
|
something bad happened. */
|
||||||
static inline int
|
static inline int
|
||||||
FCT (const char *undef_name, struct link_map *undef_map,
|
FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
|
||||||
unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result,
|
struct sym_val *result, struct r_scope_elem *scope, size_t i, ARG
|
||||||
struct r_scope_elem *scope, size_t i, ARG struct link_map *skip,
|
struct link_map *skip, int noexec, int noplt)
|
||||||
int noexec, int noplt)
|
|
||||||
{
|
{
|
||||||
struct link_map **list = scope->r_list;
|
struct link_map **list = scope->r_list;
|
||||||
size_t n = scope->r_nlist;
|
size_t n = scope->r_nlist;
|
||||||
|
111
elf/reldep.c
Normal file
111
elf/reldep.c
Normal 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
101
elf/reldep2.c
Normal 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
101
elf/reldep3.c
Normal 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
7
elf/reldepmod1.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
int some_var;
|
||||||
|
|
||||||
|
int
|
||||||
|
foo (void)
|
||||||
|
{
|
||||||
|
return some_var;
|
||||||
|
}
|
7
elf/reldepmod2.c
Normal file
7
elf/reldepmod2.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
extern int foo (void);
|
||||||
|
|
||||||
|
int
|
||||||
|
call_me (void)
|
||||||
|
{
|
||||||
|
return foo () - 42;
|
||||||
|
}
|
17
elf/reldepmod3.c
Normal file
17
elf/reldepmod3.c
Normal 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
34
elf/reldepmod4.c
Normal 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;
|
||||||
|
}
|
@ -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,
|
result = _dl_lookup_symbol (_dl_argv[i], _dl_loaded,
|
||||||
&ref, _dl_loaded->l_scope,
|
&ref, _dl_loaded->l_scope,
|
||||||
ELF_MACHINE_JMP_SLOT);
|
ELF_MACHINE_JMP_SLOT, 1);
|
||||||
|
|
||||||
loadbase = LOOKUP_VALUE_ADDRESS (result);
|
loadbase = LOOKUP_VALUE_ADDRESS (result);
|
||||||
|
|
||||||
|
65
elf/unload.c
Normal file
65
elf/unload.c
Normal 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
4
elf/unloadmod.c
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
struct testdat
|
||||||
|
{
|
||||||
|
void *next;
|
||||||
|
} testdat;
|
@ -307,7 +307,7 @@ extern lookup_t _dl_lookup_symbol (const char *undef,
|
|||||||
struct link_map *undef_map,
|
struct link_map *undef_map,
|
||||||
const ElfW(Sym) **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
int reloc_type)
|
int reloc_type, int explicit)
|
||||||
internal_function;
|
internal_function;
|
||||||
|
|
||||||
/* Lookup versioned symbol. */
|
/* Lookup versioned symbol. */
|
||||||
@ -316,7 +316,7 @@ extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
|
|||||||
const ElfW(Sym) **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const struct r_found_version *version,
|
const struct r_found_version *version,
|
||||||
int reloc_type)
|
int reloc_type, int explicit)
|
||||||
internal_function;
|
internal_function;
|
||||||
|
|
||||||
/* For handling RTLD_NEXT we must be able to skip shared objects. */
|
/* For handling RTLD_NEXT we must be able to skip shared objects. */
|
||||||
|
Loading…
Reference in New Issue
Block a user