summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'ldso')
-rw-r--r--ldso/ldso/arc/dl-debug.h15
-rw-r--r--ldso/ldso/arc/dl-sysdep.h9
-rw-r--r--ldso/ldso/arc/elfinterp.c26
3 files changed, 46 insertions, 4 deletions
diff --git a/ldso/ldso/arc/dl-debug.h b/ldso/ldso/arc/dl-debug.h
index ff559f27f..6573e5452 100644
--- a/ldso/ldso/arc/dl-debug.h
+++ b/ldso/ldso/arc/dl-debug.h
@@ -65,4 +65,19 @@ static const char *_dl_reltypes_tab[] =
"R_ARC_GOTOFF",
"R_ARC_GOTPC",
"R_ARC_GOT32",
+ "", /* 60 */
+ "",
+ "",
+ "",
+ "",
+ "", /* 65 */
+ "R_ARC_TLS_DTPMOD",
+ "R_ARC_TLS_DTPOFF",
+ "R_ARC_TLS_TPOFF",
+ "R_ARC_TLS_GD_GOT",
+ "R_ARC_TLS_GD_LD", /* 70 */
+ "R_ARC_TLS_GD_CALL",
+ "R_ARC_TLS_IE_GOT",
+ "",
+ "",
};
diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h
index af4b18064..d71e16b32 100644
--- a/ldso/ldso/arc/dl-sysdep.h
+++ b/ldso/ldso/arc/dl-sysdep.h
@@ -96,12 +96,15 @@ extern unsigned __udivmodsi4(unsigned, unsigned) attribute_hidden;
}) \
)
-/* 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_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable 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_ARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ ((((type) == R_ARC_JMP_SLOT || (type) == R_ARC_TLS_DTPMOD || \
+ (type) == R_ARC_TLS_DTPOFF || (type) == R_ARC_TLS_TPOFF) \
+ * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_ARC_COPY) * ELF_RTYPE_CLASS_COPY))
/*
diff --git a/ldso/ldso/arc/elfinterp.c b/ldso/ldso/arc/elfinterp.c
index ca0d2c16f..d26c94705 100644
--- a/ldso/ldso/arc/elfinterp.c
+++ b/ldso/ldso/arc/elfinterp.c
@@ -92,6 +92,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
unsigned long old_val = 0;
#endif
struct symbol_ref sym_ref;
+ struct elf_resolve *tls_tpnt = NULL;
reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
reloc_type = ELF_R_TYPE(rpnt->r_info);
@@ -118,15 +119,26 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
*/
if (unlikely(!symbol_addr
- && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
+ && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK
+ && ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)) {
/* Non-fatal if called from dlopen, hence different ret code */
return 1;
}
+
+ tls_tpnt = sym_ref.tpnt;
} else if (reloc_type == R_ARC_RELATIVE ) {
*reloc_addr += tpnt->loadaddr;
goto log_entry;
}
+#if defined USE_TLS && USE_TLS
+ /* 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 (!tls_tpnt)
+ tls_tpnt = tpnt;
+#endif
+
switch (reloc_type) {
case R_ARC_32:
*reloc_addr += symbol_addr + rpnt->r_addend;
@@ -142,6 +154,18 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
_dl_memcpy((void *) reloc_addr,(void *) symbol_addr,
symtab[symtab_index].st_size);
break;
+#if defined USE_TLS && USE_TLS
+ case R_ARC_TLS_DTPMOD:
+ *reloc_addr = tls_tpnt->l_tls_modid;
+ break;
+ case R_ARC_TLS_DTPOFF:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_ARC_TLS_TPOFF:
+ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+ *reloc_addr = tls_tpnt->l_tls_offset + symbol_addr + rpnt->r_addend;
+ break;
+#endif
default:
return -1;
}