Mark Wielaard c8bf00
commit f1ff8597ef9c37ff1a853411b9e3be1696c36d92
Mark Wielaard c8bf00
Author: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Mark Wielaard c8bf00
Date:   Tue Sep 19 23:17:48 2017 +0200
Mark Wielaard c8bf00
Mark Wielaard c8bf00
    Implement static TLS code for more platforms
Mark Wielaard c8bf00
    
Mark Wielaard c8bf00
    gdbserver_tests/hgtls is failing on a number of platforms
Mark Wielaard c8bf00
    as it looks like static tls handling is now needed.
Mark Wielaard c8bf00
    So, omplement static tls for a few more platforms.
Mark Wielaard c8bf00
    The formulas that are platform dependent are somewhat wild guesses
Mark Wielaard c8bf00
    obtained with trial and errors.
Mark Wielaard c8bf00
    Note that arm/arm64/ppc32 are not (yet) done
Mark Wielaard c8bf00
Mark Wielaard c8bf00
diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c
Mark Wielaard c8bf00
index 10e52fc..1f03c12 100644
Mark Wielaard c8bf00
--- a/coregrind/m_gdbserver/target.c
Mark Wielaard c8bf00
+++ b/coregrind/m_gdbserver/target.c
Mark Wielaard c8bf00
@@ -712,6 +712,7 @@ Bool valgrind_get_tls_addr (ThreadState *tst,
Mark Wielaard c8bf00
    // Check we can read the modid
Mark Wielaard c8bf00
    CHECK_DEREF(lm+lm_modid_offset, sizeof(unsigned long int), "link_map modid");
Mark Wielaard c8bf00
    modid = *(unsigned long int *)(lm+lm_modid_offset);
Mark Wielaard c8bf00
+   dlog (2, "tid %u modid %lu\n", tst->tid, modid);
Mark Wielaard c8bf00
 
Mark Wielaard c8bf00
    // Check we can access the dtv entry for modid
Mark Wielaard c8bf00
    CHECK_DEREF(dtv + 2 * modid, sizeof(CORE_ADDR), "dtv[2*modid]");
Mark Wielaard c8bf00
@@ -719,7 +720,6 @@ Bool valgrind_get_tls_addr (ThreadState *tst,
Mark Wielaard c8bf00
    // Compute the base address of the tls block.
Mark Wielaard c8bf00
    *tls_addr = *(dtv + 2 * modid);
Mark Wielaard c8bf00
 
Mark Wielaard c8bf00
-#if defined(VGA_mips32) || defined(VGA_mips64)
Mark Wielaard c8bf00
    if (*tls_addr & 1) {
Mark Wielaard c8bf00
       /* This means that computed address is not valid, most probably
Mark Wielaard c8bf00
          because given module uses Static TLS.
Mark Wielaard c8bf00
@@ -731,17 +731,24 @@ Bool valgrind_get_tls_addr (ThreadState *tst,
Mark Wielaard c8bf00
       CORE_ADDR tls_offset_addr;
Mark Wielaard c8bf00
       PtrdiffT tls_offset;
Mark Wielaard c8bf00
 
Mark Wielaard c8bf00
-      dlog(1, "computing tls_addr using static TLS\n");
Mark Wielaard c8bf00
+      dlog(2, "tls_addr (%p & 1) => computing tls_addr using static TLS\n",
Mark Wielaard c8bf00
+           (void*) *tls_addr);
Mark Wielaard c8bf00
 
Mark Wielaard c8bf00
       /* Assumes that tls_offset is placed right before tls_modid.
Mark Wielaard c8bf00
          To check the assumption, start a gdb on none/tests/tls and do:
Mark Wielaard c8bf00
-         p &((struct link_map*)0x0)->l_tls_modid
Mark Wielaard c8bf00
-         p &((struct link_map*)0x0)->l_tls_offset */
Mark Wielaard c8bf00
+           p &((struct link_map*)0x0)->l_tls_modid
Mark Wielaard c8bf00
+           p &((struct link_map*)0x0)->l_tls_offset
Mark Wielaard c8bf00
+         Instead of assuming this, we could calculate this similarly to
Mark Wielaard c8bf00
+         lm_modid_offset, by extending getplatformoffset to support querying
Mark Wielaard c8bf00
+         more than one offset.
Mark Wielaard c8bf00
+      */
Mark Wielaard c8bf00
       tls_offset_addr = lm + lm_modid_offset - sizeof(PtrdiffT);
Mark Wielaard c8bf00
 
Mark Wielaard c8bf00
       // Check we can read the tls_offset.
Mark Wielaard c8bf00
       CHECK_DEREF(tls_offset_addr, sizeof(PtrdiffT), "link_map tls_offset");
Mark Wielaard c8bf00
       tls_offset = *(PtrdiffT *)(tls_offset_addr);
Mark Wielaard c8bf00
+      dlog(2, "tls_offset_addr %p tls_offset %ld\n",
Mark Wielaard c8bf00
+           (void*)tls_offset_addr, (long)tls_offset);
Mark Wielaard c8bf00
 
Mark Wielaard c8bf00
       /* Following two values represent platform dependent constants
Mark Wielaard c8bf00
          NO_TLS_OFFSET and FORCED_DYNAMIC_TLS_OFFSET, respectively. */
Mark Wielaard c8bf00
@@ -751,9 +758,18 @@ Bool valgrind_get_tls_addr (ThreadState *tst,
Mark Wielaard c8bf00
       }
Mark Wielaard c8bf00
 
Mark Wielaard c8bf00
       // This calculation is also platform dependent.
Mark Wielaard c8bf00
+#if defined(VGA_mips32) || defined(VGA_mips64)
Mark Wielaard c8bf00
       *tls_addr = ((CORE_ADDR)dtv_loc + 2 * sizeof(CORE_ADDR) + tls_offset);
Mark Wielaard c8bf00
-   }
Mark Wielaard c8bf00
+#elif defined(VGA_ppc64be) || defined(VGA_ppc64le)
Mark Wielaard c8bf00
+      *tls_addr = ((CORE_ADDR)dtv_loc + sizeof(CORE_ADDR) + tls_offset);
Mark Wielaard c8bf00
+#elif defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x)
Mark Wielaard c8bf00
+      *tls_addr = (CORE_ADDR)dtv_loc - tls_offset - sizeof(CORE_ADDR);
Mark Wielaard c8bf00
+#else
Mark Wielaard c8bf00
+      // ppc32, arm, arm64
Mark Wielaard c8bf00
+      dlog(0, "target.c is missing platform code for static TLS\n");
Mark Wielaard c8bf00
+      return False;
Mark Wielaard c8bf00
 #endif
Mark Wielaard c8bf00
+   }
Mark Wielaard c8bf00
 
Mark Wielaard c8bf00
    // Finally, add tls variable offset to tls block base address.
Mark Wielaard c8bf00
    *tls_addr += offset;