OSDN Git Service

Joakim Tjernlund writes:
authorEric Andersen <andersen@codepoet.org>
Sat, 14 Feb 2004 11:30:39 +0000 (11:30 -0000)
committerEric Andersen <andersen@codepoet.org>
Sat, 14 Feb 2004 11:30:39 +0000 (11:30 -0000)
Hi it is me again.

This is the latest ldso patch. the NEW weak symbol handling works now
with a little special handling in _dl_find_hash(). You get to chose
if you want the new or old handling :)

There was 2 missing _dl_check_if_named_library_is_loaded() calls in _dlopen().

I then disabled the _dl_check_if_named_library_is_loaded() in dl-elf.c since
it is rendundant.

Question, why does some _dl_linux_resolver(), like i386, have 2 calls
to _dl_find_hash()? I think that is wrong, isn't it?

I really hope you can check this out soon ...

25 files changed:
ldso/include/dl-elf.h
ldso/include/dl-hash.h
ldso/ldso/arm/dl-sysdep.h
ldso/ldso/arm/elfinterp.c
ldso/ldso/cris/dl-sysdep.h
ldso/ldso/cris/elfinterp.c
ldso/ldso/dl-elf.c
ldso/ldso/dl-hash.c
ldso/ldso/dl-startup.c
ldso/ldso/i386/dl-sysdep.h
ldso/ldso/i386/elfinterp.c
ldso/ldso/ldso.c
ldso/ldso/m68k/dl-sysdep.h
ldso/ldso/m68k/elfinterp.c
ldso/ldso/mips/dl-sysdep.h
ldso/ldso/mips/elfinterp.c
ldso/ldso/powerpc/dl-sysdep.h
ldso/ldso/powerpc/elfinterp.c
ldso/ldso/sh/dl-sysdep.h
ldso/ldso/sh/elfinterp.c
ldso/ldso/sh64/dl-sysdep.h
ldso/ldso/sh64/elfinterp.c
ldso/ldso/sparc/dl-sysdep.h
ldso/ldso/sparc/elfinterp.c
ldso/libdl/libdl.c

index 4cab550..b0a4753 100644 (file)
@@ -92,6 +92,19 @@ extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
 # define UNSUPPORTED_RELOC_STR "RELA"
 #endif
 
