Fix LinuxThreads 2.4 build for various TLS targets

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Fix LinuxThreads 2.4 build for various TLS targets

Daniel Jacobowitz-2
LinuxThreads hasn't built on targets with pointer guards in a while,
because the bits in libc/sysdeps/ reference members of the TCB that
were defined under nptl/sysdeps/.  This updates LinuxThreads to match.
I've only tested i686 and x86_64.

By the way, as many people have discovered for themselves, building a
default i686-pc-linux-gnu configuration with LinuxThreads doesn't work
(errors finding _errno, _h_errno, _res).  I'm not planning to fix this,
since it is symptomatic of a larger problem that would take some
work to get right: we lie to LinuxThreads about whether TLS is
available if we support a kernel too early to use FLOATING_STACKS.

It's easy to fix: either --enable-kernel=2.4.0, or --without-__thread.
Both of those will give you a dynamic linker which supports TLS.  The
former will give you a LinuxThreads which uses it, the latter won't.
The problem only arose when LinuxThreads was configured not to use
__thread variables, but libc was configured to use __thread int errno.

No relation to the i486/i586 TLS build failure reported recently.

--
Daniel Jacobowitz
CodeSourcery

2006-04-26  Daniel Jacobowitz  <[hidden email]>

        Import pointer and stack guard changes from NPTL.
        * descr.h (struct _pthread_descr_struct): Include sysinfo
        unconditionally.  Add stack_guard and pointer_guard.
        (PTHREAD_STRUCT_END_PADDING): Define.
        * manager.c (pthread_handle_create): Copy the pointer and
        stack guards.
        * pthread.c (__pthread_initialize_manager): Likewise.

        * sysdeps/i386/tcb-offsets.sym: Add POINTER_GUARD.
        * sysdeps/i386/tls.h (tcbhead_t): Add stack_guard and pointer_guard.
        (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD,
        THREAD_SET_POINTER_GUARD, THREAD_COPY_POINTER_GUARD): Define.
        * sysdeps/ia64/tls.h (TLS_PRE_TCB_SIZE): If PTHREAD_STRUCT_END_PADDING
        is smaller than 16 bytes, increase TLS_PRE_TCB_SIZE by 16 bytes.
        (THREAD_SYSINFO, THREAD_SELF): Don't assume TLS_PRE_TCB_SIZE is
        sizeof (struct _pthread_descr_struct).
        (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD,
        THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD,
        THREAD_COPY_POINTER_GUARD): Define.
        * sysdeps/ia64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET):
        Use TLS_PRE_TCB_SIZE instead of sizeof (struct pthread).
        * sysdeps/powerpc/tcb-offsets.sym (POINTER_GUARD): Add.
        * sysdeps/powerpc/tls.h (tcbhead_t): Add stack_guard and
        pointer_guard.
        (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD,
        THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD,
        THREAD_COPY_POINTER_GUARD): Define.
        * sysdeps/s390/tcb-offsets.sym (STACK_GUARD): Add.
        * sysdeps/s390/tls.h (tcbhead_t): Add stack_guard
        field.  Put in sysinfo field unconditionally.
        (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD,
        THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD,
        THREAD_COPY_POINTER_GUARD): Define.
        * sysdeps/sh/tcb-offsets.sym: Add POINTER_GUARD.
        * sysdeps/sh/tls.h (tcbhead_t): Remove private and add pointer_guard.
        (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD,
        THREAD_COPY_POINTER_GUARD): Define.
        * sysdeps/sparc/tls.h (tcbhead_t): Add sysinfo, stack_guard,
        and pointer_guard fields.
        (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD,
        THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD,
        THREAD_COPY_POINTER_GUARD): Define.
        * sysdeps/sparc/tcb-offsets.sym (POINTER_GUARD): Define.
        * sysdeps/x86_64/tcb-offsets.sym (POINTER_GUARD): New.
        * sysdeps/x86_64/tls.h: Include <stdint.h>.
        (tcbhead_t): Add sysinfo, stack_guard, and pointer_guard.
        (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD,
        THREAD_SET_POINTER_GUARD, THREAD_COPY_POINTER_GUARD): New.
        * Makefile: Add rules to build and run tst-stackguard1{,-static}
        tests.
        * tst-stackguard1.c: New file.
        * tst-stackguard1-static.c: New file.

