diff options
-rw-r--r-- | ldso/ldso/mips/dl-sysdep.h | 20 | ||||
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 31 |
2 files changed, 35 insertions, 16 deletions
diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h index 30d84fbc5..c1aad6661 100644 --- a/ldso/ldso/mips/dl-sysdep.h +++ b/ldso/ldso/mips/dl-sysdep.h @@ -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 diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 40c3e0939..149fc5674 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -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); |