Module Name:    src
Committed By:   martin
Date:           Wed Mar 30 08:37:52 UTC 2011

Modified Files:
        src/libexec/ld.elf_so/arch/sparc64: mdreloc.c

Log Message:
Add support for 64 bit TLS relocations.


To generate a diff of this commit:
cvs rdiff -u -r1.51 -r1.52 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.51 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.52
--- src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.51	Fri Mar 25 18:07:06 2011
+++ src/libexec/ld.elf_so/arch/sparc64/mdreloc.c	Wed Mar 30 08:37:52 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.51 2011/03/25 18:07:06 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.52 2011/03/30 08:37:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2000 Eduardo Horvath.
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.51 2011/03/25 18:07:06 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.52 2011/03/30 08:37:52 martin Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -67,7 +67,7 @@
 #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 */
@@ -125,6 +125,7 @@
 	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* REGISTER */
 	_RF_S|_RF_A|	_RF_U|	_RF_SZ(64) | _RF_RS(0),		/* UA64 */
 	_RF_S|_RF_A|	_RF_U|	_RF_SZ(16) | _RF_RS(0),		/* UA16 */
+/* TLS relocs not represented here! */
 };
 
 #ifdef RTLD_DEBUG_RELOC
@@ -139,7 +140,13 @@
 	"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"
+	"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
 
@@ -150,6 +157,7 @@
 #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 long reloc_target_bitmask[] = {
 #define _BM(x)	(~(-(1ULL << (x))))
@@ -325,14 +333,74 @@
 
 		/*
 		 * We use the fact that relocation types are an `enum'
-		 * Note: R_SPARC_UA16 is currently numerically largest.
+		 * Note: R_SPARC_TLS_TPOFF64 is currently numerically largest.
 		 */
-		if (type > R_TYPE(UA16))
+		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_DTPMOD64):
+					def = _rtld_find_symdef(symnum, obj,
+					    &defobj, false);
+					if (def == NULL)
+						return -1;
+
+					*where = (Elf64_Addr)defobj->tlsindex;
+
+					rdbg(("TLS_DTPMOD64 %s in %s --> %p",
+					    obj->strtab +
+					    obj->symtab[symnum].st_name,
+					    obj->path, (void *)*where));
+
+					break;
+
+				case R_TYPE(TLS_DTPOFF64):
+					def = _rtld_find_symdef(symnum, obj,
+					    &defobj, false);
+					if (def == NULL)
+						return -1;
+
+					*where = (Elf64_Addr)(def->st_value
+					    + rela->r_addend);
+
+					rdbg(("DTPOFF64 %s in %s --> %p",
+					    obj->strtab +
+					        obj->symtab[symnum].st_name,
+					    obj->path, (void *)*where));
+
+					break;
+
+				case R_TYPE(TLS_TPOFF64):
+					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 = (Elf64_Addr)(def->st_value -
+			                            defobj->tlsoffset +
+						    rela->r_addend);
+
+		                        rdbg(("TLS_TPOFF64 %s in %s --> %p",
+		                            obj->strtab +
+					    obj->symtab[symnum].st_name,
+		                            obj->path, (void *)*where));
+
+	                		break;
+			}
+			continue;
+		}
+
+		/*
 		 * Handle relative relocs here, as an optimization.
 		 */
 		if (type == R_TYPE(RELATIVE)) {

Reply via email to