OSDN Git Service

mips/ldso: Check for TLS relocation in elf_machine_type_class.
authorKhem Raj <raj.khem@gmail.com>
Mon, 25 Jan 2010 22:24:26 +0000 (14:24 -0800)
committerKhem Raj <raj.khem@gmail.com>
Mon, 25 Jan 2010 22:35:43 +0000 (14:35 -0800)
* Store the symbol adress received from _dl_find_hash
  and do not recompute it.

Signed-off-by: Khem Raj <raj.khem@gmail.com>
ldso/ldso/mips/dl-sysdep.h
ldso/ldso/mips/elfinterp.c

index 30d84fb..c1aad66 100644 (file)
@@ -163,9 +163,25 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
 #define OFFS_ALIGN (0x10000000000UL-0x1000)
 #endif /* O32 || N32 */
 
-#define elf_machine_type_class(type) \
-  ((((type) == R_MIPS_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT)        \
+#if defined USE_TLS
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define elf_machine_type_class(type)                                  \
+  ((((type) == R_MIPS_JUMP_SLOT || (type) == R_MIPS_TLS_DTPMOD64       \
+     || (type) == R_MIPS_TLS_DTPREL64 || (type) == R_MIPS_TLS_TPREL64) \
+    * ELF_RTYPE_CLASS_PLT)                                             \
    | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
+# else
+# define elf_machine_type_class(type)                                  \
+  ((((type) == R_MIPS_JUMP_SLOT || (type) == R_MIPS_TLS_DTPMOD32       \
+     || (type) == R_MIPS_TLS_DTPREL32 || (type) == R_MIPS_TLS_TPREL32) \
+    * ELF_RTYPE_CLASS_PLT)                                             \
+   | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
+# endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
+#else
+#define elf_machine_type_class(type)                                   \
+  ((((type) == R_MIPS_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT)                        \
+   | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif /* USE_TLS */
 
 #define OFFSET_GP_GOT 0x7ff0
 
index 40c3e09..149fc56 100644 (file)
@@ -156,6 +156,7 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
        unsigned long symbol_addr;
        int reloc_type, symtab_index;
        struct elf_resolve *tpnt = xpnt->dyn;
+       char *symname = NULL;
 #if defined (__SUPPORT_LD_DEBUG__)
        unsigned long old_val=0;
 #endif
@@ -169,7 +170,6 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
        got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
 
        for (i = 0; i < rel_size; i++, rpnt++) {
-               char *symname = NULL;
                reloc_addr = (unsigned long *) (tpnt->loadaddr +
                        (unsigned long) rpnt->r_offset);
                reloc_type = ELF32_R_TYPE(rpnt->r_info);
@@ -178,13 +178,13 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
 
                debug_sym(symtab,strtab,symtab_index);
                debug_reloc(symtab,strtab,rpnt);
+               symname = strtab + symtab[symtab_index].st_name;
 #if defined (__SUPPORT_LD_DEBUG__)
                if (reloc_addr)
                        old_val = *reloc_addr;
 #endif
 
                if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) {
-                       symname = strtab + symtab[symtab_index].st_name;
                        symbol_addr = (unsigned long)_dl_find_hash(symname,
                                                                   tpnt->symbol_scope,
                                                                   tpnt,
@@ -192,6 +192,13 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
                        if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
                                return 1;
                }
+               if (!symtab_index) {
+                       /* Relocs against STN_UNDEF are usually treated as using a
+                       * symbol value of zero, and using the module containing the
+                       * reloc itself.
+                       */
+                       symbol_addr = symtab[symtab_index].st_value;
+               }
 
                switch (reloc_type) {
 #if USE_TLS
@@ -205,21 +212,17 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
                case R_MIPS_TLS_TPREL32:
 # endif
                        {
-                               ElfW(Sym) *sym_tls = &symtab[symtab_index];
                                struct elf_resolve *tpnt_tls = NULL;
 
                                if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) {
-                                       _dl_find_hash((strtab + symtab[symtab_index].st_name),
-                                                       _dl_symbol_tables, tpnt,
-                                                       elf_machine_type_class(reloc_type), &tpnt_tls);
+                                       symbol_addr = (unsigned long) _dl_find_hash(symname, tpnt->symbol_scope,
+                                               tpnt, elf_machine_type_class(reloc_type), &tpnt_tls);
                                }
-#if USE_TLS
                            /* In case of a TLS reloc, tpnt_tls 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;
-#endif
 
                                switch (reloc_type) {
                                        case R_MIPS_TLS_DTPMOD64:
@@ -228,17 +231,17 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
                                                        *(ElfW(Word) *)reloc_addr = tpnt_tls->l_tls_modid;
 #ifdef __SUPPORT_LD_DEBUG__
                                                _dl_dprintf(2, "TLS_DTPMOD : %s, %d, %d\n",
-                                                       (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr));
+                                                       symname, old_val, *((unsigned int *)reloc_addr));
 #endif
                                                break;
 
                                        case R_MIPS_TLS_DTPREL64:
                                        case R_MIPS_TLS_DTPREL32:
                                                *(ElfW(Word) *)reloc_addr +=
-                                                       TLS_DTPREL_VALUE (sym_tls);
+                                                       TLS_DTPREL_VALUE (symbol_addr);
 #ifdef __SUPPORT_LD_DEBUG__
                                                _dl_dprintf(2, "TLS_DTPREL : %s, %x, %x\n",
-                                                       (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr));
+                                                       symname, old_val, *((unsigned int *)reloc_addr));
 #endif
                                                break;
 
@@ -246,10 +249,10 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
                                        case R_MIPS_TLS_TPREL64:
                                                CHECK_STATIC_TLS((struct link_map *)tpnt_tls);
                                                *(ElfW(Word) *)reloc_addr +=
-                                                       TLS_TPREL_VALUE (tpnt_tls, sym_tls);
+                                                       TLS_TPREL_VALUE (tpnt_tls, symbol_addr);
 #ifdef __SUPPORT_LD_DEBUG__
                                                _dl_dprintf(2, "TLS_TPREL  : %s, %x, %x\n",
-                                                       (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr));
+                                                       symname, old_val, *((unsigned int *)reloc_addr));
 #endif
                                                break;
                                }
@@ -301,7 +304,7 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
                                _dl_dprintf(2, "\n%s: ",_dl_progname);
 
                                if (symtab_index)
-                                       _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+                                       _dl_dprintf(2, "symbol '%s': ", symname);
 
 #if defined (__SUPPORT_LD_DEBUG__)
                                _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname);