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>
|
||||
|
||||
* 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 \
|
||||
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
|
||||
|
@ -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
|
||||
|
149
elf/dl-lookup.c
149
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, ¤t_value,
|
||||
*scope, 0, NULL, noexec, noplt))
|
||||
if (do_lookup (undef_name, hash, *ref, ¤t_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, ¤t_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, ¤t_value, *scope, i,
|
||||
skip_map, 0, 0))
|
||||
while (*++scope)
|
||||
if (do_lookup (undef_name, undef_map, hash, *ref, ¤t_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, ¤t_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,
|
||||
¤t_value, *scope, 0, version, NULL,
|
||||
noexec, noplt);
|
||||
int res = do_lookup_versioned (undef_name, hash, *ref, ¤t_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,
|
||||
¤t_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, ¤t_value,
|
||||
*scope, i, version, skip_map, 0, 0))
|
||||
while (*++scope)
|
||||
if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
||||
¤t_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, ¤t_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)
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
48
elf/dl-sym.c
48
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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
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,
|
||||
&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
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,
|
||||
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. */
|
||||
|
Loading…
Reference in New Issue
Block a user