Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/ld.elf_so/arch/sparc Add support for TLS relocations



details:   https://anonhg.NetBSD.org/src/rev/89d2b8cca4a6
branches:  trunk
changeset: 763659:89d2b8cca4a6
user:      martin <martin%NetBSD.org@localhost>
date:      Wed Mar 30 09:22:29 2011 +0000

description:
Add support for TLS relocations

diffstat:

 libexec/ld.elf_so/arch/sparc/mdreloc.c |  97 +++++++++++++++++++++++++++++++--
 1 files changed, 91 insertions(+), 6 deletions(-)

diffs (150 lines):

diff -r e1b236da2933 -r 89d2b8cca4a6 libexec/ld.elf_so/arch/sparc/mdreloc.c
--- a/libexec/ld.elf_so/arch/sparc/mdreloc.c    Wed Mar 30 08:37:52 2011 +0000
+++ b/libexec/ld.elf_so/arch/sparc/mdreloc.c    Wed Mar 30 09:22:29 2011 +0000
@@ -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,13 +226,80 @@
 
                /*
                 * 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(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);
 
-               value = rela->r_addend;
-
                /*
                 * Handle relative relocs here, as an optimization.
                 */



Home | Main Index | Thread Index | Old Index