Index: linuxthreads/Makefile
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/Makefile,v
retrieving revision 1.100
diff -u -p -r1.100 Makefile
--- linuxthreads/Makefile 28 Feb 2006 07:13:34 -0000 1.100
+++ linuxthreads/Makefile 26 Apr 2006 14:58:00 -0000
@@ -117,13 +117,14 @@ test-srcs = tst-signal
 tests-reverse += tst-cancel5
 
 ifeq ($(build-static),yes)
-tests += tststatic tst-static-locale tst-cancel-static
-tests-static += tststatic tst-static-locale tst-cancel-static
+tests += tststatic tst-static-locale tst-cancel-static tst-stackguard1-static
+tests-static += tststatic tst-static-locale tst-cancel-static \
+ tst-stackguard1-static
 endif
 
 ifeq (yes,$(build-shared))
 tests-nodelete-yes = unload
-tests += tst-tls1 tst-_res1
+tests += tst-tls1 tst-_res1 tst-stackguard1
 endif
 
 modules-names = tst-_res1mod1 tst-_res1mod2 \
@@ -340,3 +341,6 @@ $(objpfx)tst-cancel-wrappers.out: tst-ca
 generated += tst-signal.out tst-cancel-wrappers.out
 endif
 endif
+
+tst-stackguard1-ARGS = --command "$(built-program-cmd) --child"
+tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
Index: linuxthreads/descr.h
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/descr.h,v
retrieving revision 1.16
diff -u -p -r1.16 descr.h
--- linuxthreads/descr.h 11 Nov 2005 22:30:26 -0000 1.16
+++ linuxthreads/descr.h 26 Apr 2006 14:58:00 -0000
@@ -120,9 +120,9 @@ struct _pthread_descr_struct
       union dtv *dtvp;
       pthread_descr self; /* Pointer to this structure */
       int multiple_threads;
-# ifdef NEED_DL_SYSINFO
       uintptr_t sysinfo;
-# endif
+      uintptr_t stack_guard;
+      uintptr_t pointer_guard;
     } data;
     void *__padding[16];
   } p_header;
@@ -190,6 +190,13 @@ struct _pthread_descr_struct
   size_t p_alloca_cutoff; /* Maximum size which should be allocated
    using alloca() instead of malloc().  */
   /* New elements must be added at the end.  */
+
+  /* This member must be last.  */
+  char end_padding[];
+
+#define PTHREAD_STRUCT_END_PADDING \
+  (sizeof (struct _pthread_descr_struct)      \
+   - offsetof (struct _pthread_descr_struct, end_padding))
 } __attribute__ ((aligned(32))); /* We need to align the structure so that
     doubles are aligned properly.  This is 8
     bytes on MIPS and 16 bytes on MIPS64.
Index: linuxthreads/manager.c
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/manager.c,v
retrieving revision 1.98
diff -u -p -r1.98 manager.c
--- linuxthreads/manager.c 3 May 2004 21:41:23 -0000 1.98
+++ linuxthreads/manager.c 26 Apr 2006 14:58:01 -0000
@@ -670,6 +670,17 @@ static int pthread_handle_create(pthread
   new_thread->p_inheritsched = attr ? attr->__inheritsched : 0;
   new_thread->p_alloca_cutoff = stksize / 4 > __MAX_ALLOCA_CUTOFF
  ? __MAX_ALLOCA_CUTOFF : stksize / 4;
+
+  /* Copy the stack guard canary.  */
+#ifdef THREAD_COPY_STACK_GUARD
+  THREAD_COPY_STACK_GUARD (new_thread);
+#endif
+
+  /* Copy the pointer guard value.  */
+#ifdef THREAD_COPY_POINTER_GUARD
+  THREAD_COPY_POINTER_GUARD (new_thread);
+#endif
+
   /* Initialize the thread handle */
   __pthread_init_lock(&__pthread_handles[sseg].h_lock);
   __pthread_handles[sseg].h_descr = new_thread;
