Module Name: src Committed By: martin Date: Wed Mar 30 09:22:29 UTC 2011
Modified Files: src/libexec/ld.elf_so/arch/sparc: mdreloc.c Log Message: Add support for TLS relocations To generate a diff of this commit: cvs rdiff -u -r1.45 -r1.46 src/libexec/ld.elf_so/arch/sparc/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/sparc/mdreloc.c diff -u src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.45 src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.46 --- src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.45 Fri Mar 25 18:07:06 2011 +++ src/libexec/ld.elf_so/arch/sparc/mdreloc.c Wed Mar 30 09:22:29 2011 @@ -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 @@ #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 @@ _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 @@ "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 @@ #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 @@ /* * 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)) {