* elf/dl-lookup.c (dl_new_hash): New functions.

(_dl_lookup_symbol_x): Rename hash to old_hash and don't compute
	value here.  Compute new-style hash value.  Pass new hash value
	and reference to variable with the old value to do_lookup_x.
	(_dl_setup_hash): If DT_GNU_HASH is defined, use it and not
	old-style hash table.
	(_dl_debug_bindings): Pass new hash value and reference to variable
	with the old value to do_lookup_x.
	* elf/do-lookup.h (do_lookup_x): Accept additional parameter with
	new-style hash value and change old-style hash value parameter to
	be a reference.  Reoganize functions to determine whether
	new-style hash table is available.  Only fall back on old-style
	table.  If old-style hash value is needed, compute it here.
	* elf/dynamic-link.h (elf_get_dynamic_info): Relocate DT_GNU_HASH
	entry.
	* elf/elf.h: Define SHT_GNU_HASH, DT_GNU_HASH, DT_TLSDEC_PLT,
	DT_TLSDEC_GOT.  Adjust DT_ADDRNUM.
	* include/link.h (struct link_map): Add l_gnu_bitmask_idxbits,
	l_gnu_shift, l_gnu_bitmask, l_gnu_buckets and l_gnu_chain_zero.
	* Makeconfig: If linker supports --hash-style option add it to all
	linker command lines to build DSOs.
	* config.make.in: Define have-hash-style.
	* configure.in: Test whether linker supports --hash-style option.

	* elf/dl-misc.c (_dl_name_match_p): Make MAP parameter const.
	* sysdeps/generic/ldsodefs.h: Adjust prototype.
This commit is contained in:
Ulrich Drepper 2006-07-10 21:59:43 +00:00
parent f3be81a91c
commit 871b91589b
14 changed files with 315 additions and 138 deletions

View File

@ -1,3 +1,32 @@
2006-07-10 Ulrich Drepper <drepper@redhat.com>
* elf/dl-lookup.c (dl_new_hash): New functions.
(_dl_lookup_symbol_x): Rename hash to old_hash and don't compute
value here. Compute new-style hash value. Pass new hash value
and reference to variable with the old value to do_lookup_x.
(_dl_setup_hash): If DT_GNU_HASH is defined, use it and not
old-style hash table.
(_dl_debug_bindings): Pass new hash value and reference to variable
with the old value to do_lookup_x.
* elf/do-lookup.h (do_lookup_x): Accept additional parameter with
new-style hash value and change old-style hash value parameter to
be a reference. Reoganize functions to determine whether
new-style hash table is available. Only fall back on old-style
table. If old-style hash value is needed, compute it here.
* elf/dynamic-link.h (elf_get_dynamic_info): Relocate DT_GNU_HASH
entry.
* elf/elf.h: Define SHT_GNU_HASH, DT_GNU_HASH, DT_TLSDEC_PLT,
DT_TLSDEC_GOT. Adjust DT_ADDRNUM.
* include/link.h (struct link_map): Add l_gnu_bitmask_idxbits,
l_gnu_shift, l_gnu_bitmask, l_gnu_buckets and l_gnu_chain_zero.
* Makeconfig: If linker supports --hash-style option add it to all
linker command lines to build DSOs.
* config.make.in: Define have-hash-style.
* configure.in: Test whether linker supports --hash-style option.
* elf/dl-misc.c (_dl_name_match_p): Make MAP parameter const.
* sysdeps/generic/ldsodefs.h: Adjust prototype.
2006-06-27 Ulrich Drepper <drepper@redhat.com>
* elf/dl-load.c (open_path): Fix test to determine whether DSO is

View File

