OSDN Git Service

Merge remote branch 'origin/master' into prelink
authorCarmelo Amoroso <carmelo.amoroso@st.com>
Fri, 21 Jan 2011 14:04:47 +0000 (15:04 +0100)
committerCarmelo Amoroso <carmelo.amoroso@st.com>
Fri, 21 Jan 2011 14:04:47 +0000 (15:04 +0100)
* origin/master:
  bump version to 0.9.32-rc2-git
  release 0.9.32-rc2
  nptl: Fix __USER_LABEL_PREFIX__ concatenatio
  nptl: fix start_thread() for _STACK_GROWS_UP
  ldso: get rid of _dl_lookup_hash
  Add protected symbols support for all architectures
  Revert "ldso/arm: Correct protected symbol resolution"
  Revert "ldso_sh: add support for protected symbols to SH"
  Revert "ldso/i386: support protected symbols"
  cris: Fix build issues
  syslog: fix 'everyone logs with user facility'
  __psfs_parse_spec: always use long int for %p
  buildsys: headers target should not depend on sysnum.h
  buildsys: fix make release target
  nptl: get rid of the last preprocessor warning when __ASSUME_TGKILL is not defined
  remove uClibc_ctype.h if !LOCALE
  Revert "Makefile.in: Add header to 'all' target"
  nptl: get rid of preprocessor warning when __ASSUME_TGKILL is not defined

Conflicts:
ldso/include/dl-hash.h
ldso/ldso/arm/elfinterp.c
ldso/ldso/avr32/elfinterp.c
ldso/ldso/bfin/elfinterp.c
ldso/ldso/cris/elfinterp.c
ldso/ldso/dl-hash.c
ldso/ldso/i386/elfinterp.c
ldso/ldso/m68k/elfinterp.c
ldso/ldso/mips/elfinterp.c
ldso/ldso/powerpc/elfinterp.c
ldso/ldso/sh/elfinterp.c
ldso/ldso/sh64/elfinterp.c
ldso/ldso/sparc/elfinterp.c
ldso/ldso/x86_64/elfinterp.c
ldso/ldso/xtensa/elfinterp.c
ldso/libdl/libdl.c

Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
18 files changed:
1  2 
ldso/include/dl-hash.h
ldso/ldso/arm/elfinterp.c
ldso/ldso/avr32/elfinterp.c
ldso/ldso/bfin/elfinterp.c
ldso/ldso/cris/elfinterp.c
ldso/ldso/dl-debug.c
ldso/ldso/dl-hash.c
ldso/ldso/i386/elfinterp.c
ldso/ldso/ldso.c
ldso/ldso/m68k/elfinterp.c
ldso/ldso/mips/elfinterp.c
ldso/ldso/powerpc/elfinterp.c
ldso/ldso/sh/elfinterp.c
ldso/ldso/sh64/elfinterp.c
ldso/ldso/sparc/elfinterp.c
ldso/ldso/x86_64/elfinterp.c
ldso/ldso/xtensa/elfinterp.c
ldso/libdl/libdl.c

@@@ -25,19 -25,11 +25,19 @@@ struct dyn_elf 
    struct dyn_elf * prev;
  };
  
- struct sym_val {
-   const ElfW(Sym) *s;
-   struct elf_resolve *m;
+ struct symbol_ref {
+   const ElfW(Sym) *sym;
+   struct elf_resolve *tpnt;
  };
  
 +/* Structure to describe a single list of scope elements.  The lookup
 +   functions get passed an array of pointers to such structures.  */
 +struct r_scope_elem {
 +  struct elf_resolve **r_list; /* Array of maps for the scope.  */
 +  unsigned int r_nlist;        /* Number of entries in the scope.  */
 +  struct r_scope_elem *next;
 +};
 +
  struct elf_resolve {
    /* These entries must be in this order to be compatible with the interface used
       by gdb to obtain the list of symbols. */
@@@ -156,20 -142,9 +156,9 @@@ extern struct elf_resolve * _dl_add_elf
        DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info,
        unsigned long dynamic_addr, unsigned long dynamic_size);
  
- /* Only need extra arg with some configurations */
- #if !((defined(USE_TLS) && USE_TLS) || defined __FDPIC__)
- # define _dl_lookup_hash(n, r, m, s, c, tpnt) _dl_lookup_hash(n, r, m, s, c)
- # define _dl_find_hash(n, r, m, s, t, tpntp) _dl_find_hash(n, r, m, s, t)
- #endif
- extern char *_dl_lookup_hash(const char *name, struct r_scope_elem *scope,
-               struct elf_resolve *mytpnt, struct sym_val *symbol, int type_class,
-               struct elf_resolve **tpntp);
- static __always_inline char *_dl_find_hash(const char *name, struct r_scope_elem *scope,
-               struct elf_resolve *mytpnt, struct sym_val *symbol, int type_class,
-               struct elf_resolve **tpntp)
- {
-       return _dl_lookup_hash(name, scope, mytpnt, symbol, type_class, tpntp);
- }
 -extern char *_dl_find_hash(const char *name, struct dyn_elf *rpnt,
++extern char *_dl_find_hash(const char *name, struct r_scope_elem *scope,
+               struct elf_resolve *mytpnt, int type_class,
+               struct symbol_ref *symbol);
  
  extern int _dl_linux_dynamic_link(void);
  
@@@ -69,8 -69,8 +69,8 @@@ unsigned long _dl_linux_resolver(struc
        got_addr = (char **) instr_addr;
  
        /* Get the address of the GOT entry */
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope,
 +      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope,
-                                tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+                                tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
                        _dl_progname, symname);
@@@ -217,9 -216,7 +216,10 @@@ _dl_do_reloc (struct elf_resolve *tpnt,
                        return 1;
  
                }
-                                       &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                                      &sym_ref, elf_machine_type_class(reloc_type));
+               def_mod = sym_ref.tpnt;
        } else {
                /*
                 * Relocs against STN_UNDEF are usually treated as using a
@@@ -50,9 -50,8 +50,9 @@@ unsigned long _dl_linux_resolver(unsign
        strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
        symname = strtab + sym->st_name;
  
-       new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
+       new_addr = (unsigned long) _dl_find_hash(symname,
 -                                               tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
 +                                               &_dl_loaded_modules->symbol_scope, tpnt,
-                                                NULL, 0, resolver);
++                                               ELF_RTYPE_CLASS_PLT, NULL);
  
        entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
        *entry = new_addr;
@@@ -149,9 -148,6 +149,9 @@@ static int _dl_do_reloc(struct elf_reso
                                    _dl_progname, symname);
                        return 0;
                }
-                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                              &sym_ref, elf_machine_type_class(reloc_type));
        }
  
  #if defined(__SUPPORT_LD_DEBUG__)
@@@ -65,9 -67,9 +67,9 @@@ _dl_linux_resolver (struct elf_resolve 
        got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);
  
        /* Get the address to be used to fill in the GOT entry.  */
-       new_addr = _dl_lookup_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, NULL, 0, &new_tpnt);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, NULL, 0, &sym_ref);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, 0, &sym_ref);
        if (!new_addr) {
-               new_addr = _dl_lookup_hash(symname, NULL, NULL, NULL, 0, &new_tpnt);
+               new_addr = _dl_find_hash(symname, NULL, NULL, 0, &sym_ref);
                if (!new_addr) {
                        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
                                    _dl_progname, symname);
@@@ -191,12 -194,10 +194,13 @@@ _dl_do_reloc (struct elf_resolve *tpnt,
  
                if (!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
                        _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
-                                    _dl_progname, strtab + symtab[symtab_index].st_name);
+                                    _dl_progname, symname);
                        _dl_exit (1);
                }
-                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                              &sym_ref, elf_machine_type_class(reloc_type));
+               symbol_tpnt = sym_ref.tpnt;
        }
  
  #if defined (__SUPPORT_LD_DEBUG__)
@@@ -66,7 -66,7 +66,7 @@@ _dl_linux_resolver(struct elf_resolve *
        got_addr = (char **)instr_addr;
  
        /* Get the address of the GOT entry. */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
                _dl_exit(1);
@@@ -183,10 -184,8 +184,11 @@@ _dl_do_reloc(struct elf_resolve *tpnt, 
                        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
                        _dl_exit(1);
                }
                symbol_addr += rpnt->r_addend;
-                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                              &sym_ref, elf_machine_type_class(reloc_type));
        }
  
  #if defined (__SUPPORT_LD_DEBUG__)