+/* Reloc type classes as returned by elf_machine_type_class().
+   ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
+   some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
+   satisfied by any symbol in the executable.  Some architectures do
+   not support copy relocations.  In this case we define the macro to
+   zero so that the code for handling them gets automatically optimized
+   out.  */
+#define ELF_RTYPE_CLASS_PLT 1
+#ifndef DL_NO_COPY_RELOCS
+# define ELF_RTYPE_CLASS_COPY 2
+#else
+# define ELF_RTYPE_CLASS_COPY 0
+#endif
 
 
 /* Convert between the Linux flags for page protections and the
index 2d41e00..767c2ac 100644 (file)
@@ -67,9 +67,8 @@ extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname,
        char * loadaddr, unsigned long * dynamic_info, 
        unsigned long dynamic_addr, unsigned long dynamic_size);
 
-enum caller_type{symbolrel=0,copyrel=1,resolver=2};
 extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1, 
-       struct elf_resolve * f_tpnt, enum caller_type);
+                           int type_class);
 
 extern int _dl_linux_dynamic_link(void);
 
index 04e504e..96aa626 100644 (file)
@@ -122,3 +122,11 @@ static inline unsigned long arm_modulus(unsigned long m, unsigned long p) {
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_ARM_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+   | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
index 4af0535..5ab1f14 100644 (file)
@@ -118,6 +118,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        int reloc_type;
        ELF_RELOC *this_reloc;
        char *strtab;
+       char *symname;
        Elf32_Sym *symtab;
        ELF_RELOC *rel_addr;
        int symtab_index;
@@ -133,6 +134,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 
        symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
        strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+       symname = strtab + symtab[symtab_index].st_name;
 
 
        if (reloc_type != R_ARM_JUMP_SLOT) {
@@ -147,11 +149,11 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        got_addr = (char **) instr_addr;
 
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
-               tpnt->symbol_scope, tpnt, resolver);
+       new_addr = _dl_find_hash(symname,
+               tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
        if (!new_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);
        };
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -159,8 +161,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        {
                if (_dl_debug_bindings)
                {
-                       _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
-                                       strtab + symtab[symtab_index].st_name);
+                       _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
                        if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
                                        "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
                }
@@ -283,7 +284,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        if (symtab_index) {
 
                symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
-                               scope, (reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), symbolrel);
+                               scope, elf_machine_type_class(reloc_type));
 
                /*
                 * We want to allow undefined references to weak symbols - this might
@@ -424,7 +425,7 @@ _dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
 
                symbol_addr = (unsigned long) _dl_find_hash(strtab +
                        symtab[symtab_index].st_name, scope,
-                       NULL, copyrel);
+                       ELF_RTYPE_CLASS_COPY);
                if (!symbol_addr) goof++;
        }
        if (!goof) {
index 7066863..baad524 100644 (file)
@@ -110,3 +110,19 @@ cris_mod(unsigned long m, unsigned long p)
 #define PAGE_ALIGN 0xffffe000
 #define ADDR_ALIGN 0x1fff
 #define OFFS_ALIGN 0xffffe000
+
+/* The union of reloc-type-classes where the reloc TYPE is a member.
+
+   TYPE is in the class ELF_RTYPE_CLASS_PLT if it can describe a
+   relocation for a PLT entry, that is, for which a PLT entry should not
+   be allowed to define the value.  The GNU linker for CRIS can merge a
+   .got.plt entry (R_CRIS_JUMP_SLOT) with a .got entry (R_CRIS_GLOB_DAT),
+   so we need to match both these reloc types.
+
+   TYPE is in the class ELF_RTYPE_CLASS_NOCOPY if it should not be allowed
+   to resolve to one of the main executable's symbols, as for a COPY
+   reloc.  */
+#define elf_machine_type_class(type)                           \
+  ((((((type) == R_CRIS_JUMP_SLOT))                            \
+     || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT)    \
+   | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY))
index 71e1ff7..3e1b554 100644 (file)
@@ -142,16 +142,10 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        got_addr = (char **) instr_addr;
 
        /* Fetch the address of the GOT entry. */
-       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
-
+       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
        if (!new_addr) {
-               new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
-
-               if (new_addr)
-                       return (unsigned long) new_addr;
-
-               _dl_dprintf(2, "%s: Can't resolv symbol '%s'\n", _dl_progname, symname);
-               _dl_exit(1);
+           _dl_dprintf(2, "%s: Can't resolv symbol '%s'\n", _dl_progname, symname);
+           _dl_exit(1);
        }
 
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -261,7 +255,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF_RELOC *rpnt,
                }
                else {
                        symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-                               (reloc_type == R_CRIS_JUMP_SLOT ? tpnt : NULL), symbolrel);
+                                                                   elf_machine_type_class(reloc_type));
                }
 
                if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
@@ -366,7 +360,7 @@ _dl_do_copy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF_RELOC *rp
        goof = 0;
 
        if (symtab_index) {
-               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
+               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY);
 
                if (!symbol_addr)
                        goof++;
index 5a1c892..e14a23d 100644 (file)
@@ -255,12 +255,13 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
        if (pnt1) {
                libname = pnt1 + 1;
        }
-
+#if 0
        /* Critical step!  Weed out duplicates early to avoid
         * function aliasing, which wastes memory, and causes
         * really bad things to happen with weaks and globals. */
        if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL)
                return tpnt1;
+#endif
 
 #if defined (__SUPPORT_LD_DEBUG__)
        if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfind library='%s'; searching\n", libname);
index f69f0c1..57fb995 100644 (file)
@@ -154,7 +154,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
  * relocations or when we call an entry in the PLT table for the first time.
  */
 char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