@ -413,11 +413,20 @@ LDFLAGS.so += $(relro-LDFLAGS)
LDFLAGS-rtld += $(relro-LDFLAGS)
endif
ifeq (yes,$(have-hash-style))
# For the time being we unconditionally use 'both'. At some time we
# should declare statically linked code as 'out of luck' and compile
# with --hash-style=gnu only.
hashstyle-LDFLAGS = -Wl,--hash-style=both
LDFLAGS.so += $(hashstyle-LDFLAGS)
LDFLAGS-rtld += $(hashstyle-LDFLAGS)
endif
# Command for linking programs with the C library.
ifndef +link
+link = $(CC) -nostdlib -nostartfiles -o $@ \
$(sysdep-LDFLAGS) $(config-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
$(combreloc-LDFLAGS) $(relro-LDFLAGS) \
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
$(addprefix $(csu-objpfx),$(start-installed-name)) \
$(+preinit) $(+prector) \
$(filter-out $(addprefix $(csu-objpfx),start.o \

6
NEWS
View File

@ -1,4 +1,4 @@
GNU C Library NEWS -- history of user-visible changes. 2006-05-24
GNU C Library NEWS -- history of user-visible changes. 2006-07-10
Copyright (C) 1992-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
See the end for copying conditions.
@ -13,7 +13,7 @@ Version 2.5
* Allow system admin to configure getaddrinfo with the /etc/gai.conf file.
Implemented by Ulrich Drepper.
* New Linux interfaces: splice, tee, sync_file_range, vmsplace.
* New Linux interfaces: splice, tee, sync_file_range, vmsplice.
* New iconv module for MIK. Contributed by Alexander Shopov.
@ -31,6 +31,8 @@ Version 2.5
* The interfaces introduced in RFC 3542 have been implemented by
Ulrich Drepper.
* Support for the new ELF hash table format was added by Ulrich Drepper.
Version 2.4

View File

@ -65,6 +65,7 @@ have-libcap = @have_libcap@
have-cc-with-libunwind = @libc_cv_cc_with_libunwind@
fno-unit-at-a-time = @fno_unit_at_a_time@
bind-now = @bindnow@
have-hash-style = @libc_cv_hashstyle@
static-libgcc = @libc_cv_gcc_static_libgcc@

30
configure vendored
View File

@ -313,7 +313,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS with_fp with_cvs enable_check_abi oldest_abi bindnow force_install all_warnings build build_cpu build_vendor build_os host host_cpu host_vendor host_os subdirs add_ons add_on_subdirs base_machine submachine sysnames sysdeps_add_ons INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT BUILD_CC cross_compiling CPP CXX CXXFLAGS ac_ct_CXX AR OBJDUMP RANLIB ac_ct_RANLIB MIG AS LD PWD_P MAKE MSGFMT MAKEINFO SED AUTOCONF SYSINCLUDES CXX_SYSINCLUDES libc_cv_gcc_static_libgcc BASH libc_cv_have_bash2 KSH libc_cv_have_ksh AWK PERL INSTALL_INFO BISON VERSIONING libc_cv_asm_protected_directive libc_cv_cc_with_libunwind libc_cv_z_nodelete libc_cv_z_nodlopen libc_cv_z_initfirst libc_cv_z_relro libc_cv_Bgroup libc_cv_libgcc_s_suffix libc_cv_as_needed ASFLAGS_config libc_cv_z_combreloc libc_cv_z_execstack libc_cv_fpie fno_unit_at_a_time libc_cv_ssp libc_cv_have_initfini no_whole_archive exceptions LIBGD have_libaudit have_libcap have_selinux EGREP sizeof_long_double libc_cv_gcc_unwind_find_fde uname_sysname uname_release uname_version old_glibc_headers libc_cv_slibdir libc_cv_localedir libc_cv_sysconfdir libc_cv_rootsbindir libc_cv_forced_unwind use_ldconfig ldd_rewrite_script elf xcoff static shared pic_default profile omitfp bounded static_nss nopic_initfini DEFINES mach_interface_list VERSION RELEASE LIBOBJS LTLIBOBJS'
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS with_fp with_cvs enable_check_abi oldest_abi bindnow force_install all_warnings build build_cpu build_vendor build_os host host_cpu host_vendor host_os subdirs add_ons add_on_subdirs base_machine submachine sysnames sysdeps_add_ons INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT BUILD_CC cross_compiling CPP CXX CXXFLAGS ac_ct_CXX AR OBJDUMP RANLIB ac_ct_RANLIB MIG AS LD PWD_P MAKE MSGFMT MAKEINFO SED AUTOCONF SYSINCLUDES CXX_SYSINCLUDES libc_cv_gcc_static_libgcc BASH libc_cv_have_bash2 KSH libc_cv_have_ksh AWK PERL INSTALL_INFO BISON VERSIONING libc_cv_asm_protected_directive libc_cv_cc_with_libunwind libc_cv_z_nodelete libc_cv_z_nodlopen libc_cv_z_initfirst libc_cv_z_relro libc_cv_Bgroup libc_cv_libgcc_s_suffix libc_cv_as_needed ASFLAGS_config libc_cv_z_combreloc libc_cv_z_execstack libc_cv_fpie libc_cv_hashstyle fno_unit_at_a_time libc_cv_ssp libc_cv_have_initfini no_whole_archive exceptions LIBGD have_libaudit have_libcap have_selinux EGREP sizeof_long_double libc_cv_gcc_unwind_find_fde uname_sysname uname_release uname_version old_glibc_headers libc_cv_slibdir libc_cv_localedir libc_cv_sysconfdir libc_cv_rootsbindir libc_cv_forced_unwind use_ldconfig ldd_rewrite_script elf xcoff static shared pic_default profile omitfp bounded static_nss nopic_initfini DEFINES mach_interface_list VERSION RELEASE LIBOBJS LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@ -5876,6 +5876,33 @@ echo "$as_me:$LINENO: result: $libc_cv_fpie" >&5
echo "${ECHO_T}$libc_cv_fpie" >&6
echo "$as_me:$LINENO: checking for --hash-style option" >&5
echo $ECHO_N "checking for --hash-style option... $ECHO_C" >&6
if test "${libc_cv_hashstyle+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat > conftest.c <<EOF
int _start (void) { return 42; }
EOF
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
-fPIC -shared -o conftest.so conftest.c
-Wl,--hash-style=both -nostdlib 1>&5'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }
then
libc_cv_hashstyle=yes
else
libc_cv_hashstyle=no
fi
rm -f conftest*
fi
echo "$as_me:$LINENO: result: $libc_cv_hashstyle" >&5
echo "${ECHO_T}$libc_cv_hashstyle" >&6
fi
echo "$as_me:$LINENO: checking for -fno-toplevel-reorder" >&5
@ -8496,6 +8523,7 @@ s,@ASFLAGS_config@,$ASFLAGS_config,;t t
s,@libc_cv_z_combreloc@,$libc_cv_z_combreloc,;t t
s,@libc_cv_z_execstack@,$libc_cv_z_execstack,;t t
s,@libc_cv_fpie@,$libc_cv_fpie,;t t
s,@libc_cv_hashstyle@,$libc_cv_hashstyle,;t t
s,@fno_unit_at_a_time@,$fno_unit_at_a_time,;t t
s,@libc_cv_ssp@,$libc_cv_ssp,;t t
s,@libc_cv_have_initfini@,$libc_cv_have_initfini,;t t

View File

@ -1589,6 +1589,22 @@ EOF
rm -f conftest*])
AC_SUBST(libc_cv_fpie)
AC_CACHE_CHECK(for --hash-style option,
libc_cv_hashstyle, [dnl
cat > conftest.c <<EOF
int _start (void) { return 42; }
EOF
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
-fPIC -shared -o conftest.so conftest.c
-Wl,--hash-style=both -nostdlib 1>&AS_MESSAGE_LOG_FD])
then
libc_cv_hashstyle=yes
else
libc_cv_hashstyle=no
fi
rm -f conftest*])
AC_SUBST(libc_cv_hashstyle)
fi
AC_CACHE_CHECK(for -fno-toplevel-reorder, libc_cv_fno_toplevel_reorder, [dnl

View File

@ -1,5 +1,5 @@
/* Look up a symbol in the loaded objects.
Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -72,6 +72,16 @@ struct sym_val
#include "do-lookup.h"
static uint_fast32_t
dl_new_hash (const char *s)
{
uint_fast32_t h = 5381;
for (unsigned char c = *s; c != '\0'; c = *++s)
h = h * 33 + c;
return h & 0xffffffff;
}
/* Add extra dependency on MAP to UNDEF_MAP. */
static int
internal_function
@ -206,7 +216,8 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
const struct r_found_version *version,
int type_class, int flags, struct link_map *skip_map)
{
const unsigned long int hash = _dl_elf_hash (undef_name);
const uint_fast32_t new_hash = dl_new_hash (undef_name);
unsigned long int old_hash = 0xffffffff;
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope = symbol_scope;
@ -229,8 +240,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
/* Search the relevant loaded objects for a definition. */
for (size_t start = i; *scope != NULL; start = 0, ++scope)
{
int res = do_lookup_x (undef_name, hash, *ref, &current_value, *scope,
start, version, flags, skip_map, type_class);
int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
&current_value, *scope, start, version, flags,
skip_map, type_class);
if (res > 0)
break;
@ -301,9 +313,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
struct sym_val protected_value = { NULL, NULL };
for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
if (do_lookup_x (undef_name, hash, *ref, &protected_value,
*scope, i, version, flags, skip_map,
ELF_RTYPE_CLASS_PLT) != 0)
if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
&protected_value, *scope, i, version, flags,
skip_map, ELF_RTYPE_CLASS_PLT) != 0)
break;
if (protected_value.s != NULL && protected_value.m != undef_map)
@ -352,6 +364,31 @@ _dl_setup_hash (struct link_map *map)
Elf_Symndx *hash;
Elf_Symndx nchain;
if (__builtin_expect (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
+ DT_THISPROCNUM + DT_VERSIONTAGNUM
+ DT_EXTRANUM + DT_VALNUM] != NULL, 1))
{
Elf32_Word *hash32
= (void *) D_PTR (map, l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
+ DT_THISPROCNUM + DT_VERSIONTAGNUM
+ DT_EXTRANUM + DT_VALNUM]);
map->l_nbuckets = *hash32++;
Elf32_Word symbias = *hash32++;
Elf32_Word bitmask_nwords = *hash32++;
/* Must be a power of two. */
assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
map->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
map->l_gnu_shift = *hash32++;
map->l_gnu_bitmask = (ElfW(Addr) *) hash32;
hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
map->l_gnu_buckets = hash32;
hash32 += map->l_nbuckets;
map->l_gnu_chain_zero = hash32 - symbias;
return;
}
if (!map->l_info[DT_HASH])
return;
hash = (void *) D_PTR (map, l_info[DT_HASH]);
@ -399,9 +436,10 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|| GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
&& undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded)
{
const unsigned long int hash = _dl_elf_hash (undef_name);
const uint_fast32_t new_hash = dl_new_hash (undef_name);
unsigned long int old_hash = 0xffffffff;
do_lookup_x (undef_name, hash, *ref, &val,
do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
undef_map->l_local_scope[0], 0, version, 0, NULL,
type_class);

View File

@ -1,5 +1,5 @@
/* Miscellaneous support functions for dynamic linker
Copyright (C) 1997-2002, 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 1997-2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -308,7 +308,7 @@ _dl_dprintf (int fd, const char *fmt, ...)
/* Test whether given NAME matches any of the names of the given object. */
int
internal_function
_dl_name_match_p (const char *name, struct link_map *map)
_dl_name_match_p (const char *name, const struct link_map *map)
{
if (strcmp (name, map->l_name) == 0)
return 1;

View File

@ -17,32 +17,29 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* Inner part of the lookup functions. We return a value > 0 if we
found the symbol, the value 0 if nothing is found and < 0 if
something bad happened. */
static int
__attribute_noinline__
do_lookup_x (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result,
struct r_scope_elem *scope, size_t i,
do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
unsigned long int *old_hash, const ElfW(Sym) *ref,
struct sym_val *result, struct r_scope_elem *scope, size_t i,
const struct r_found_version *const version, int flags,
struct link_map *skip, int type_class)
{
struct link_map **list = scope->r_list;
size_t n = scope->r_nlist;
struct link_map *map;
do
{
const ElfW(Sym) *symtab;
const char *strtab;
const ElfW(Half) *verstab;
/* These variables are used in the nested function. */
Elf_Symndx symidx;
const ElfW(Sym) *sym;
int num_versions = 0;
const ElfW(Sym) *versioned_sym = NULL;
map = list[i]->l_real;
const struct link_map *map = list[i]->l_real;
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
if (map == skip)
@ -63,109 +60,158 @@ do_lookup_x (const char *undef_name, unsigned long int hash,
map->l_name[0] ? map->l_name : rtld_progname,
map->l_ns);
symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
verstab = map->l_versyms;
/* If the hash table is empty there is nothing to do here. */
if (map->l_nbuckets == 0)
continue;
/* Search the appropriate hash bucket in this object's symbol table
for a definition for the same symbol name. */
for (symidx = map->l_buckets[hash % map->l_nbuckets];
symidx != STN_UNDEF;
symidx = map->l_chain[symidx])
/* The tables for this map. */
const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
/* Nested routine to check whether the symbol matches. */
const ElfW(Sym) *
__attribute_noinline__
check_match (const ElfW(Sym) *sym)
{
assert (ELF_RTYPE_CLASS_PLT == 1);
if (__builtin_expect ((sym->st_value == 0 /* No value. */
&& ELFW(ST_TYPE) (sym->st_info) != STT_TLS)
|| (type_class & (sym->st_shndx == SHN_UNDEF)),
0))
return NULL;
if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC
&& ELFW(ST_TYPE) (sym->st_info) != STT_TLS, 0))
/* Ignore all but STT_NOTYPE, STT_OBJECT and STT_FUNC
entries (and STT_TLS if TLS is supported) since these
are no code/data definitions. */
return NULL;
if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
/* Not the symbol we are looking for. */
return NULL;
const ElfW(Half) *verstab = map->l_versyms;
if (version != NULL)
{
if (__builtin_expect (verstab == NULL, 0))
{
/* We need a versioned symbol but haven't found any. If
this is the object which is referenced in the verneed
entry it is a bug in the library since a symbol must
not simply disappear.
It would also be a bug in the object since it means that
the list of required versions is incomplete and so the
tests in dl-version.c haven't found a problem.*/
assert (version->filename == NULL
|| ! _dl_name_match_p (version->filename, map));
/* Otherwise we accept the symbol. */
}
else
{
/* We can match the version information or use the
default one if it is not hidden. */
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
if ((map->l_versions[ndx].hash != version->hash
|| strcmp (map->l_versions[ndx].name, version->name))
&& (version->hidden || map->l_versions[ndx].hash
|| (verstab[symidx] & 0x8000)))
/* It's not the version we want. */
return NULL;
}
}
else
{
/* No specific version is selected. There are two ways we
can got here:
- a binary which does not include versioning information
is loaded
- dlsym() instead of dlvsym() is used to get a symbol which
might exist in more than one form
If the library does not provide symbol version information
there is no problem at at: we simply use the symbol if it
is defined.
These two lookups need to be handled differently if the
library defines versions. In the case of the old
unversioned application the oldest (default) version
should be used. In case of a dlsym() call the latest and
public interface should be returned. */
if (verstab != NULL)
{
if ((verstab[symidx] & 0x7fff)
>= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
{
/* Don't accept hidden symbols. */
if ((verstab[symidx] & 0x8000) == 0
&& num_versions++ == 0)
/* No version so far. */
versioned_sym = sym;
return NULL;
}
}
}
/* There cannot be another entry for this symbol so stop here. */
return sym;
}
const ElfW(Sym) *sym;
const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
if (__builtin_expect (bitmask != NULL, 1))
{
sym = &symtab[symidx];
ElfW(Addr) bitmask_word
= bitmask[(new_hash / __ELF_NATIVE_CLASS)
& map->l_gnu_bitmask_idxbits];
assert (ELF_RTYPE_CLASS_PLT == 1);
if ((sym->st_value == 0 /* No value. */
#ifdef USE_TLS
&& ELFW(ST_TYPE) (sym->st_info) != STT_TLS
#endif
)
|| (type_class & (sym->st_shndx == SHN_UNDEF)))
continue;
unsigned int hashbit1 = new_hash & (__ELF_NATIVE_CLASS - 1);
unsigned int hashbit2 = ((new_hash >> map->l_gnu_shift)
& (__ELF_NATIVE_CLASS - 1));
if (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC
#ifdef USE_TLS
&& ELFW(ST_TYPE) (sym->st_info) != STT_TLS
#endif
)
/* Ignore all but STT_NOTYPE, STT_OBJECT and STT_FUNC
entries (and STT_TLS if TLS is supported) since these
are no code/data definitions. */
continue;
if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
/* Not the symbol we are looking for. */
continue;
if (version != NULL)
if (__builtin_expect ((bitmask_word >> hashbit1)
& (bitmask_word >> hashbit2) & 1, 0))
{
if (__builtin_expect (verstab == NULL, 0))
Elf32_Word bucket = map->l_gnu_buckets[new_hash
% map->l_nbuckets];
if (bucket != 0)
{
/* We need a versioned symbol but haven't found any. If
this is the object which is referenced in the verneed
entry it is a bug in the library since a symbol must
not simply disappear.
const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
It would also be a bug in the object since it means that
the list of required versions is incomplete and so the
tests in dl-version.c haven't found a problem.*/
assert (version->filename == NULL
|| ! _dl_name_match_p (version->filename, map));
/* Otherwise we accept the symbol. */
}
else
{
/* We can match the version information or use the
default one if it is not hidden. */
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
if ((map->l_versions[ndx].hash != version->hash
|| strcmp (map->l_versions[ndx].name, version->name))
&& (version->hidden || map->l_versions[ndx].hash
|| (verstab[symidx] & 0x8000)))
/* It's not the version we want. */
continue;
do
if ((*hasharr & ~1u) == (new_hash & ~1u))
{
symidx = hasharr - map->l_gnu_chain_zero;
sym = check_match (&symtab[symidx]);
if (sym != NULL)
goto found_it;
}
while ((*hasharr++ & 1u) == 0);
}
}
else
}
else
{
if (*old_hash == 0xffffffff)
*old_hash = _dl_elf_hash (undef_name);
/* Use the old SysV-style hash table. Search the appropriate
hash bucket in this object's symbol table for a definition
for the same symbol name. */
for (symidx = map->l_buckets[*old_hash % map->l_nbuckets];
symidx != STN_UNDEF;
symidx = map->l_chain[symidx])
{
/* No specific version is selected. There are two ways we
can got here:
- a binary which does not include versioning information
is loaded
- dlsym() instead of dlvsym() is used to get a symbol which
might exist in more than one form
If the library does not provide symbol version
information there is no problem at at: we simply use the
symbol if it is defined.
These two lookups need to be handled differently if the
library defines versions. In the case of the old
unversioned application the oldest (default) version
should be used. In case of a dlsym() call the latest and
public interface should be returned. */
if (verstab != NULL)
{
if ((verstab[symidx] & 0x7fff)
>= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
{
/* Don't accept hidden symbols. */
if ((verstab[symidx] & 0x8000) == 0
&& num_versions++ == 0)
/* No version so far. */
versioned_sym = sym;
continue;
}
}
sym = check_match (&symtab[symidx]);
if (sym != NULL)
goto found_it;
}
/* There cannot be another entry for this symbol so stop here. */
goto found_it;
}
/* If we have seen exactly one versioned symbol while we are
@ -186,7 +232,7 @@ do_lookup_x (const char *undef_name, unsigned long int hash,
if (! result->s)
{
result->s = sym;
result->m = map;
result->m = (struct link_map *) map;
}
break;
}
@ -194,7 +240,7 @@ do_lookup_x (const char *undef_name, unsigned long int hash,
case STB_GLOBAL:
/* Global definition. Just what we need. */
result->s = sym;
result->m = map;
result->m = (struct link_map *) map;
return 1;
default:
/* Local symbols are ignored. */
@ -213,7 +259,3 @@ do_lookup_x (const char *undef_name, unsigned long int hash,
/* We have not found anything until now. */
return 0;
}
#undef FCT
#undef ARG
#undef VERSIONED

View File

@ -1,5 +1,5 @@
/* Inline functions for dynamic linking.
Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -143,6 +143,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
# endif
ADJUST_DYN_INFO (DT_JMPREL);
ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM);
# undef ADJUST_DYN_INFO
assert (cnt <= DL_RO_DYN_TEMP_CNT);
}

View File

@ -329,7 +329,8 @@ typedef struct
#define SHT_GROUP 17 /* Section group */
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
#define SHT_NUM 19 /* Number of defined types. */
#define SHT_LOOS 0x60000000 /* Start OS-specific */
#define SHT_LOOS 0x60000000 /* Start OS-specific. */
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
@ -699,6 +700,9 @@ typedef struct
If any adjustment is made to the ELF object after it has been
built these entries will need to be adjusted. */
#define DT_ADDRRNGLO 0x6ffffe00
#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */
#define DT_TLSDESC_PLT 0x6ffffef6
#define DT_TLSDESC_GOT 0x6ffffef7
#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
#define DT_CONFIG 0x6ffffefa /* Configuration information. */
@ -709,7 +713,7 @@ typedef struct
#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
#define DT_ADDRRNGHI 0x6ffffeff
#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
#define DT_ADDRNUM 10
#define DT_ADDRNUM 11
/* The versioning entry types. The next are defined as part of the
GNU extension. */

View File

@ -124,7 +124,7 @@ struct link_map
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
ElfW(Addr) l_entry; /* Entry point location. */
ElfW(Half) l_phnum; /* Number of program header entries. */
ElfW(Half) l_ldnum; /* Number of dynamic segment entries. */
ElfW(Half) l_ldnum; /* Number of dynamic segment entries. */
/* Array of DT_NEEDED dependencies and their dependencies, in
dependency order for symbol lookup (with and without
@ -141,7 +141,19 @@ struct link_map
/* Symbol hash table. */
Elf_Symndx l_nbuckets;
const Elf_Symndx *l_buckets, *l_chain;
Elf32_Word l_gnu_bitmask_idxbits;
Elf32_Word l_gnu_shift;
const ElfW(Addr) *l_gnu_bitmask;
union
{
const Elf32_Word *l_gnu_buckets;
const Elf_Symndx *l_chain;
};
union
{
const Elf32_Word *l_gnu_chain_zero;
const Elf_Symndx *l_buckets;
};
unsigned int l_direct_opencount; /* Reference count for dlopen/dlclose. */
enum /* Where this object came from. */

View File

@ -41,7 +41,8 @@ __pthread_mutex_init (mutex, mutexattr)
imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;
/* Sanity checks. */
// XXX For now we don't support priority protected mutexes.
// XXX For now we don't support priority inherited or priority protected
// XXX mutexes.
switch (__builtin_expect (imutexattr->mutexkind
& PTHREAD_MUTEXATTR_PROTOCOL_MASK,
PTHREAD_PRIO_NONE
@ -50,13 +51,6 @@ __pthread_mutex_init (mutex, mutexattr)
case PTHREAD_PRIO_NONE << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
break;
case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
#ifndef __ASSUME_SET_ROBUST_LIST
if (__set_robust_list_avail < 0)
return ENOTSUP;
#endif
break;
default:
return ENOTSUP;
}
@ -81,11 +75,11 @@ __pthread_mutex_init (mutex, mutexattr)
switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK)
{
case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_PRIVATE_NP;
break;
case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP;
if (PTHREAD_MUTEX_PRIO_CEILING_MASK
== PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
mutex->__data.__kind |= (imutexattr->mutexkind

View File

@ -331,7 +331,7 @@ struct audit_ifaces
/* Test whether given NAME matches any of the names of the given object. */
extern int _dl_name_match_p (const char *__name, struct link_map *__map)
extern int _dl_name_match_p (const char *__name, const struct link_map *__map)
internal_function;
/* Function used as argument for `_dl_receive_error' function. The