summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authormartin <martin@NetBSD.org>2011-03-30 09:22:29 +0000
committermartin <martin@NetBSD.org>2011-03-30 09:22:29 +0000
commit06e2de105601f3a69b5e844d58cbd2fa9e024d08 (patch)
tree274759a1c73d985e9e172fa432f796d04b3fb7c7 /libexec
parent7f2251f95604b836613d40ee4c31aebe521169e3 (diff)
Add support for TLS relocations
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.elf_so/arch/sparc/mdreloc.c95
1 files changed, 90 insertions, 5 deletions
diff --git a/libexec/ld.elf_so/arch/sparc/mdreloc.c b/libexec/ld.elf_so/arch/sparc/mdreloc.c
index 9f5b1b41fca..a75ee9667d6 100644
--- a/libexec/ld.elf_so/arch/sparc/mdreloc.c
+++ b/libexec/ld.elf_so/arch/sparc/mdreloc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.45 2011/03/25 18:07:06 joerg Exp $ */
+/* $NetBSD: mdreloc.c,v 1.46 2011/03/30 09:22:29 martin Exp $ */
/*-
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.45 2011/03/25 18:07:06 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.46 2011/03/30 09:22:29 martin Exp $");
#endif /* not lint */
#include <errno.h>
@@ -66,7 +66,7 @@ __RCSID("$NetBSD: mdreloc.c,v 1.45 2011/03/25 18:07:06 joerg Exp $");
#define _RF_U 0x04000000 /* Unaligned */
#define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */
#define _RF_RS(s) ( (s) & 0xff) /* right shift */
-static const int reloc_target_flags[] = {
+static const int reloc_target_flags[R_TYPE(TLS_TPOFF64)+1] = {
0, /* NONE */
_RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */
_RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */
@@ -91,6 +91,8 @@ static const int reloc_target_flags[] = {
_RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */
_RF_A| _RF_B| _RF_SZ(32) | _RF_RS(0), /* RELATIVE */
_RF_S|_RF_A| _RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */
+
+ /* TLS and 64 bit relocs not listed here... */
};
#ifdef RTLD_DEBUG_RELOC
@@ -100,6 +102,21 @@ static const char *reloc_names[] = {
"22", "13", "LO10", "GOT10", "GOT13",
"GOT22", "PC10", "PC22", "WPLT30", "COPY",
"GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32"
+
+ /* not used with 32bit userland, besides a few of the TLS ones */
+ "PLT32",
+ "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32",
+ "10", "11", "64", "OLO10", "HH22",
+ "HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22",
+ "WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6",
+ "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44",
+ "L44", "REGISTER", "UA64", "UA16",
+ "TLS_GD_HI22", "TLS_GD_LO10", "TLS_GD_ADD", "TLS_GD_CALL",
+ "TLS_LDM_HI22", "TLS_LDM_LO10", "TLS_LDM_ADD", "TLS_LDM_CALL",
+ "TLS_LDO_HIX22", "TLS_LDO_LOX10", "TLS_LDO_ADD", "TLS_IE_HI22",
+ "TLS_IE_LO10", "TLS_IE_LD", "TLS_IE_LDX", "TLS_IE_ADD", "TLS_LE_HIX22",
+ "TLS_LE_LOX10", "TLS_DTPMOD32", "TLS_DTPMOD64", "TLS_DTPOFF32",
+ "TLS_DTPOFF64", "TLS_TPOFF32", "TLS_TPOFF64",
};
#endif
@@ -110,6 +127,7 @@ static const char *reloc_names[] = {
#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0)
#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff)
#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff)
+#define RELOC_TLS(t) (t >= R_TYPE(TLS_GD_HI22))
static const int reloc_target_bitmask[] = {
#define _BM(x) (~(-(1ULL << (x))))
@@ -208,14 +226,81 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
/*
* We use the fact that relocation types are an `enum'
- * Note: R_SPARC_6 is currently numerically largest.
+ * Note: R_SPARC_TLS_TPOFF64 is currently numerically largest.
*/
- if (type > R_TYPE(6))
+ if (type > R_TYPE(TLS_TPOFF64))
return (-1);
value = rela->r_addend;
/*
+ * Handle TLS relocations here, they are different.
+ */
+ if (RELOC_TLS(type)) {
+ switch (type) {
+ case R_TYPE(TLS_DTPMOD32):
+ def = _rtld_find_symdef(symnum, obj,
+ &defobj, false);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr)defobj->tlsindex;
+
+ rdbg(("TLS_DTPMOD32 %s in %s --> %p",
+ obj->strtab +
+ obj->symtab[symnum].st_name,
+ obj->path, (void *)*where));
+
+ break;
+
+ case R_TYPE(TLS_DTPOFF32):
+ def = _rtld_find_symdef(symnum, obj,
+ &defobj, false);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr)(def->st_value
+ + rela->r_addend);
+
+ rdbg(("TLS_DTPOFF32 %s in %s --> %p",
+ obj->strtab +
+ obj->symtab[symnum].st_name,
+ obj->path, (void *)*where));
+
+ break;
+
+ case R_TYPE(TLS_TPOFF32):
+ def = _rtld_find_symdef(symnum, obj,
+ &defobj, false);
+ if (def == NULL)
+ return -1;
+
+ if (!defobj->tls_done &&
+ _rtld_tls_offset_allocate(obj))
+ return -1;
+
+ *where = (Elf_Addr)(def->st_value -
+ defobj->tlsoffset +
+ rela->r_addend);
+
+ rdbg(("TLS_TPOFF32 %s in %s --> %p",
+ obj->strtab +
+ obj->symtab[symnum].st_name,
+ obj->path, (void *)*where));
+
+ break;
+ }
+ continue;
+ }
+
+ /*
+ * If it is no TLS relocation (handled above), we can not
+ * deal with it if it is beyound R_SPARC_6.
+ */
+ if (type > R_TYPE(6))
+ return (-1);
+
+ /*
* Handle relative relocs here, as an optimization.
*/
if (type == R_TYPE(RELATIVE)) {