summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldso/ldso/mips/dl-sysdep.h20
-rw-r--r--ldso/ldso/mips/elfinterp.c31
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);