@@@ -104,60 -104,3 +104,59 @@@ static void debug_reloc(ElfW(Sym) *symt
  #define debug_reloc(symtab, strtab, rpnt)
  
  #endif /* __SUPPORT_LD_DEBUG__ */
-                                       const ElfW(Sym) *ref, struct sym_val *value, int type_class)
 +
 +#ifdef __LDSO_PRELINK_SUPPORT__
 +static void
 +internal_function
 +_dl_debug_lookup (const char *undef_name, struct elf_resolve *undef_map,
-         struct elf_resolve *tls_tpnt = NULL;
-       struct sym_val val = { NULL, NULL };
++                                      const ElfW(Sym) *ref, struct symbol_ref *value, int type_class)
 +{
 +#ifdef SHARED
 +  unsigned long symbol_addr;
 +
 +  if (_dl_trace_prelink)
 +    {
 +      int conflict = 0;
-                                                                       undef_map, &val, type_class, &tls_tpnt);
++      struct symbol_ref val = { NULL, NULL };
 +
 +      if ((_dl_trace_prelink_map == NULL
 +         || _dl_trace_prelink_map == _dl_loaded_modules)
 +        && undef_map != _dl_loaded_modules)
 +      {
 +              symbol_addr = (unsigned long)
 +                                        _dl_find_hash(undef_name, &undef_map->symbol_scope,
-         if (val.s != value->s || val.m != value->m)
++                                                                      undef_map, type_class, &val);
 +
-       if (value->s
-         && (__builtin_expect (ELF_ST_TYPE(value->s->st_info)
++        if (val.sym != value->sym || val.tpnt != value->tpnt)
 +          conflict = 1;
 +      }
 +
-                     (size_t) (value->m ? value->m->mapaddr : 0),
-                     (size_t) (value->s ? value->s->st_value : 0));
++      if (value->sym
++        && (__builtin_expect (ELF_ST_TYPE(value->sym->st_info)
 +                              == STT_TLS, 0)))
 +      type_class = 4;
 +
 +      if (conflict
 +        || _dl_trace_prelink_map == undef_map
 +        || _dl_trace_prelink_map == NULL
 +        || type_class == 4)
 +      {
 +        _dl_dprintf (1, "%s %x %x -> %x %x ",
 +                    conflict ? "conflict" : "lookup",
 +                    (size_t) undef_map->mapaddr,
 +                    (size_t) (((ElfW(Addr)) ref) - undef_map->mapaddr),
-                       (size_t) (val.m ? val.m->mapaddr : 0),
-                       (size_t) (val.s ? val.s->st_value : 0));
++                    (size_t) (value->tpnt ? value->tpnt->mapaddr : 0),
++                    (size_t) (value->sym ? value->sym->st_value : 0));
 +        if (conflict)
 +          _dl_dprintf (1, "x %x %x ",
++                      (size_t) (val.tpnt ? val.tpnt->mapaddr : 0),
++                      (size_t) (val.sym ? val.sym->st_value : 0));
 +        _dl_dprintf (1, "/%x %s\n", type_class, undef_name);
 +      }
 +}
 +#endif
 +}
 +
 +#else
 +#define _dl_debug_lookup(undef_name, undef_map, ref, value, type_class)
 +#endif
@@@ -267,8 -268,8 +267,8 @@@ _dl_lookup_sysv_hash(struct elf_resolv
   * This function resolves externals, and this is either called when we process
   * relocations or when we call an entry in the PLT table for the first time.
   */
- char *_dl_lookup_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt,
-       struct sym_val *symbol, int type_class, struct elf_resolve **tpntp)
 -char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt,