Index: linuxthreads/pthread.c
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/pthread.c,v
retrieving revision 1.136
diff -u -p -r1.136 pthread.c
--- linuxthreads/pthread.c 9 Jan 2005 20:02:37 -0000 1.136
+++ linuxthreads/pthread.c 26 Apr 2006 14:58:01 -0000
@@ -696,6 +696,16 @@ int __pthread_initialize_manager(void)
   mgr = &__pthread_manager_thread;
 #endif
 
+  /* Copy the stack guard canary.  */
+#ifdef THREAD_COPY_STACK_GUARD
+  THREAD_COPY_STACK_GUARD (mgr);
+#endif
+
+  /* Copy the pointer guard value.  */
+#ifdef THREAD_COPY_POINTER_GUARD
+  THREAD_COPY_POINTER_GUARD (mgr);
+#endif
+
   __pthread_manager_request = manager_pipe[1]; /* writing end */
   __pthread_manager_reader = manager_pipe[0]; /* reading end */
 
Index: linuxthreads/tst-stackguard1-static.c
===================================================================
RCS file: linuxthreads/tst-stackguard1-static.c
diff -N linuxthreads/tst-stackguard1-static.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ linuxthreads/tst-stackguard1-static.c 26 Apr 2006 14:58:01 -0000
@@ -0,0 +1 @@
+#include "tst-stackguard1.c"
Index: linuxthreads/tst-stackguard1.c
===================================================================
RCS file: linuxthreads/tst-stackguard1.c
diff -N linuxthreads/tst-stackguard1.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ linuxthreads/tst-stackguard1.c 26 Apr 2006 14:58:01 -0000
@@ -0,0 +1,226 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <[hidden email]>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <elf/stackguard-macros.h>
+#include <unistd.h>
+
+static const char *command;
+static bool child;
+static uintptr_t stack_chk_guard_copy;
+static bool stack_chk_guard_copy_set;
+static int fds[2];
+
+static void __attribute__ ((constructor))
+con (void)
+{
+  stack_chk_guard_copy = STACK_CHK_GUARD;
+  stack_chk_guard_copy_set = true;
+}
+
+static int
+uintptr_t_cmp (const void *a, const void *b)
+{
+  if (*(uintptr_t *) a < *(uintptr_t *) b)
+    return 1;
+  if (*(uintptr_t *) a > *(uintptr_t *) b)
+    return -1;
+  return 0;
+}
+
+static void *
+tf (void *arg)
+{
+  if (stack_chk_guard_copy != STACK_CHK_GUARD)
+    {
+      puts ("STACK_CHK_GUARD changed in thread");
+      return (void *) 1L;
+    }
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  if (!stack_chk_guard_copy_set)
+    {
+      puts ("constructor has not been run");
+      return 1;
+    }
+
+  if (stack_chk_guard_copy != STACK_CHK_GUARD)
+    {
+      puts ("STACK_CHK_GUARD changed between constructor and do_test");
+      return 1;
+    }
+
+  if (child)
+    {
+      int i;
+      pthread_t th[4];
+      void *ret;
+      for (i = 0; i < 4; ++i)
+ if (pthread_create (&th[i], NULL, tf, NULL))
+  {
+    puts ("thread creation failed");
+    return 1;
+  }
+      for (i = 0; i < 4; ++i)
+ if (pthread_join (th[i], &ret))
+  {
+    puts ("thread join failed");
+    return 1;
+  }
+ else if (ret != NULL)
+  return 1;
+
+      write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
+      return 0;
+    }
+
+  if (command == NULL)
+    {
+      puts ("missing --command or --child argument");
+      return 1;
+    }
+
+#define N 16
+  uintptr_t child_stack_chk_guards[N + 1];
+  child_stack_chk_guards[N] = stack_chk_guard_copy;
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      if (pipe (fds) < 0)
+ {
+  printf ("couldn't create pipe: %m\n");
+  return 1;
+ }
+
+      pid_t pid = fork ();
+      if (pid < 0)
+ {
+  printf ("fork failed: %m\n");
+  return 1;
+ }
+
+      if (!pid)
+ {
+  if (stack_chk_guard_copy != STACK_CHK_GUARD)
+    {
+      puts ("STACK_CHK_GUARD changed after fork");
+      exit (1);
+    }
+
+  close (fds[0]);
+  close (2);
+  dup2 (fds[1], 2);
+  close (fds[1]);
+
+  system (command);
+  exit (0);
+ }
+
+      close (fds[1]);
+
+      if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
+    sizeof (uintptr_t))) != sizeof (uintptr_t))
+ {
+  puts ("could not read stack_chk_guard value from child");
+  return 1;
+ }
+
+      close (fds[0]);
+
+      pid_t termpid;
+      int status;
+      termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+      if (termpid == -1)
+ {
+  printf ("waitpid failed: %m\n");
+  return 1;
+ }
+      else if (termpid != pid)
+ {
+  printf ("waitpid returned %ld != %ld\n",
+  (long int) termpid, (long int) pid);
+  return 1;
+ }
+      else if (!WIFEXITED (status) || WEXITSTATUS (status))
+ {
+  puts ("child hasn't exited with exit status 0");
+  return 1;
+ }
+    }
+
+  qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
+
+  uintptr_t default_guard = 0;
+  unsigned char *p = (unsigned char *) &default_guard;
+  p[sizeof (uintptr_t) - 1] = 255;
+  p[sizeof (uintptr_t) - 2] = '\n';
+  p[0] = 0;
+
+  /* Test if the stack guard canaries are either randomized,
+     or equal to the default stack guard canary value.
+     Even with randomized stack guards it might happen
+     that the random number generator generates the same
+     values, but if that happens in more than half from
+     the 16 runs, something is very wrong.  */
+  int ndifferences = 0;
+  int ndefaults = 0;
+  for (i = 0; i < N; ++i)
+    {
+      if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
+ ndifferences++;
+      else if (child_stack_chk_guards[i] == default_guard)
+ ndefaults++;
+    }
+
+  printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+
+  if (ndifferences < N / 2 && ndefaults < N / 2)
+    {
+      puts ("stack guard canaries are not randomized enough");
+      puts ("nor equal to the default canary value");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define OPT_COMMAND 10000
+#define OPT_CHILD 10001
+#define CMDLINE_OPTIONS \
+  { "command", required_argument, NULL, OPT_COMMAND },  \
+  { "child", no_argument, NULL, OPT_CHILD },
+#define CMDLINE_PROCESS \
+  case OPT_COMMAND: \
+    command = optarg; \
+    break; \
+  case OPT_CHILD: \
+    child = true; \
+    break;
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: linuxthreads/sysdeps/i386/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/i386/tcb-offsets.sym,v
retrieving revision 1.1
diff -u -p -r1.1 tcb-offsets.sym
--- linuxthreads/sysdeps/i386/tcb-offsets.sym 28 Dec 2002 22:07:24 -0000 1.1
+++ linuxthreads/sysdeps/i386/tcb-offsets.sym 26 Apr 2006 14:58:01 -0000
@@ -5,3 +5,4 @@ MULTIPLE_THREADS_OFFSET offsetof (tcbhe
 #ifdef NEED_DL_SYSINFO
 SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo)
 #endif
+POINTER_GUARD offsetof (tcbhead_t, pointer_guard)
Index: linuxthreads/sysdeps/i386/tls.h
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/i386/tls.h,v
retrieving revision 1.38
diff -u -p -r1.38 tls.h
--- linuxthreads/sysdeps/i386/tls.h 9 Jan 2005 20:01:13 -0000 1.38
+++ linuxthreads/sysdeps/i386/tls.h 26 Apr 2006 14:58:01 -0000
@@ -47,9 +47,9 @@ typedef struct
   dtv_t *dtv;
   void *self; /* Pointer to the thread descriptor.  */
   int multiple_threads;
-#ifdef NEED_DL_SYSINFO
   uintptr_t sysinfo;
-#endif
+  uintptr_t stack_guard;
+  uintptr_t pointer_guard;
 } tcbhead_t;
 
 #else /* __ASSEMBLER__ */
