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)) {