++char *_dl_find_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt,
+       int type_class, struct symbol_ref *sym_ref)
  {
        struct elf_resolve *tpnt = NULL;
        ElfW(Sym) *symtab;
        unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name);
  #endif
  
 -      for (; rpnt; rpnt = rpnt->next) {
 -              tpnt = rpnt->dyn;
 -
 -              if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) {
 -                      if (mytpnt == tpnt)
 -                              ;
 -                      else {
 -                              struct init_fini_list *tmp;
 -
 -                              for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) {
 -                                      if (tmp->tpnt == tpnt)
 -                                              break;
+       if ((sym_ref) && (sym_ref->sym) && (ELF32_ST_VISIBILITY(sym_ref->sym->st_other) == STV_PROTECTED)) {
+                       sym = sym_ref->sym;
+               if (mytpnt)
+                       tpnt = mytpnt;
+       } else
 +      for (loop_scope = scope; loop_scope && !sym; loop_scope = loop_scope->next) {
 +              for (i = 0; i < loop_scope->r_nlist; i++) {
 +                      tpnt = loop_scope->r_list[i];
 +
 +                      if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) {
 +                              if (mytpnt == tpnt)
 +                                      ;
 +                              else {
 +                                      struct init_fini_list *tmp;
 +
 +                                      for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) {
 +                                              if (tmp->tpnt == tpnt)
 +                                                      break;
 +                                      }
 +                                      if (!tmp)
 +                                              continue;
                                }
 -                              if (!tmp)
 -                                      continue;
                        }
 -              }
 -              /* Don't search the executable when resolving a copy reloc. */
 -              if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
 -                      continue;
 +                      /* Don't search the executable when resolving a copy reloc. */
 +                      if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
 +                              continue;
  
 -              /* If the hash table is empty there is nothing to do here.  */
 -              if (tpnt->nbucket == 0)
 -                      continue;
 +                      /* If the hash table is empty there is nothing to do here.  */
 +                      if (tpnt->nbucket == 0)
 +                              continue;
  
 -              symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
 +                      symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
  
  #ifdef __LDSO_GNU_HASH_SUPPORT__
 -              /* Prefer GNU hash style, if any */
 -              if (tpnt->l_gnu_bitmask) {
 -                      sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
 -                      if (sym != NULL)
 -                              /* If sym has been found, do not search further */
 -                              break;
 -              } else {
 +                      /* Prefer GNU hash style, if any */
 +                      if (tpnt->l_gnu_bitmask) {
 +                              sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
 +                              if (sym != NULL)
 +                                      /* If sym has been found, do not search further */
 +                                      break;
 +                      } else {
  #endif
 -              /* Use the old SysV-style hash table */
 +                              /* Use the old SysV-style hash table */
  
 -              /* Calculate the old sysv hash number only once */
 -              if (elf_hash_number == 0xffffffff)
 -                      elf_hash_number = _dl_elf_hash((const unsigned char *)name);
 +                              /* Calculate the old sysv hash number only once */
 +                              if (elf_hash_number == 0xffffffff)
 +                                      elf_hash_number = _dl_elf_hash((const unsigned char *)name);
  
 -              sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
 -              if (sym != NULL)
 -                      break;
 +                              sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
 +                              if (sym != NULL)
 +                                      /* If sym has been found, do not search further */
 +                                      break;
  #ifdef __LDSO_GNU_HASH_SUPPORT__
 -              }
 +                      }
  #endif
 -      } /* end of for (; rpnt; rpnt = rpnt->next) { */
 +              } /* End of inner for */
 +      }
  
        if (sym) {
-               if (symbol) {
-                       symbol->s = sym;
-                       symbol->m = tpnt;
++              if (sym_ref) {
++                      sym_ref->sym = sym;
++                      sym_ref->tpnt = tpnt;
 +              }
                /* At this point we have found the requested symbol, do binding */
  #if defined(USE_TLS) && USE_TLS
                if (ELF_ST_TYPE(sym->st_info) == STT_TLS) {
@@@ -71,7 -71,7 +71,7 @@@ _dl_linux_resolver(struct elf_resolve *
        got_addr = (char **)instr_addr;
  
        /* Get the address of the GOT entry. */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
                _dl_exit(1);
@@@ -191,16 -190,9 +190,12 @@@ _dl_do_reloc(struct elf_resolve *tpnt, 
                if (unlikely(!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
                                        && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
                        return 1;
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
-                                       &current_value, elf_machine_type_class(reloc_type));
++                                      &sym_ref, elf_machine_type_class(reloc_type));
+               tls_tpnt = sym_ref.tpnt;
        } else {
-               if (symtab_index)
-                       symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type),
-                                                        &symtab[symtab_index]);
-               else
-                       symbol_addr = symtab[symtab_index].st_value;
+               symbol_addr = symtab[symtab_index].st_value;
                tls_tpnt = tpnt;
        }
        
@@@ -380,7 -283,7 +380,7 @@@ void *_dl_get_ready_to_run(struct elf_r
        ElfW(Phdr) *ppnt;
        ElfW(Dyn) *dpnt;
        char *lpntstr;
-       unsigned int i, cnt, k, nscope_elem;
 -      unsigned int i;
++      unsigned int i, cnt, nscope_elem;
        int unlazy = 0, trace_loaded_objects = 0;
        struct dyn_elf *rpnt;
        struct elf_resolve *tcurr;
@@@ -1106,43 -913,16 +1106,44 @@@ of this helper program; chances are yo
                tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
  #endif
                tpnt = NULL;
 +
 +      /*
 +       * Allocate the global scope array.
 +       */
 +      scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
 +
 +      for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
 +              scope_elem_list[i++] = tcurr;
 +
 +      _dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
 +      _dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
 +      /*
 +       * The symbol scope of the application, that is the first entry of the
 +       * _dl_loaded_modules list, is just the global scope to be used for the
 +       * symbol lookup.
 +       */
 +      global_scope = &_dl_loaded_modules->symbol_scope;
 +
 +      /* Build the local scope for each loaded modules. */
 +      local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
 +      i = 1;
 +      for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
++              unsigned int k;
 +              cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
 +              tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
 +              tcurr->symbol_scope.r_nlist = cnt;
 +              _dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
 +              /* Restoring the init_flag.*/
 +              for (k = 1; k < nscope_elem; k++)
 +                      scope_elem_list[k]->init_flag &= ~DL_RESERVED;
        }
  
 +      _dl_free(local_scope);
 +
  #ifdef __LDSO_LDD_SUPPORT__
 -      /* End of the line for ldd.... */
 -      if (trace_loaded_objects) {
 -              _dl_dprintf(1, "\t%s => %s (%x)\n",
 -                          rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1,
 -                          rpnt->dyn->libname, DL_LOADADDR_BASE(rpnt->dyn->loadaddr));
 +      /* Exit if LD_TRACE_LOADED_OBJECTS is on. */
 +      if (trace_loaded_objects && !_dl_trace_prelink)
                _dl_exit(0);
 -      }
  #endif
  
  #if defined(USE_TLS) && USE_TLS
         * ld.so.1, so we have to look up each symbol individually.
         */
  
-       _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, NULL, 0, NULL);
 -      _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", _dl_symbol_tables, NULL, 0, NULL);
++      _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
        if (_dl_envp)
                *_dl_envp = (unsigned long) envp;
  
  
        /* Find the real malloc function and make ldso functions use that from now on */
        _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
-                       global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -                      _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++                      global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
  
  #if defined(USE_TLS) && USE_TLS
        /* Find the real functions and make ldso functions use them from now on */
        _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -              _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++              _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
  
        _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -              _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++              _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
  
        _dl_free_function = (void (*)(void *)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -              _dl_find_hash(__C_SYMBOL_PREFIX__ "free", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++              _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
  
        _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -              _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++              _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
  
  #endif
  
@@@ -70,7 -70,7 +70,7 @@@ _dl_linux_resolver(struct elf_resolve *
        got_addr = (char **)instr_addr;
  
        /* Get the address of the GOT entry. */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
                _dl_exit(1);
@@@ -185,9 -184,6 +184,9 @@@ _dl_do_reloc(struct elf_resolve *tpnt, 
                        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
                        _dl_exit(1);
                }
-                                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                                              &sym_ref, elf_machine_type_class(reloc_type));
        }
  
  #if defined (__SUPPORT_LD_DEBUG__)
@@@ -56,7 -56,7 +56,7 @@@ unsigned long __dl_runtime_resolve(unsi
        symname = strtab + sym->st_name;
  
        new_addr = (unsigned long) _dl_find_hash(symname,
-                       &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -                      tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++                      &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
                                _dl_progname, symname);
@@@ -111,7 -111,7 +111,7 @@@ __dl_runtime_pltresolve(struct elf_reso
        got_addr = (char **)instr_addr;
  
        /* Get the address of the GOT entry. */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
                _dl_exit(1);
@@@ -161,8 -161,6 +161,7 @@@ int _dl_parse_relocation_information(st
        unsigned long old_val=0;
  #endif
  
-       struct sym_val current_value = { NULL, NULL };
++      struct symbol_ref sym_ref = { NULL, NULL };
        /* Now parse the relocation information */
        rel_size = rel_size / sizeof(ElfW(Rel));
        rpnt = (ELF_RELOC *) rel_addr;
        strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
        got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
  
++
        for (i = 0; i < rel_size; i++, rpnt++) {
                reloc_addr = (unsigned long *) (tpnt->loadaddr +
                        (unsigned long) rpnt->r_offset);
  
                if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) {
                        symbol_addr = (unsigned long)_dl_find_hash(symname,
 -                                                                 tpnt->symbol_scope,
 +                                                                 scope,
-                                                                  tpnt, &current_value,
-                                                                  elf_machine_type_class(reloc_type), NULL);
+                                                                  tpnt,
 -                                                                 elf_machine_type_class(reloc_type), NULL);
++                                                                 elf_machine_type_class(reloc_type), &sym_ref);
                        if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
                                return 1;
-                                                       &current_value, elf_machine_type_class(reloc_type));
 +                      if (_dl_trace_prelink)
 +                              _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                                                      &sym_ref, elf_machine_type_class(reloc_type));
                }
                if (!symtab_index) {
                        /* Relocs against STN_UNDEF are usually treated as using a
                case R_MIPS_TLS_TPREL32:
  # endif
                        {
-                               struct elf_resolve *tpnt_tls = NULL;
+                               struct elf_resolve *tls_tpnt = NULL;
 -                              struct symbol_ref sym_ref;
+                               sym_ref.sym =  &symtab[symtab_index];
+                               sym_ref.tpnt =  NULL;
  
                                if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) {
 -                                      symbol_addr = (unsigned long) _dl_find_hash(symname, tpnt->symbol_scope,
 +                                      symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-                                               tpnt, &current_value, elf_machine_type_class(reloc_type), &tpnt_tls);
+                                               tpnt, elf_machine_type_class(reloc_type), &sym_ref);
+                                       tls_tpnt = sym_ref.tpnt;
                                }
-                           /* In case of a TLS reloc, tpnt_tls NULL means we have an 'anonymous'
+                           /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous'
                               symbol.  This is the case for a static tls variable, so the lookup
                               module is just that one is referencing the tls variable. */
-                           if (!tpnt_tls)
-                               tpnt_tls = tpnt;
+                           if (!tls_tpnt)
+                               tls_tpnt = tpnt;
  
                                switch (reloc_type) {
                                        case R_MIPS_TLS_DTPMOD64:
@@@ -362,12 -362,12 +365,12 @@@ void _dl_perform_mips_global_got_reloca
                                }
                                else {
                                        *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                               sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -                                              sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++                                              sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
                                }
                        }
                        else if (sym->st_shndx == SHN_COMMON) {
                                *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                       sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -                                      sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++                                      sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
                        }
                        else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
                                *got_entry != sym->st_value && tmp_lazy) {
                        }
                        else {
                                *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                       sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -                                      sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++                                      sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
                        }
  
                        got_entry++;