@@ -224,6 +224,23 @@ TLS_DO_MODIFY_LDT_KERNEL_CHECK(  
   ({ struct _pthread_descr_struct *__descr;      \
      THREAD_GETMEM (__descr, p_header.data.dtvp); })
 
+
+/* Set the stack guard field in TCB head.  */
+#define THREAD_SET_STACK_GUARD(value) \
+  THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value)
+#define THREAD_COPY_STACK_GUARD(descr) \
+  ((descr)->p_header.data.stack_guard      \
+   = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard))
+
+
+/* Set the pointer guard field in the TCB head.  */
+#define THREAD_SET_POINTER_GUARD(value) \
+  THREAD_SETMEM (THREAD_SELF, p_header.data.pointer_guard, value)
+#define THREAD_COPY_POINTER_GUARD(descr) \
+  ((descr)->p_header.data.pointer_guard      \
+   = THREAD_GETMEM (THREAD_SELF, p_header.data.pointer_guard))
+
+
 # endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
 #endif /* __ASSEMBLER__ */
 
Index: linuxthreads/sysdeps/ia64/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/ia64/tcb-offsets.sym,v
retrieving revision 1.6
diff -u -p -r1.6 tcb-offsets.sym
--- linuxthreads/sysdeps/ia64/tcb-offsets.sym 25 Apr 2003 22:04:27 -0000 1.6
+++ linuxthreads/sysdeps/ia64/tcb-offsets.sym 26 Apr 2006 14:58:01 -0000
@@ -3,7 +3,7 @@
 
 --
 #ifdef USE_TLS
-MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) - sizeof (struct _pthread_descr_struct)
+MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) - TCB_PRE_SIZE
 #else
 MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
 #endif
Index: linuxthreads/sysdeps/ia64/tls.h
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/ia64/tls.h,v
retrieving revision 1.10
diff -u -p -r1.10 tls.h
--- linuxthreads/sysdeps/ia64/tls.h 9 Jan 2005 20:01:13 -0000 1.10
+++ linuxthreads/sysdeps/ia64/tls.h 26 Apr 2006 14:58:01 -0000
@@ -64,8 +64,16 @@ typedef struct
 /* This is the size of the TCB.  */
 #  define TLS_TCB_SIZE sizeof (tcbhead_t)
 
-/* This is the size we need before TCB.  */
-#  define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
+/* This is the size we need before TCB.
+   If there is not any room for uintptr_t stack_guard and
+   uintptr_t pointer_guard in struct pthread's final padding,
+   we need to put struct pthread 16 byte slower.  */
+# define TLS_PRE_TCB_SIZE \
+  (sizeof (struct pthread) \
+   + (PTHREAD_STRUCT_END_PADDING < 2 * sizeof (uintptr_t) \
+      ? ((2 * sizeof (uintptr_t) + __alignof__ (struct pthread) - 1) \
+ & ~(__alignof__ (struct pthread) - 1)) \
+      : 0))
 
 /* Alignment requirements for the TCB.  */
 #  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
@@ -105,7 +113,8 @@ typedef struct
 
 /* Return the thread descriptor for the current thread.  */
 #  undef THREAD_SELF
-#  define THREAD_SELF (__thread_self - 1)
+#  define THREAD_SELF \
+  ((struct pthread *) ((char *) __thread_self - TLS_PRE_TCB_SIZE))
 
 #  undef INIT_THREAD_SELF
 #  define INIT_THREAD_SELF(descr, nr) \
@@ -113,6 +122,22 @@ typedef struct
 
 # define TLS_MULTIPLE_THREADS_IN_TCB 1
 
+/* Set the stack guard field in TCB head.  */
+#define THREAD_SET_STACK_GUARD(value) \
+  (((uintptr_t *) __thread_self)[-1] = (value))
+#define THREAD_COPY_STACK_GUARD(descr) \
+  (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-1] \
+   = ((uintptr_t *) __thread_self)[-1])
+
+/* Set the pointer guard field in TCB head.  */
+#define THREAD_GET_POINTER_GUARD() \
+  (((uintptr_t *) __thread_self)[-2])
+#define THREAD_SET_POINTER_GUARD(value) \
+  (((uintptr_t *) __thread_self)[-2] = (value))
+#define THREAD_COPY_POINTER_GUARD(descr) \
+  (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-2] \
+   = THREAD_GET_POINTER_GUARD ())
+
 /* Get the thread descriptor definition.  */
 #  include <linuxthreads/descr.h>
 