-       struct elf_resolve *f_tpnt, enum caller_type caller_type)
+                   int type_class)
 {
        struct elf_resolve *tpnt;
        int si;
@@ -163,23 +163,12 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
        Elf32_Sym *symtab;
        unsigned long elf_hash_number, hn;
        char *weak_result;
-       struct dyn_elf *rpnt, first;
+       struct dyn_elf *rpnt;
        const ElfW(Sym) *sym;
 
        weak_result = 0;
        elf_hash_number = _dl_elf_hash(name);
 
-       /* A quick little hack to make sure that any symbol in the executable
-          will be preferred to one in a shared library.  This is necessary so
-          that any shared library data symbols referenced in the executable
-          will be seen at the same address by the executable, shared libraries
-          and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
-       if (_dl_symbol_tables && rpnt1) {
-               first = (*_dl_symbol_tables);
-               first.next = rpnt1;
-               rpnt1 = (&first);
-       }
-
        /*
         * The passes are so that we can first search the regular symbols
         * for whatever module was specified, and then search anything
@@ -187,39 +176,35 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
         * starting the first dlopened module, and anything above that
         * is just the next one in the chain.
         */
+       if (rpnt1 == NULL)
+               rpnt1 = _dl_symbol_tables;
+
        for (pass = 0; (1 == 1); pass++) {
 
                /*
                 * If we are just starting to search for RTLD_GLOBAL, setup
                 * the pointer for the start of the search.
                 */
-               if (pass == 1) {
+               if (pass == 1)
                        rpnt1 = _dl_handles;
-               }
 
                /*
                 * Anything after this, we need to skip to the next module.
                 */
-               else if (pass >= 2) {
+               else if (pass >= 2)
                        rpnt1 = rpnt1->next_handle;
-               }
 
                /*
-                * Make sure we still have a module, and make sure that this
-                * module was loaded with RTLD_GLOBAL.
+                * Make sure we still have a module.
                 */
-               if (pass != 0) {
                        if (rpnt1 == NULL)
                                break;
-                       //if ((rpnt1->flags & RTLD_GLOBAL) == 0)
-                               //continue;
-               }
 
-               for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
+               for (rpnt = rpnt1; rpnt; rpnt = rpnt->next) {
                        tpnt = rpnt->dyn;
 
                        /* Don't search the executable when resolving a copy reloc. */
-                       if (tpnt->libtype == elf_executable && caller_type == copyrel)
+                       if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
                                continue;
 
                        /*
@@ -236,19 +221,25 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
                                        continue;
                                if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC)
                                        continue;
-                               if (sym->st_shndx == SHN_UNDEF && caller_type != copyrel)
+                               if (type_class & (sym->st_shndx == SHN_UNDEF))
                                        continue;
                                if (_dl_strcmp(strtab + sym->st_name, name) != 0)
                                        continue;
 
                                switch (ELF32_ST_BIND(sym->st_info)) {
                                        case STB_WEAK:
-//Disable this to match current glibc behavior.  Of course,
-//this doesn't actually work yet and will cause segfaults...
-#if 1
+#ifndef __LIBDL_SHARED__
+/* 
+Due to a special hack in libdl.c, one must handle the _dl_ symbols
+according to the OLD weak symbol scheme. This stuff can be deleted
+once that hack has been fixed.
+*/
+
+                                               if(_dl_symbol((char *)name)) {
                                                if (!weak_result)
                                                        weak_result = (char *)tpnt->loadaddr + sym->st_value;
                                                break;
+                                               }
 #endif
                                        case STB_GLOBAL:
                                                return (char*)tpnt->loadaddr + sym->st_value;
index e9191e8..3a0c314 100644 (file)
@@ -513,11 +513,10 @@ found_got:
                                /* We only do a partial dynamic linking right now.  The user
                                   is not supposed to define any symbols that start with a
                                   '_dl', so we can do this with confidence. */
-                               if (!symname || symname[0] != '_' ||
-                                               symname[1] != 'd' || symname[2] != 'l' || symname[3] != '_')
-                               {
+                               if (!symname || !_dl_symbol(symname)) {
                                        continue;
                                }
+
                                symbol_addr = load_addr + symtab[symtab_index].st_value;
 
                                if (!symbol_addr) {
index f39a196..d7475d6 100644 (file)
@@ -79,3 +79,12 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_386_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)                        \
+   | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY))
index 8673652..362df3c 100644 (file)
@@ -133,7 +133,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
        symname= strtab + symtab[symtab_index].st_name;
 
-       if (reloc_type != R_386_JMP_SLOT) {
+       if (unlikely(reloc_type != R_386_JMP_SLOT)) {
                _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
                                _dl_progname);
                _dl_exit(1);
@@ -145,15 +145,11 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        got_addr = (char **) instr_addr;
 
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
-       if (!new_addr) {
-               new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
-               if (new_addr) {
-                       return (unsigned long) new_addr;
-               }
+       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
+       if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
                _dl_exit(1);
-       }
+       };
 
 #if defined (__SUPPORT_LD_DEBUG__)
        if ((unsigned long) got_addr < 0x40000000)
@@ -263,7 +259,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        if (symtab_index) {
 
                symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-                               (reloc_type == R_386_JMP_SLOT ? tpnt : NULL), symbolrel);
+                                                           elf_machine_type_class(reloc_type));
 
                /*
                 * We want to allow undefined references to weak symbols - this might
@@ -377,7 +373,7 @@ _dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
        symname      = strtab + symtab[symtab_index].st_name;
 
        if (symtab_index) {
-               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
+               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY);
                if (!symbol_addr) goof++;
        }
        if (!goof) {
index 71fadd4..2e0fa75 100644 (file)
@@ -609,12 +609,12 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
           up each symbol individually. */
 
 
-       _dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("___brk_addr", NULL, NULL, symbolrel);
+       _dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("___brk_addr", NULL, 0);
 
        if (_dl_brkp) {
                *_dl_brkp = brk_addr;
        }
-       _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", NULL, NULL, symbolrel);
+       _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", NULL, 0);
 
        if (_dl_envp) {
                *_dl_envp = (unsigned long) envp;
@@ -638,10 +638,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
 
        }
 #endif
-       _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, NULL, symbolrel);
+       _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, 0);
 #if defined (__SUPPORT_LD_DEBUG__)
        _dl_on_exit = (int (*)(void (*)(int, void *),void*))
