about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/dl-tls.c25
-rw-r--r--sysdeps/generic/ldsodefs.h5
-rw-r--r--sysdeps/i386/dl-tls.h8
3 files changed, 32 insertions, 6 deletions
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 729adf0040..1b16bd58f4 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -103,7 +103,21 @@ _dl_determine_tlsoffset (struct link_map *firstp)
 
   /* The thread descriptor (pointed to by the thread pointer) has its
      own alignment requirement.  Adjust the static TLS size
-     appropriately.  */
+     and TLS offsets appropriately.  */
+  if (offset % TLS_TCB_ALIGN != 0)
+    {
+      size_t add = TLS_TCB_ALIGN - offset % TLS_TCB_ALIGN;
+
+      /* XXX If the offset stored is negative we must subtract here.  */
+      offset += add;
+
+      runp = firstp;
+      do
+	runp->l_tls_offset += add;
+      while ((runp = runp->l_tls_nextimage) != firstp);
+    }
+
+  GL(dl_tls_static_size) = offset + TLS_TCB_SIZE;
 # elif TLS_DTV_AT_TP
   struct link_map *lastp;
 
@@ -121,10 +135,17 @@ _dl_determine_tlsoffset (struct link_map *firstp)
       offset = roundup (offset + lastp->l_tls_blocksize, runp->l_tls_align);
 
       runp->l_tls_offset = offset;
+
+      lastp = runp;
     }
+
+  GL(dl_tls_static_size) = offset + lastp->l_tls_blocksize;
 # else
 #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
 # endif
+
+  /* The alignment requirement for the static TLS block.  */
+  GL(dl_tls_static_align) = MAX (TLS_TCB_ALIGN, max_align);
 }
 
 
@@ -136,7 +157,7 @@ _dl_determine_tlsoffset (struct link_map *firstp)
    it.  Users of the IA-64 form have to provide adequate definitions
    of the following macros.  */
 # ifndef GET_ADDR_ARGS
-#  define GET_ADDR_ARGS struct tls_index *ti
+#  define GET_ADDR_ARGS tls_index *ti
 # endif
 # ifndef GET_ADDR_MODULE
 #  define GET_ADDR_MODULE ti->ti_module
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 9913820b03..f049878cbd 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -298,6 +298,11 @@ struct rtld_global
   EXTERN size_t _dl_tls_max_dtv_idx;
   /* Flag signalling whether there are gaps in the module ID allocation.  */
   EXTERN bool _dl_tls_dtv_gaps;
+
+  /* Size of the static TLS block.  */
+  EXTERN size_t _dl_tls_static_size;
+  /* Alignment requirement of the static TLS block.  */
+  EXTERN size_t _dl_tls_static_align;
 #endif
 
   /* Name of the shared object to be profiled (if any).  */
diff --git a/sysdeps/i386/dl-tls.h b/sysdeps/i386/dl-tls.h
index 5398609748..7fe4be8e62 100644
--- a/sysdeps/i386/dl-tls.h
+++ b/sysdeps/i386/dl-tls.h
@@ -19,15 +19,15 @@
 
 #ifdef USE_TLS
 /* Type used for the representation of TLS information in the GOT.  */
-struct tls_index
+typedef struct
 {
   unsigned long int ti_module;
   unsigned long int ti_offset;
-};
+} tls_index;
 
 
 /* This is the prototype for the GNU version.  */
-extern void *___tls_get_addr (struct tls_index *ti)
+extern void *___tls_get_addr (tls_index *ti)
      __attribute__ ((__regparm__ (1)));
 
 /* The special thing about the x86 TLS ABI is that we have two
@@ -37,7 +37,7 @@ extern void *___tls_get_addr (struct tls_index *ti)
    an additional underscore at the beginning.  The Sun version uses
    the normal calling convention.  */
 void *
-__tls_get_addr (struct tls_index *ti)
+__tls_get_addr (tls_index *ti)
 {
   return ___tls_get_addr (ti);
 }