@@@ -139,7 -139,7 +139,7 @@@ unsigned long _dl_linux_resolver(struc
  
        /* Get the address of the GOT entry */
        finaladdr = (Elf32_Addr) _dl_find_hash(symname,
-                       &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -                      tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++                      &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!finaladdr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
                _dl_exit(1);
@@@ -213,17 -212,14 +212,17 @@@ _dl_do_reloc (struct elf_resolve *tpnt,
                 * here, so all bases should be covered.
                 */
                if (unlikely(!symbol_addr
-                       && (ELF32_ST_TYPE(sym->st_info) != STT_TLS
-                               && ELF32_ST_BIND(sym->st_info) != STB_WEAK)))
+                       && (ELF32_ST_TYPE(sym_ref.sym->st_info) != STT_TLS
+                               && ELF32_ST_BIND(sym_ref.sym->st_info) != STB_WEAK)))
                        return 1;
-                                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                                              &sym_ref, elf_machine_type_class(reloc_type));
+               tls_tpnt = sym_ref.tpnt;
        } else {
-               symbol_addr = sym->st_value;
+               symbol_addr = sym_ref.sym->st_value;
                tls_tpnt = tpnt;
        }
  #if defined (__SUPPORT_LD_DEBUG__)
        old_val = *reloc_addr;
  #endif
