Add support for 64 bit TLS relocations.

This commit is contained in:
martin 2011-03-30 08:37:52 +00:00
parent a873c5cd55
commit 3a4af49105
1 changed files with 74 additions and 6 deletions

View File

@ -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 @@ __RCSID("$NetBSD: mdreloc.c,v 1.51 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 */
@ -125,6 +125,7 @@ static const int reloc_target_flags[] = {
_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 @@ static const char *reloc_names[] = {
"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 @@ 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 long reloc_target_bitmask[] = {
#define _BM(x) (~(-(1ULL << (x))))
@ -325,13 +333,73 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
/*
* 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.
*/