Browse Source

Promote do_lookup_x:check_match to a full function.

While it may be argued that nested functions make the resulting
code easier to read, or worse to read the following two bugs
make it difficult to debug:

Bug 8300 - no local symbol information within nested or nesting
procedures
https://sourceware.org/bugzilla/show_bug.cgi?id=8300

Bug 53927 - wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927

Until these are fixed I've made check_match a full function.
After they are fixed we can resume arguing about the merits
of nested functions on readability and maintenance.
roland/gold-vs-libc
Carlos O'Donell 12 years ago
parent
commit
8e25d1e772
  1. 7
      ChangeLog
  2. 154
      elf/dl-lookup.c

7
ChangeLog

@ -1,3 +1,10 @@
2014-02-28 Carlos O'Donell <carlos@redhat.com>
* elf/dl-lookup.c (check_match): New function.
(ELF_MACHINE_SYM_NO_MATCH): Adjust comment.
(do_lookup_x): Remove nested function check_match. Use non-nested
function check_match.
2014-02-28 Roland McGrath <roland@hack.frob.com>
* csu/Makefile (generated, before-compile): Use += rather than =.

154
elf/dl-lookup.c

@ -31,9 +31,8 @@
#include <assert.h>
/* Return nonzero if do_lookup_x:check_match should consider SYM to
fail to match a symbol reference for some machine-specific
reason. */
/* Return nonzero if check_match should consider SYM to fail to match a
symbol reference for some machine-specific reason. */
#ifndef ELF_MACHINE_SYM_NO_MATCH
# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
#endif
@ -75,67 +74,25 @@ struct sym_val
# define bump_num_relocations() ((void) 0)
#endif
/* 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, 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 *undef_map)
/* Utility function for do_lookup_x. The caller is called with undef_name,
ref, version, flags and type_class, and those are passed as the first
five arguments. The caller then computes sym, symidx, strtab, and map
and passes them as the next four arguments. Lastly the caller passes in
versioned_sym and num_versions which are modified by check_match during
the checking process. */
static const ElfW(Sym) *
check_match (const char *const undef_name,
const ElfW(Sym) *const ref,
const struct r_found_version *const version,
const int flags,
const int type_class,
const ElfW(Sym) *const sym,
const Elf_Symndx symidx,
const char *const strtab,
const struct link_map *const map,
const ElfW(Sym) **const versioned_sym,
int *const num_versions)
{
size_t n = scope->r_nlist;
/* Make sure we read the value before proceeding. Otherwise we
might use r_list pointing to the initial scope and r_nlist being
the value after a resize. That is the only path in dl-open.c not
protected by GSCOPE. A read barrier here might be to expensive. */
__asm volatile ("" : "+r" (n), "+m" (scope->r_list));
struct link_map **list = scope->r_list;
do
{
/* These variables are used in the nested function. */
Elf_Symndx symidx;
int num_versions = 0;
const ElfW(Sym) *versioned_sym = NULL;
const struct link_map *map = list[i]->l_real;
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
if (map == skip)
continue;
/* Don't search the executable when resolving a copy reloc. */
if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
continue;
/* Do not look into objects which are going to be removed. */
if (map->l_removed)
continue;
/* Print some debugging info if wanted. */
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS))
_dl_debug_printf ("symbol=%s; lookup in file=%s [%lu]\n",
undef_name, DSO_FILENAME (map->l_name),
map->l_ns);
/* If the hash table is empty there is nothing to do here. */
if (map->l_nbuckets == 0)
continue;
/* 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)
{
unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
assert (ELF_RTYPE_CLASS_PLT == 1);
if (__builtin_expect ((sym->st_value == 0 /* No value. */
@ -216,9 +173,9 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
{
/* Don't accept hidden symbols. */
if ((verstab[symidx] & 0x8000) == 0
&& num_versions++ == 0)
&& (*num_versions)++ == 0)
/* No version so far. */
versioned_sym = sym;
*versioned_sym = sym;
return NULL;
}
@ -227,7 +184,62 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
/* There cannot be another entry for this symbol so stop here. */
return sym;
}
}
/* 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, 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 *undef_map)
{
size_t n = scope->r_nlist;
/* Make sure we read the value before proceeding. Otherwise we
might use r_list pointing to the initial scope and r_nlist being
the value after a resize. That is the only path in dl-open.c not
protected by GSCOPE. A read barrier here might be to expensive. */
__asm volatile ("" : "+r" (n), "+m" (scope->r_list));
struct link_map **list = scope->r_list;
do
{
/* These variables are used in the nested function. */
Elf_Symndx symidx;
int num_versions = 0;
const ElfW(Sym) *versioned_sym = NULL;
const struct link_map *map = list[i]->l_real;
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
if (map == skip)
continue;
/* Don't search the executable when resolving a copy reloc. */
if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
continue;
/* Do not look into objects which are going to be removed. */
if (map->l_removed)
continue;
/* Print some debugging info if wanted. */
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS))
_dl_debug_printf ("symbol=%s; lookup in file=%s [%lu]\n",
undef_name, DSO_FILENAME (map->l_name),
map->l_ns);
/* If the hash table is empty there is nothing to do here. */
if (map->l_nbuckets == 0)
continue;
/* 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]);
const ElfW(Sym) *sym;
const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
@ -254,7 +266,10 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
if (((*hasharr ^ new_hash) >> 1) == 0)
{
symidx = hasharr - map->l_gnu_chain_zero;
sym = check_match (&symtab[symidx]);
sym = check_match (undef_name, ref, version, flags,
type_class, &symtab[symidx], symidx,
strtab, map, &versioned_sym,
&num_versions);
if (sym != NULL)
goto found_it;
}
@ -276,7 +291,10 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
symidx != STN_UNDEF;
symidx = map->l_chain[symidx])
{
sym = check_match (&symtab[symidx]);
sym = check_match (undef_name, ref, version, flags,
type_class, &symtab[symidx], symidx,
strtab, map, &versioned_sym,
&num_versions);
if (sym != NULL)
goto found_it;
}

Loading…
Cancel
Save