diff options
| author | martin <martin@NetBSD.org> | 2011-03-30 09:22:29 +0000 |
|---|---|---|
| committer | martin <martin@NetBSD.org> | 2011-03-30 09:22:29 +0000 |
| commit | 06e2de105601f3a69b5e844d58cbd2fa9e024d08 (patch) | |
| tree | 274759a1c73d985e9e172fa432f796d04b3fb7c7 /libexec | |
| parent | 7f2251f95604b836613d40ee4c31aebe521169e3 (diff) | |
Add support for TLS relocations
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/ld.elf_so/arch/sparc/mdreloc.c | 95 |
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)) { |