-               (intptr_t) _dl_find_hash("on_exit", NULL, NULL, symbolrel);
+               (intptr_t) _dl_find_hash("on_exit", NULL, 0);
 #endif
 
        /* Notify the debugger we have added some objects. */
index 2cbc7d4..d8936f5 100644 (file)
@@ -86,3 +86,11 @@ extern unsigned int _dl_linux_resolver (int, int, struct elf_resolve *, int);
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_68K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)  \
+   | (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY))
index 1bcbec3..a033529 100644 (file)
@@ -98,7 +98,7 @@ unsigned int _dl_linux_resolver (int dummy1, int dummy2,
 
   /* Get the address of the GOT entry.  */
   new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
-                           tpnt->symbol_scope, tpnt, resolver);
+                           tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
   if (!new_addr)
     {
       _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
@@ -218,7 +218,7 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt,
          symbol_addr = (unsigned int)
            _dl_find_hash (strtab + symtab[symtab_index].st_name,
                           tpnt->symbol_scope,
-                          reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, symbolrel);
+                          elf_machine_type_class(reloc_type));
 
          /* We want to allow undefined references to weak symbols -
             this might have been intentional.  We should not be
@@ -342,7 +342,7 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt,
        {
          symbol_addr = (unsigned int)
            _dl_find_hash (strtab + symtab[symtab_index].st_name,
-                          xpnt->next, NULL, copyrel);
+                          xpnt->next, ELF_RTYPE_CLASS_COPY);
          if (!symbol_addr)
            {
              _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
index 17ce7cf..879cb83 100644 (file)
@@ -134,3 +134,5 @@ unsigned long _dl_linux_resolver(unsigned long sym_index,
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+#define elf_machine_type_class(type)           ELF_RTYPE_CLASS_PLT
index 59eca69..5d3355b 100644 (file)
@@ -128,8 +128,13 @@ unsigned long _dl_linux_resolver(unsigned long sym_index,
        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,
-                tpnt->symbol_scope, tpnt, resolver);
+       new_addr = (unsigned long) _dl_find_hash(symname,
+                       tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
+       if (!new_addr) {
+               _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+                               _dl_progname, symname);
+               _dl_exit (1);
+       }
 
        /* Address of jump instruction to fix up */
        instr_addr = (unsigned long) (got + local_gotno + sym_index - gotsym);
@@ -279,12 +284,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
                                        *got_entry = sym->st_value + (unsigned long) tpnt->loadaddr;
                                else {
                                        *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                               sym->st_name, tpnt->symbol_scope, NULL, copyrel);
+                                               sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_COPY);
                                }
                        }
                        else if (sym->st_shndx == SHN_COMMON) {
                                *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                       sym->st_name, tpnt->symbol_scope, NULL, copyrel);
+                                       sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_COPY);
                        }
                        else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
                                *got_entry != sym->st_value)
