mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-03 08:11:08 +00:00
Implement STB_GNU_UNIQUE handling.
Some symbols have to be identified process-wide by their name. This is particularly important for some C++ features (e.g., class local static data and static variables in inline functions). This cannot completely be implemented with ELF functionality so far. The STB_GNU_UNIQUE binding helps by ensuring the dynamic linker will always use the same definition for all symbols with the same name and this binding.
This commit is contained in:
parent
b4f55afd03
commit
415ac3df9b
24
ChangeLog
24
ChangeLog
@ -1,3 +1,25 @@
|
|||||||
|
2009-07-09 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* configure.in: Check for gnu_unique_symbol symbol type.
|
||||||
|
* config.h.in: Add HAVE_ASM_UNIQUE_OBJECT entry.
|
||||||
|
* elf/do-lookup.h (do_lookup_x): Take new parameter with link map of
|
||||||
|
the undefined symbol. Handle STB_GNU_UNIQUE binding of found symbol.
|
||||||
|
* elf/dl-lookup.c (_dl_lookup_symbol_x): Adjust callers for do_lookup_x
|
||||||
|
change.
|
||||||
|
* sysdeps/generic/ldsodefs.h (struct rtld_global): Add definitions for
|
||||||
|
unique symbol table.
|
||||||
|
* elf/rtld.c (rtld_global): Initialize lock of unique symbol hash table
|
||||||
|
for first namespace.
|
||||||
|
* elf/dl-open.c (_dl_open): For new namespace, initialize lock for
|
||||||
|
unique symbol hash table.
|
||||||
|
* elf/Makefile: Add rules to build and run tst-unique1 and tst-unique2.
|
||||||
|
* elf/tst-unique1.c: New file.
|
||||||
|
* elf/tst-unique1mod1.c: New file.
|
||||||
|
* elf/tst-unique1mod2.c: New file.
|
||||||
|
* elf/tst-unique2.c: New file.
|
||||||
|
* elf/tst-unique2mod1.c: New file.
|
||||||
|
* elf/tst-unique2mod2.c: New file.
|
||||||
|
|
||||||
2009-07-07 Ulrich Drepper <drepper@redhat.com>
|
2009-07-07 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* elf/elf.h (STB_GNU_UNIQUE): Define.
|
* elf/elf.h (STB_GNU_UNIQUE): Define.
|
||||||
@ -9,7 +31,7 @@
|
|||||||
|
|
||||||
2009-07-06 Ulrich Drepper <drepper@redhat.com>
|
2009-07-06 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* elf/do-lookup.h (ALLOWED_STT): Optimize test for valid symbol types.
|
* elf/do-lookup.h (do_lookup_x): Optimize test for valid symbol types.
|
||||||
|
|
||||||
2009-07-03 Andreas Schwab <aschwab@redhat.com>
|
2009-07-03 Andreas Schwab <aschwab@redhat.com>
|
||||||
|
|
||||||
|
@ -59,6 +59,9 @@
|
|||||||
assembler's `.type' directive, if it has one. */
|
assembler's `.type' directive, if it has one. */
|
||||||
#undef ASM_TYPE_DIRECTIVE_PREFIX
|
#undef ASM_TYPE_DIRECTIVE_PREFIX
|
||||||
|
|
||||||
|
/* Define if the assembler supports the gnu_unique_object symbol type. */
|
||||||
|
#undef HAVE_ASM_UNIQUE_OBJECT
|
||||||
|
|
||||||
/* Define a symbol_name as a global .symbol_name for ld. */
|
/* Define a symbol_name as a global .symbol_name for ld. */
|
||||||
#undef HAVE_ASM_GLOBAL_DOT_NAME
|
#undef HAVE_ASM_GLOBAL_DOT_NAME
|
||||||
|
|
||||||
|
26
configure
vendored
26
configure
vendored
@ -5994,6 +5994,32 @@ _ACEOF
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:$LINENO: checking for assembler gnu_unique_object symbol type" >&5
|
||||||
|
$as_echo_n "checking for assembler gnu_unique_object symbol type... " >&6; }
|
||||||
|
if test "${libc_cv_asm_unique_object+set}" = set; then
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
cat > conftest.s <<EOF
|
||||||
|
${libc_cv_dot_text}
|
||||||
|
_sym:
|
||||||
|
.type _sym, ${libc_cv_asm_type_prefix}gnu_unique_object
|
||||||
|
EOF
|
||||||
|
if ${CC-cc} -c $ASFLAGS conftest.s 1>&5 2>&5; then
|
||||||
|
libc_cv_asm_unique_object=yes
|
||||||
|
else
|
||||||
|
libc_cv_asm_unique_object=no
|
||||||
|
fi
|
||||||
|
rm -f conftest*
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:$LINENO: result: $libc_cv_asm_unique_object" >&5
|
||||||
|
$as_echo "$libc_cv_asm_unique_object" >&6; }
|
||||||
|
if test $libc_cv_asm_unique_object = yes; then
|
||||||
|
cat >>confdefs.h <<\_ACEOF
|
||||||
|
#define HAVE_ASM_UNIQUE_OBJECT 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
# For the multi-arch option we need support in the assembler.
|
# For the multi-arch option we need support in the assembler.
|
||||||
if test "$multi_arch" = yes; then
|
if test "$multi_arch" = yes; then
|
||||||
if test "x$libc_cv_asm_type_prefix" != xno; then
|
if test "x$libc_cv_asm_type_prefix" != xno; then
|
||||||
|
17
configure.in
17
configure.in
@ -1211,6 +1211,23 @@ if test "x$libc_cv_asm_type_prefix" != xno; then
|
|||||||
AC_DEFINE_UNQUOTED(ASM_TYPE_DIRECTIVE_PREFIX, ${libc_cv_asm_type_prefix})
|
AC_DEFINE_UNQUOTED(ASM_TYPE_DIRECTIVE_PREFIX, ${libc_cv_asm_type_prefix})
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK(for assembler gnu_unique_object symbol type,
|
||||||
|
libc_cv_asm_unique_object, [dnl
|
||||||
|
cat > conftest.s <<EOF
|
||||||
|
${libc_cv_dot_text}
|
||||||
|
_sym:
|
||||||
|
.type _sym, ${libc_cv_asm_type_prefix}gnu_unique_object
|
||||||
|
EOF
|
||||||
|
if ${CC-cc} -c $ASFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
|
||||||
|
libc_cv_asm_unique_object=yes
|
||||||
|
else
|
||||||
|
libc_cv_asm_unique_object=no
|
||||||
|
fi
|
||||||
|
rm -f conftest*])
|
||||||
|
if test $libc_cv_asm_unique_object = yes; then
|
||||||
|
AC_DEFINE(HAVE_ASM_UNIQUE_OBJECT)
|
||||||
|
fi
|
||||||
|
|
||||||
# For the multi-arch option we need support in the assembler.
|
# For the multi-arch option we need support in the assembler.
|
||||||
if test "$multi_arch" = yes; then
|
if test "$multi_arch" = yes; then
|
||||||
if test "x$libc_cv_asm_type_prefix" != xno; then
|
if test "x$libc_cv_asm_type_prefix" != xno; then
|
||||||
|
18
elf/Makefile
18
elf/Makefile
@ -111,7 +111,9 @@ distribute := rtld-Rules \
|
|||||||
ifuncdep5.c ifuncdep5pic.c ifuncmod5.c \
|
ifuncdep5.c ifuncdep5pic.c ifuncmod5.c \
|
||||||
ifuncmain6pie.c ifuncmod6.c \
|
ifuncmain6pie.c ifuncmod6.c \
|
||||||
ifuncmain7.c ifuncmain7pic.c ifuncmain7picstatic.c \
|
ifuncmain7.c ifuncmain7pic.c ifuncmain7picstatic.c \
|
||||||
ifuncmain7pie.c ifuncmain7static.c
|
ifuncmain7pie.c ifuncmain7static.c \
|
||||||
|
tst-unique1.c tst-unique1mod1.c tst-unique1mod2.c \
|
||||||
|
tst-unique2.c tst-unique2mod1.c tst-unique2mod2.c
|
||||||
|
|
||||||
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
|
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
|
||||||
CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
|
CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
|
||||||
@ -190,7 +192,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
|||||||
tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
|
tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
|
||||||
unload3 unload4 unload5 unload6 unload7 tst-global1 order2 \
|
unload3 unload4 unload5 unload6 unload7 tst-global1 order2 \
|
||||||
tst-audit1 tst-audit2 \
|
tst-audit1 tst-audit2 \
|
||||||
tst-stackguard1 tst-addr1 tst-thrlock
|
tst-stackguard1 tst-addr1 tst-thrlock \
|
||||||
|
tst-unique1 tst-unique2
|
||||||
# reldep9
|
# reldep9
|
||||||
test-srcs = tst-pathopt
|
test-srcs = tst-pathopt
|
||||||
tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
|
tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
|
||||||
@ -239,7 +242,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
|||||||
unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
|
unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
|
||||||
unload6mod1 unload6mod2 unload6mod3 \
|
unload6mod1 unload6mod2 unload6mod3 \
|
||||||
unload7mod1 unload7mod2 \
|
unload7mod1 unload7mod2 \
|
||||||
order2mod1 order2mod2 order2mod3 order2mod4
|
order2mod1 order2mod2 order2mod3 order2mod4 \
|
||||||
|
tst-unique1mod1 tst-unique1mod2 \
|
||||||
|
tst-unique2mod1 tst-unique2mod2
|
||||||
ifeq (yes,$(have-initfini-array))
|
ifeq (yes,$(have-initfini-array))
|
||||||
modules-names += tst-array2dep tst-array5dep
|
modules-names += tst-array2dep tst-array5dep
|
||||||
endif
|
endif
|
||||||
@ -1103,3 +1108,10 @@ $(objpfx)ifuncmain5pic: $(addprefix $(objpfx),ifuncmod5.so)
|
|||||||
$(objpfx)ifuncmain5static: $(addprefix $(objpfx),ifuncdep5.o)
|
$(objpfx)ifuncmain5static: $(addprefix $(objpfx),ifuncdep5.o)
|
||||||
$(objpfx)ifuncmain5staticpic: $(addprefix $(objpfx),ifuncdep5pic.o)
|
$(objpfx)ifuncmain5staticpic: $(addprefix $(objpfx),ifuncdep5pic.o)
|
||||||
$(objpfx)ifuncmain5picstatic: $(addprefix $(objpfx),ifuncdep5pic.o)
|
$(objpfx)ifuncmain5picstatic: $(addprefix $(objpfx),ifuncdep5pic.o)
|
||||||
|
|
||||||
|
$(objpfx)tst-unique1: $(libdl)
|
||||||
|
$(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \
|
||||||
|
$(objpfx)tst-unique1mod2.so
|
||||||
|
|
||||||
|
$(objpfx)tst-unique2: $(libdl) $(objpfx)tst-unique2mod1.so
|
||||||
|
$(objpfx)tst-unique2.out: $(objpfx)tst-unique2mod2.so
|
||||||
|
@ -337,7 +337,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
|||||||
{
|
{
|
||||||
int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
||||||
¤t_value, *scope, start, version, flags,
|
¤t_value, *scope, start, version, flags,
|
||||||
skip_map, type_class);
|
skip_map, type_class, undef_map);
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -410,7 +410,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
|||||||
for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
|
for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
|
||||||
if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
||||||
&protected_value, *scope, i, version, flags,
|
&protected_value, *scope, i, version, flags,
|
||||||
skip_map, ELF_RTYPE_CLASS_PLT) != 0)
|
skip_map, ELF_RTYPE_CLASS_PLT, NULL) != 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s != NULL && protected_value.m != undef_map)
|
if (protected_value.s != NULL && protected_value.m != undef_map)
|
||||||
@ -536,7 +536,7 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
|||||||
|
|
||||||
do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
|
do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
|
||||||
undef_map->l_local_scope[0], 0, version, 0, NULL,
|
undef_map->l_local_scope[0], 0, version, 0, NULL,
|
||||||
type_class);
|
type_class, undef_map);
|
||||||
|
|
||||||
if (val.s != value->s || val.m != value->m)
|
if (val.s != value->s || val.m != value->m)
|
||||||
conflict = 1;
|
conflict = 1;
|
||||||
|
@ -569,7 +569,7 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
|
|||||||
if (GL(dl_ns)[nsid]._ns_loaded == NULL)
|
if (GL(dl_ns)[nsid]._ns_loaded == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (nsid == DL_NNS)
|
if (__builtin_expect (nsid == DL_NNS, 0))
|
||||||
{
|
{
|
||||||
/* No more namespace available. */
|
/* No more namespace available. */
|
||||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||||
@ -579,7 +579,10 @@ no more namespaces available for dlmopen()"));
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nsid == GL(dl_nns))
|
if (nsid == GL(dl_nns))
|
||||||
++GL(dl_nns);
|
{
|
||||||
|
__rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
|
||||||
|
++GL(dl_nns);
|
||||||
|
}
|
||||||
|
|
||||||
_dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
|
_dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
|
||||||
}
|
}
|
||||||
|
118
elf/do-lookup.h
118
elf/do-lookup.h
@ -27,7 +27,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
|||||||
unsigned long int *old_hash, const ElfW(Sym) *ref,
|
unsigned long int *old_hash, const ElfW(Sym) *ref,
|
||||||
struct sym_val *result, struct r_scope_elem *scope, size_t i,
|
struct sym_val *result, struct r_scope_elem *scope, size_t i,
|
||||||
const struct r_found_version *const version, int flags,
|
const struct r_found_version *const version, int flags,
|
||||||
struct link_map *skip, int type_class)
|
struct link_map *skip, int type_class, struct link_map *undef_map)
|
||||||
{
|
{
|
||||||
size_t n = scope->r_nlist;
|
size_t n = scope->r_nlist;
|
||||||
/* Make sure we read the value before proceeding. Otherwise we
|
/* Make sure we read the value before proceeding. Otherwise we
|
||||||
@ -233,7 +233,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
|||||||
if (sym != NULL)
|
if (sym != NULL)
|
||||||
{
|
{
|
||||||
found_it:
|
found_it:
|
||||||
switch (ELFW(ST_BIND) (sym->st_info))
|
switch (__builtin_expect (ELFW(ST_BIND) (sym->st_info), STB_GLOBAL))
|
||||||
{
|
{
|
||||||
case STB_WEAK:
|
case STB_WEAK:
|
||||||
/* Weak definition. Use this value if we don't find another. */
|
/* Weak definition. Use this value if we don't find another. */
|
||||||
@ -248,10 +248,124 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
|||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case STB_GLOBAL:
|
case STB_GLOBAL:
|
||||||
|
success:
|
||||||
/* Global definition. Just what we need. */
|
/* Global definition. Just what we need. */
|
||||||
result->s = sym;
|
result->s = sym;
|
||||||
result->m = (struct link_map *) map;
|
result->m = (struct link_map *) map;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
case STB_GNU_UNIQUE:;
|
||||||
|
/* We have to determine whether we already found a
|
||||||
|
symbol with this name before. If not then we have to
|
||||||
|
add it to the search table. If we already found a
|
||||||
|
definition we have to use it. */
|
||||||
|
void enter (struct unique_sym *table, size_t size,
|
||||||
|
unsigned int hash, const char *name,
|
||||||
|
const ElfW(Sym) *sym, const struct link_map *map)
|
||||||
|
{
|
||||||
|
size_t idx = hash % size;
|
||||||
|
size_t hash2 = 1 + hash % (size - 2);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (table[idx].hashval == 0)
|
||||||
|
{
|
||||||
|
table[idx].hashval = hash;
|
||||||
|
table[idx].name = strtab + sym->st_name;
|
||||||
|
if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
|
||||||
|
{
|
||||||
|
table[idx].sym = ref;
|
||||||
|
table[idx].map = undef_map;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
table[idx].sym = sym;
|
||||||
|
table[idx].map = map;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx += hash2;
|
||||||
|
if (idx >= size)
|
||||||
|
idx -= size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct unique_sym_table *tab
|
||||||
|
= &GL(dl_ns)[map->l_ns]._ns_unique_sym_table;
|
||||||
|
|
||||||
|
__rtld_lock_lock_recursive (tab->lock);
|
||||||
|
|
||||||
|
struct unique_sym *entries = tab->entries;
|
||||||
|
size_t size = tab->size;
|
||||||
|
if (entries != NULL)
|
||||||
|
{
|
||||||
|
size_t idx = new_hash % size;
|
||||||
|
size_t hash2 = 1 + new_hash % (size - 2);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (entries[idx].hashval == new_hash
|
||||||
|
&& strcmp (entries[idx].name, undef_name) == 0)
|
||||||
|
{
|
||||||
|
result->s = entries[idx].sym;
|
||||||
|
result->m = (struct link_map *) entries[idx].map;
|
||||||
|
__rtld_lock_unlock_recursive (tab->lock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries[idx].hashval == 0
|
||||||
|
&& entries[idx].name == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
idx += hash2;
|
||||||
|
if (idx >= size)
|
||||||
|
idx -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size * 3 <= tab->n_elements)
|
||||||
|
{
|
||||||
|
/* Expand the table. */
|
||||||
|
size_t newsize = _dl_higher_prime_number (size);
|
||||||
|
struct unique_sym *newentries
|
||||||
|
= calloc (sizeof (struct unique_sym), newsize);
|
||||||
|
if (newentries == NULL)
|
||||||
|
{
|
||||||
|
nomem:
|
||||||
|
__rtld_lock_unlock_recursive (tab->lock);
|
||||||
|
_dl_fatal_printf ("out of memory\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx = 0; idx < size; ++idx)
|
||||||
|
if (entries[idx].hashval != 0)
|
||||||
|
enter (newentries, newsize, entries[idx].hashval,
|
||||||
|
entries[idx].name, entries[idx].sym,
|
||||||
|
entries[idx].map);
|
||||||
|
|
||||||
|
tab->free (entries);
|
||||||
|
tab->size = newsize;
|
||||||
|
entries = tab->entries = newentries;
|
||||||
|
tab->free = free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#define INITIAL_NUNIQUE_SYM_TABLE 31
|
||||||
|
size = INITIAL_NUNIQUE_SYM_TABLE;
|
||||||
|
entries = calloc (sizeof (struct unique_sym), size);
|
||||||
|
if (entries == NULL)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
|
tab->entries = entries;
|
||||||
|
tab->size = size;
|
||||||
|
tab->free = free;
|
||||||
|
}
|
||||||
|
|
||||||
|
enter (entries, size, new_hash, strtab + sym->st_name, sym, map);
|
||||||
|
++tab->n_elements;
|
||||||
|
|
||||||
|
__rtld_lock_unlock_recursive (tab->lock);
|
||||||
|
|
||||||
|
goto success;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Local symbols are ignored. */
|
/* Local symbols are ignored. */
|
||||||
break;
|
break;
|
||||||
|
@ -127,7 +127,12 @@ struct rtld_global _rtld_global =
|
|||||||
#ifdef _LIBC_REENTRANT
|
#ifdef _LIBC_REENTRANT
|
||||||
._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||||
#endif
|
#endif
|
||||||
._dl_nns = 1
|
._dl_nns = 1,
|
||||||
|
._dl_ns =
|
||||||
|
{
|
||||||
|
[LM_ID_BASE] = { ._ns_unique_sym_table
|
||||||
|
= { .lock = _RTLD_LOCK_RECURSIVE_INITIALIZER } }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
/* If we would use strong_alias here the compiler would see a
|
/* If we would use strong_alias here the compiler would see a
|
||||||
non-hidden definition. This would undo the effect of the previous
|
non-hidden definition. This would undo the effect of the previous
|
||||||
|
40
elf/tst-unique1.c
Normal file
40
elf/tst-unique1.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include <config.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_ASM_UNIQUE_OBJECT
|
||||||
|
void *h1 = dlopen ("tst-unique1mod1.so", RTLD_LAZY);
|
||||||
|
if (h1 == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot load tst-unique1mod1");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int *(*f1) (void) = dlsym (h1, "f");
|
||||||
|
if (f1 == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot locate f in tst-unique1mod1");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
void *h2 = dlopen ("tst-unique1mod2.so", RTLD_LAZY);
|
||||||
|
if (h2 == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot load tst-unique1mod2");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int (*f2) (int *) = dlsym (h2, "f");
|
||||||
|
if (f2 == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot locate f in tst-unique1mod2");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return f2 (f1 ());
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
#include "../test-skeleton.c"
|
21
elf/tst-unique1mod1.c
Normal file
21
elf/tst-unique1mod1.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_ASM_UNIQUE_OBJECT
|
||||||
|
# define S(s) _S (s)
|
||||||
|
# define _S(s) #s
|
||||||
|
|
||||||
|
asm (".data;"
|
||||||
|
S (ASM_GLOBAL_DIRECTIVE) " var\n"
|
||||||
|
".type var, " S (ASM_TYPE_DIRECTIVE_PREFIX) "gnu_unique_object\n"
|
||||||
|
".size var, 4\n"
|
||||||
|
"var:.zero 4\n"
|
||||||
|
".previous");
|
||||||
|
extern int var;
|
||||||
|
|
||||||
|
int *
|
||||||
|
f (void)
|
||||||
|
{
|
||||||
|
var = 1;
|
||||||
|
return &var;
|
||||||
|
}
|
||||||
|
#endif
|
20
elf/tst-unique1mod2.c
Normal file
20
elf/tst-unique1mod2.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_ASM_UNIQUE_OBJECT
|
||||||
|
# define S(s) _S (s)
|
||||||
|
# define _S(s) #s
|
||||||
|
|
||||||
|
asm (".data;"
|
||||||
|
S (ASM_GLOBAL_DIRECTIVE) " var\n"
|
||||||
|
".type var, " S (ASM_TYPE_DIRECTIVE_PREFIX) "gnu_unique_object\n"
|
||||||
|
".size var, 4\n"
|
||||||
|
"var:.zero 4\n"
|
||||||
|
".previous");
|
||||||
|
extern int var;
|
||||||
|
|
||||||
|
int
|
||||||
|
f (int *p)
|
||||||
|
{
|
||||||
|
return &var != p || *p != 1;
|
||||||
|
}
|
||||||
|
#endif
|
32
elf/tst-unique2.c
Normal file
32
elf/tst-unique2.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <config.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern int var;
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_ASM_UNIQUE_OBJECT
|
||||||
|
var = 1;
|
||||||
|
|
||||||
|
void *h = dlopen ("tst-unique2mod2.so", RTLD_LAZY);
|
||||||
|
if (h == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot load tst-unique2mod2");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int (*f) (int *) = dlsym (h, "f");
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot locate f in tst-unique2mod2");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return f (&var);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
#include "../test-skeleton.c"
|
13
elf/tst-unique2mod1.c
Normal file
13
elf/tst-unique2mod1.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_ASM_UNIQUE_OBJECT
|
||||||
|
# define S(s) _S (s)
|
||||||
|
# define _S(s) #s
|
||||||
|
|
||||||
|
asm (".data;"
|
||||||
|
S (ASM_GLOBAL_DIRECTIVE) " var\n"
|
||||||
|
".type var, " S (ASM_TYPE_DIRECTIVE_PREFIX) "gnu_unique_object\n"
|
||||||
|
".size var, 4\n"
|
||||||
|
"var:.zero 4\n"
|
||||||
|
".previous");
|
||||||
|
#endif
|
20
elf/tst-unique2mod2.c
Normal file
20
elf/tst-unique2mod2.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_ASM_UNIQUE_OBJECT
|
||||||
|
# define S(s) _S (s)
|
||||||
|
# define _S(s) #s
|
||||||
|
|
||||||
|
asm (".data;"
|
||||||
|
S (ASM_GLOBAL_DIRECTIVE) " var\n"
|
||||||
|
".type var, " S (ASM_TYPE_DIRECTIVE_PREFIX) "gnu_unique_object\n"
|
||||||
|
".size var, 4\n"
|
||||||
|
"var:.zero 4\n"
|
||||||
|
".previous");
|
||||||
|
extern int var;
|
||||||
|
|
||||||
|
int
|
||||||
|
f (int *p)
|
||||||
|
{
|
||||||
|
return &var != p || *p != 1;
|
||||||
|
}
|
||||||
|
#endif
|
@ -383,6 +383,21 @@ struct rtld_global
|
|||||||
allocated by rtld. Later it keeps the size of the map. It might be
|
allocated by rtld. Later it keeps the size of the map. It might be
|
||||||
reset if in _dl_close if the last global object is removed. */
|
reset if in _dl_close if the last global object is removed. */
|
||||||
size_t _ns_global_scope_alloc;
|
size_t _ns_global_scope_alloc;
|
||||||
|
/* Search table for unique objects. */
|
||||||
|
struct unique_sym_table
|
||||||
|
{
|
||||||
|
__rtld_lock_recursive_t lock;
|
||||||
|
struct unique_sym
|
||||||
|
{
|
||||||
|
uint32_t hashval;
|
||||||
|
const char *name;
|
||||||
|
const ElfW(Sym) *sym;
|
||||||
|
const struct link_map *map;
|
||||||
|
} *entries;
|
||||||
|
size_t size;
|
||||||
|
size_t n_elements;
|
||||||
|
void (*free) (void *);
|
||||||
|
} _ns_unique_sym_table;
|
||||||
/* Keep track of changes to each namespace' list. */
|
/* Keep track of changes to each namespace' list. */
|
||||||
struct r_debug _ns_debug;
|
struct r_debug _ns_debug;
|
||||||
} _dl_ns[DL_NNS];
|
} _dl_ns[DL_NNS];
|
||||||
|
Loading…
Reference in New Issue
Block a user