@@@ -69,7 -69,7 +69,7 @@@ unsigned long _dl_linux_resolver(struc
        got_addr = (char **) instr_addr;
  
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
  
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
@@@ -170,33 -172,24 +172,27 @@@ _dl_do_reloc (struct elf_resolve *tpnt
  
        if (symtab_index) {
                symname = strtab + symtab[symtab_index].st_name;
-               if (ELF32_ST_VISIBILITY(symtab[symtab_index].st_other)
-                       != STV_PROTECTED) {
-                       symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, &current_value,
-                                                                       elf_machine_type_class(reloc_type), &tls_tpnt);
-                       /*
-                        * We want to allow undefined references to weak symbols - this might
-                        * have been intentional.  We should not be linking local symbols
-                        * here, so all bases should be covered.
-                        */
-                       if (!symbol_addr
-                               && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
-                               && (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
-                               _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
-                                               _dl_progname, strtab + symtab[symtab_index].st_name);
-                               /* Let the caller to handle the error: it may be non fatal if called from dlopen */
-                               return 1;
-                       }
-               } else
-                       /* Resolve protected symbols locally */
-                       symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type),
-                                                                                       &symtab[symtab_index]);
+               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt,
+                                               elf_machine_type_class(reloc_type), &sym_ref);
+               /*
+                * We want to allow undefined references to weak symbols - this might
+                * have been intentional.  We should not be linking local symbols
+                * here, so all bases should be covered.
+                */
+               if (!symbol_addr
+                       && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
+                       && (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
+                       _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+                                   _dl_progname, symname);
+                       /* Let the caller to handle the error: it may be non fatal if called from dlopen */
+                       return 1;
+               }
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
-                                                       &current_value, elf_machine_type_class(reloc_type));
++                                                      &sym_ref, elf_machine_type_class(reloc_type));
+               tls_tpnt = sym_ref.tpnt;
        }
  
  #if defined (__SUPPORT_LD_DEBUG__)