@@ -295,7 +300,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
                        }
                        else {
                                *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                       sym->st_name, tpnt->symbol_scope, NULL, copyrel);
+                                       sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_COPY);
                        }
 
                        got_entry++;
index 8768c9a..1a78b1b 100644 (file)
@@ -125,3 +125,16 @@ void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt);
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+/* We never want to use a PLT entry as the destination of a
+   reloc, when what is being relocated is a branch. This is
+   partly for efficiency, but mostly so we avoid loops.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_PPC_JMP_SLOT                          \
+    || (type) == R_PPC_REL24                           \
+    || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)  \
+   | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
index eb2f986..fec92e6 100644 (file)
@@ -209,8 +209,8 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 #endif
 
        /* Get the address of the GOT entry */
-       finaladdr = (Elf32_Addr) _dl_find_hash(strtab + symtab[symtab_index].st_name,
-                                               tpnt->symbol_scope, tpnt, resolver);
+       finaladdr = (Elf32_Addr) _dl_find_hash(symname,
+                       tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
        if (!finaladdr) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
                _dl_exit(1);
@@ -223,11 +223,8 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        delta = finaladdr - (Elf32_Word)reloc_addr;
        if (delta<<6>>6 == delta) {
                *reloc_addr = OPCODE_B(delta);
-#if 0
-       /* this will almost never be true */
-       } else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) {
+       } else if (finaladdr <= 0x01fffffc) {
                *reloc_addr = OPCODE_BA (finaladdr);
-#endif
        } else {
                /* Warning: we don't handle double-sized PLT entries */
                Elf32_Word *plt, *data_words, index, offset;
@@ -261,7 +258,6 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        char *symname;
        Elf32_Addr *reloc_addr;
        Elf32_Addr finaladdr;
-       struct dyn_elf *sym_scope;
 
        unsigned long symbol_addr;
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -278,19 +274,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        symtab_index = ELF32_R_SYM(rpnt->r_info);
        symname      = strtab + symtab[symtab_index].st_name;
 
-#if 1
-       sym_scope = scope->dyn->symbol_scope;
-#else
-       /* Funny, this works too and appears to be much faster. */
-       sym_scope = scope;
-#endif
-       if (reloc_type == R_PPC_COPY) {
-               sym_scope = scope->next;
-               tpnt = NULL; /* To be or not to be ...*/
-       }
-       symbol_addr = (unsigned long) _dl_find_hash(symname, sym_scope,
-                                                   (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL),
-                                                   (reloc_type == R_PPC_COPY ? copyrel : symbolrel));
+       symbol_addr = (unsigned long) _dl_find_hash(symname, scope->dyn->symbol_scope,
+                                                   elf_machine_type_class(reloc_type));
        /*
         * We want to allow undefined references to weak symbols - this might
         * have been intentional.  We should not be linking local symbols
@@ -320,11 +305,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 
                if (delta<<6>>6 == delta) {
                        *reloc_addr = OPCODE_B(delta);
-#if 0
-               /* this will almost never be true */
-               } else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) {
+               } else if (finaladdr <= 0x01fffffc) {
                        *reloc_addr = OPCODE_BA (finaladdr);
-#endif
                } else {
                        /* Warning: we don't handle double-sized PLT entries */
                        Elf32_Word *plt, *data_words, index, offset;
@@ -384,7 +366,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                _dl_dprintf(2, "%s ", _dl_reltypes(reloc_type));
 #endif
                if (symtab_index)
-                       _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
+                       _dl_dprintf(2, "'%s'\n", symname);
                return -1;
        };
 
index cd11089..83cc9b3 100644 (file)
@@ -142,3 +142,12 @@ _dl_urem(unsigned int n, unsigned int base)
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)   \
+   | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
index a2edffe..e003260 100644 (file)
@@ -149,13 +149,8 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 
 
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
+       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
        if (!new_addr) {
-               new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
-               if (new_addr) {
-                       return (unsigned long) new_addr;
-               }
-
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
                _dl_exit(1);
        }
@@ -270,7 +265,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 
 
                symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-                               (reloc_type == R_SH_JMP_SLOT ? tpnt : NULL), symbolrel);