Index: linuxthreads/sysdeps/powerpc/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/powerpc/tcb-offsets.sym,v
retrieving revision 1.8
diff -u -p -r1.8 tcb-offsets.sym
--- linuxthreads/sysdeps/powerpc/tcb-offsets.sym 5 Mar 2005 19:27:55 -0000 1.8
+++ linuxthreads/sysdeps/powerpc/tcb-offsets.sym 26 Apr 2006 14:58:01 -0000
@@ -17,3 +17,4 @@
 # endif
 
 MULTIPLE_THREADS_OFFSET thread_offsetof (multiple_threads)
+POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
Index: linuxthreads/sysdeps/powerpc/tls.h
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/powerpc/tls.h,v
retrieving revision 1.9
diff -u -p -r1.9 tls.h
--- linuxthreads/sysdeps/powerpc/tls.h 9 Jan 2005 20:01:14 -0000 1.9
+++ linuxthreads/sysdeps/powerpc/tls.h 26 Apr 2006 14:58:01 -0000
@@ -48,11 +48,13 @@ typedef union dtv
 
 # ifndef __ASSEMBLER__
 
-/* This layout is actually wholly private and not affected by the ABI.
-   Nor does it overlap the pthread data structure, so we need nothing
-   extra here at all.  */
+/* The stack_guard is accessed directly by GCC -fstack-protector code,
+   so it is a part of public ABI.  The dtv and pointer_guard fields
+   are private.  */
 typedef struct
-{
+{
+  uintptr_t pointer_guard;
+  uintptr_t stack_guard;
   dtv_t *dtv;
 } tcbhead_t;
 
@@ -131,6 +133,27 @@ typedef struct
    See below.  */
 #  define TLS_MULTIPLE_THREADS_IN_TCB 1
 
+/* Set the stack guard field in TCB head.  */
+# define THREAD_SET_STACK_GUARD(value) \
+    (((tcbhead_t *) ((char *) __thread_register      \
+     - TLS_TCB_OFFSET))[-1].stack_guard = (value))
+# define THREAD_COPY_STACK_GUARD(descr) \
+    (((tcbhead_t *) ((char *) (descr)      \
+     + TLS_PRE_TCB_SIZE))[-1].stack_guard      \
+     = ((tcbhead_t *) ((char *) __thread_register      \
+       - TLS_TCB_OFFSET))[-1].stack_guard)
+
+/* Set the stack guard field in TCB head.  */
+# define THREAD_GET_POINTER_GUARD() \
+    (((tcbhead_t *) ((char *) __thread_register      \
+     - TLS_TCB_OFFSET))[-1].pointer_guard)
+# define THREAD_SET_POINTER_GUARD(value) \
+    (THREAD_GET_POINTER_GUARD () = (value))
+# define THREAD_COPY_POINTER_GUARD(descr) \
+    (((tcbhead_t *) ((char *) (descr)      \
+     + TLS_PRE_TCB_SIZE))[-1].pointer_guard      \
+     = THREAD_GET_POINTER_GUARD())
+
 /* Get the thread descriptor definition.  */
 #  include <linuxthreads/descr.h>
 
Index: linuxthreads/sysdeps/s390/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/s390/tcb-offsets.sym,v
retrieving revision 1.1
diff -u -p -r1.1 tcb-offsets.sym
--- linuxthreads/sysdeps/s390/tcb-offsets.sym 5 Jan 2003 05:09:19 -0000 1.1
+++ linuxthreads/sysdeps/s390/tcb-offsets.sym 26 Apr 2006 14:58:01 -0000
@@ -2,3 +2,4 @@
 #include <tls.h>
 
 MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
+STACK_GUARD offsetof (tcbhead_t, stack_guard)
Index: linuxthreads/sysdeps/s390/tls.h
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/s390/tls.h,v
retrieving revision 1.4
diff -u -p -r1.4 tls.h
--- linuxthreads/sysdeps/s390/tls.h 9 Jan 2005 20:01:14 -0000 1.4
+++ linuxthreads/sysdeps/s390/tls.h 26 Apr 2006 14:58:01 -0000
@@ -44,6 +44,8 @@ typedef struct
   dtv_t *dtv;
   void *self; /* Pointer to the thread descriptor.  */
   int multiple_threads;
+  uintptr_t sysinfo;
+  uintptr_t stack_guard;
 } tcbhead_t;
 
 #else /* __ASSEMBLER__ */