@@@ -73,7 -73,7 +73,7 @@@ unsigned long _dl_linux_resolver(struc
  
  
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
                            _dl_progname, symname);
@@@ -199,12 -200,9 +200,12 @@@ static int _dl_do_reloc(struct elf_reso
  
                if (stb != STB_WEAK && !symbol_addr) {
                        _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
-                                    _dl_progname, strtab + symtab[symtab_index].st_name);
+                                    _dl_progname, symname);
                        _dl_exit (1);
                }
-                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                              &sym_ref, elf_machine_type_class(reloc_type));
        }
  
  #ifdef __SUPPORT_LD_DEBUG__
@@@ -80,7 -80,7 +80,7 @@@ _dl_linux_resolver(struct elf_resolve *
        got_addr = (char **)instr_addr;
  
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
                _dl_exit(1);
@@@ -201,9 -200,7 +200,10 @@@ _dl_do_reloc(struct elf_resolve *tpnt, 
                        return 1;
  
                }
-                                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                                              &sym_ref, elf_machine_type_class(reloc_type));
+               tls_tpnt = sym_ref.tpnt;
        } else {
                /* Relocs against STN_UNDEF are usually treated as using a
                 * symbol value of zero, and using the module containing the
@@@ -70,7 -70,7 +70,7 @@@ _dl_linux_resolver(struct elf_resolve *
        got_addr = (char **)instr_addr;
  
        /* Get the address of the GOT entry. */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 -      new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++      new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
                _dl_exit(1);
@@@ -187,9 -186,7 +186,10 @@@ _dl_do_reloc(struct elf_resolve *tpnt, 
                        /* This may be non-fatal if called from dlopen. */
                        return 1;
                }
-                                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                                              &sym_ref, elf_machine_type_class(reloc_type));
+               tls_tpnt = sym_ref.tpnt;
        } else {
                /* Relocs against STN_UNDEF are usually treated as using a
                 * symbol value of zero, and using the module containing the
@@@ -178,9 -177,6 +177,9 @@@ _dl_do_reloc (struct elf_resolve *tpnt
                                                 _dl_progname, symname);
                        _dl_exit (1);
                }
-                                               &current_value, elf_machine_type_class(reloc_type));
 +              if (_dl_trace_prelink)
 +                      _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++                                              &sym_ref, elf_machine_type_class(reloc_type));
        }
  
  #if defined (__SUPPORT_LD_DEBUG__)
@@@ -706,13 -668,13 +707,13 @@@ void *dlsym(void *vhandle, const char *
        tpnt = NULL;
        if (handle == _dl_symbol_tables)
                tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
-       ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, NULL, NULL, 0, &tls_tpnt);
 -      ret = _dl_find_hash(name2, handle, tpnt, 0, &sym_ref);
++      ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, tpnt, 0, &sym_ref);
  
  #if defined(USE_TLS) && USE_TLS && defined SHARED
-       if (tls_tpnt) {
+       if (sym_ref.tpnt) {
                /* The found symbol is a thread-local storage variable.
                Return the address for to the current thread.  */
-               ret = _dl_tls_symaddr ((struct link_map *)tls_tpnt, (Elf32_Addr)ret);
+               ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret);
        }
  #endif