+                                                           elf_machine_type_class(reloc_type));
 
                /*
                 * We want to allow undefined references to weak symbols - this might
@@ -385,7 +380,7 @@ _dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
 
        if (symtab_index) {
 
-               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
+               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY);
                if (!symbol_addr) goof++;
        }
        if (!goof) {
index 241cde9..f654b83 100644 (file)
@@ -168,3 +168,11 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
 
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)   \
+   | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
index fce53db..d4f45d5 100644 (file)
@@ -190,13 +190,8 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 
 
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
+       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
        if (!new_addr) {
-               new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
-
-               if (new_addr)
-                       return (unsigned long)new_addr;
-
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
                            _dl_progname, symname);
                _dl_exit(1);
@@ -319,8 +314,7 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope,
                int stb;
 
                symbol_addr = (unsigned long)_dl_find_hash(symname, scope,
-                               (reloc_type == R_SH_JMP_SLOT ? tpnt : NULL),
-                                symbolrel);
+                                                          elf_machine_type_class(reloc_type));
 
                /*
                 * We want to allow undefined references to weak symbols - this
@@ -492,7 +486,7 @@ static int _dl_do_copy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
 
        if (symtab_index) {
                symbol_addr = (unsigned long)
-                       _dl_find_hash(symname, scope, NULL, copyrel);
+                       _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY);
 
                if (!symbol_addr)
                        goof++;
index 1930a93..72a8553 100644 (file)
@@ -110,3 +110,11 @@ extern unsigned int _dl_linux_resolver(unsigned int reloc_entry,
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)                              \
+   | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
index e9e55c0..ada72bf 100644 (file)
@@ -109,7 +109,7 @@ unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
 
   /* Get the address of the GOT entry */
   new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
-                       tpnt->symbol_scope, tpnt, resolver);
+                       tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
   if(!new_addr) {
     _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
               _dl_progname, strtab + symtab[symtab_index].st_name);
@@ -225,8 +225,7 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt,
 
       symbol_addr = (unsigned int)
        _dl_find_hash(strtab + symtab[symtab_index].st_name,
-                             tpnt->symbol_scope,
-                     (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), symbolrel);
+                     tpnt->symbol_scope, elf_machine_type_class(reloc_type);
 
       if(!symbol_addr &&
         ELF32_ST_BIND(symtab [symtab_index].st_info) == STB_GLOBAL) {
@@ -343,7 +342,7 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt,
 
       symbol_addr = (unsigned int)
        _dl_find_hash(strtab + symtab[symtab_index].st_name,
-                             xpnt->next, NULL, copyrel);
+                     xpnt->next,  ELF_RTYPE_CLASS_COPY);
       if(!symbol_addr) {
        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
                   _dl_progname, strtab + symtab[symtab_index].st_name);
index f3bc89a..5d7c22b 100644 (file)
@@ -30,7 +30,7 @@ static void __attribute__ ((unused)) foobar(void)
 
 static int __attribute__ ((unused)) foobar1 = (int) foobar;    /* Use as pointer */
 extern void _dl_dprintf(int, const char *, ...) __attribute__ ((__weak__, __alias__ ("foobar")));
-extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, enum caller_type)
+extern char *_dl_find_hash(const char *, struct dyn_elf *, int)
        __attribute__ ((__weak__, __alias__ ("foobar")));
 extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *, int)
        __attribute__ ((__weak__, __alias__ ("foobar")));
@@ -179,6 +179,7 @@ void *_dlopen(const char *libname, int flag)
        if(_dl_debug) 
        _dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
 #endif
+       if (!(tpnt = _dl_check_if_named_library_is_loaded((char *)libname, 0)))
        tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
        if (tpnt == NULL) {
                _dl_unmap_cache();
@@ -220,6 +221,9 @@ void *_dlopen(const char *libname, int flag)
                                        dpnt->d_un.d_val);
                                name = _dl_get_last_path_component(lpntstr);
 
+                               if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, 0)))
+                                       continue;
+
 #ifdef __SUPPORT_LD_DEBUG__
                                if(_dl_debug) 
                                _dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n", 
@@ -381,7 +385,7 @@ void *_dlsym(void *vhandle, const char *name)
                }
        }
 
-       ret = _dl_find_hash((char*)name, handle, NULL, copyrel);
+       ret = _dl_find_hash((char*)name, handle, 0);
 
        /*
         * Nothing found.