@@ -122,6 +124,20 @@ typedef struct
 #  define THREAD_DTV() \
   (((tcbhead_t *) __builtin_thread_pointer ())->dtv)
 
+/* Set the stack guard field in TCB head.  */
+#define THREAD_SET_STACK_GUARD(value) \
+  THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
+#define THREAD_COPY_STACK_GUARD(descr) \
+  ((descr)->header.stack_guard      \
+   = THREAD_GETMEM (THREAD_SELF, header.stack_guard))
+
+/* s390 doesn't have HP_TIMING_*, so for the time being
+   use stack_guard as pointer_guard.  */
+#define THREAD_GET_POINTER_GUARD() \
+  THREAD_GETMEM (THREAD_SELF, header.stack_guard)
+#define THREAD_SET_POINTER_GUARD(value)
+#define THREAD_COPY_POINTER_GUARD(descr)
+
 # endif /* __ASSEMBLER__ */
 
 #else /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
Index: linuxthreads/sysdeps/sh/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/sh/tcb-offsets.sym,v
retrieving revision 1.4
diff -u -p -r1.4 tcb-offsets.sym
--- linuxthreads/sysdeps/sh/tcb-offsets.sym 25 Apr 2003 22:08:05 -0000 1.4
+++ linuxthreads/sysdeps/sh/tcb-offsets.sym 26 Apr 2006 14:58:01 -0000
@@ -8,3 +8,4 @@ TLS_PRE_TCB_SIZE sizeof (struct _pthread
 #else
 MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
 #endif
+POINTER_GUARD offsetof (tcbhead_t, pointer_guard)
Index: linuxthreads/sysdeps/sh/tls.h
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/sh/tls.h,v
retrieving revision 1.11
diff -u -p -r1.11 tls.h
--- linuxthreads/sysdeps/sh/tls.h 12 Nov 2005 00:49:59 -0000 1.11
+++ linuxthreads/sysdeps/sh/tls.h 26 Apr 2006 14:58:01 -0000
@@ -63,7 +63,7 @@ typedef union dtv
 typedef struct
 {
   dtv_t *dtv;
-  void *private;
+  uintptr_t pointer_guard;
 } tcbhead_t;
 
 /* This is the size of the initial TCB.  */
@@ -126,6 +126,19 @@ typedef struct
 
 # define TLS_MULTIPLE_THREADS_IN_TCB 1
 
+#define THREAD_GET_POINTER_GUARD() \
+  ({ tcbhead_t *__tcbp;      \
+     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));      \
+     __tcbp->pointer_guard;})
+ #define THREAD_SET_POINTER_GUARD(value) \
+  ({ tcbhead_t *__tcbp;      \
+     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));      \
+     __tcbp->pointer_guard = (value);})
+#define THREAD_COPY_POINTER_GUARD(descr) \
+  ({ tcbhead_t *__tcbp;      \
+     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));      \
+     ((tcbhead_t *) (descr + 1))->pointer_guard = __tcbp->pointer_guard;})
+
 /* Get the thread descriptor definition.  This must be after the
    the definition of THREAD_SELF for TLS.  */
 #  include <linuxthreads/descr.h>
Index: linuxthreads/sysdeps/sparc/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/sparc/tcb-offsets.sym,v
retrieving revision 1.1
diff -u -p -r1.1 tcb-offsets.sym
--- linuxthreads/sysdeps/sparc/tcb-offsets.sym 28 Dec 2002 22:12:30 -0000 1.1
+++ linuxthreads/sysdeps/sparc/tcb-offsets.sym 26 Apr 2006 14:58:01 -0000
@@ -2,3 +2,4 @@
 #include <tls.h>
 
 MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
+POINTER_GUARD offsetof (tcbhead_t, pointer_guard)
Index: linuxthreads/sysdeps/sparc/tls.h
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/sparc/tls.h,v
retrieving revision 1.4
diff -u -p -r1.4 tls.h
--- linuxthreads/sysdeps/sparc/tls.h 9 Jan 2005 20:01:15 -0000 1.4
+++ linuxthreads/sysdeps/sparc/tls.h 26 Apr 2006 14:58:01 -0000
@@ -44,6 +44,9 @@ typedef struct
   dtv_t *dtv;
   void *self; /* Pointer to the thread descriptor.  */
   int multiple_threads;
+  uintptr_t sysinfo;
+  uintptr_t stack_guard;
+  uintptr_t pointer_guard;
 } tcbhead_t;
 
 #else /* __ASSEMBLER__ */
@@ -99,6 +102,21 @@ typedef struct
 #  define THREAD_DTV() \
   (((tcbhead_t *) __thread_self)->dtv)
 
+/* Set the stack guard field in TCB head.  */
+#define THREAD_SET_STACK_GUARD(value) \
+  THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value)
+# define THREAD_COPY_STACK_GUARD(descr) \
+  ((descr)->p_header.data.stack_guard \
+   = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard))
+
+/* Get/set the stack guard field in TCB head.  */
+#define THREAD_GET_POINTER_GUARD() \
+  THREAD_GETMEM (THREAD_SELF, p_header.data.pointer_guard)
+#define THREAD_SET_POINTER_GUARD(value) \
+  THREAD_SETMEM (THREAD_SELF, p_header.data.pointer_guard, value)
+# define THREAD_COPY_POINTER_GUARD(descr) \
+  ((descr)->p_header.data.pointer_guard = THREAD_GET_POINTER_GUARD ())
+
 # endif
 
 #else
Index: linuxthreads/sysdeps/x86_64/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/x86_64/tcb-offsets.sym,v
retrieving revision 1.1
diff -u -p -r1.1 tcb-offsets.sym
--- linuxthreads/sysdeps/x86_64/tcb-offsets.sym 17 Jun 2003 22:23:41 -0000 1.1
+++ linuxthreads/sysdeps/x86_64/tcb-offsets.sym 26 Apr 2006 14:58:01 -0000
@@ -2,3 +2,4 @@
 #include <tls.h>
 
 MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
+POINTER_GUARD offsetof (tcbhead_t, pointer_guard)
Index: linuxthreads/sysdeps/x86_64/tls.h
===================================================================
RCS file: /cvs/glibc/linuxthreads/linuxthreads/sysdeps/x86_64/tls.h,v
retrieving revision 1.7
diff -u -p -r1.7 tls.h
--- linuxthreads/sysdeps/x86_64/tls.h 9 Jan 2005 20:01:15 -0000 1.7
+++ linuxthreads/sysdeps/x86_64/tls.h 26 Apr 2006 14:58:01 -0000
@@ -25,6 +25,7 @@
 # include <pt-machine.h>
 # include <stdbool.h>
 # include <stddef.h>
+# include <stdint.h>
 
 /* Type for the dtv.  */
 typedef union dtv
@@ -45,6 +46,9 @@ typedef struct
   dtv_t *dtv;
   void *self; /* Pointer to the thread descriptor.  */
   int multiple_threads;
+  uintptr_t sysinfo;
+  uintptr_t stack_guard;
+  uintptr_t pointer_guard;
 } tcbhead_t;
 
 #else /* __ASSEMBLER__ */
@@ -128,6 +132,21 @@ typedef struct
   ({ struct _pthread_descr_struct *__descr;      \
      THREAD_GETMEM (__descr, p_header.data.dtvp); })
 
+/* Set the stack guard field in TCB head.  */
+# define THREAD_SET_STACK_GUARD(value) \
+    THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value)
+# define THREAD_COPY_STACK_GUARD(descr) \
+    ((descr)->p_header.data.stack_guard      \
+     = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard))
+
+
+/* Set the pointer guard field in the TCB head.  */
+#define THREAD_SET_POINTER_GUARD(value) \
+  THREAD_SETMEM (THREAD_SELF, p_header.data.pointer_guard, value)
+#define THREAD_COPY_POINTER_GUARD(descr) \
+  ((descr)->p_header.data.pointer_guard      \
+   = THREAD_GETMEM (THREAD_SELF, p_header.data.pointer_guard))
+
 # endif /* HAVE_TLS_SUPPORT */
 #endif /* __ASSEMBLER__ */