This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PPC64 enable with-tls


This patch enables --with-tls for powerpc64. It requires the binutils
form cvs head as of 2003/02/14 to compile and link correctly. 

The only thing that might be controversial is the change to
sysdeps/generic/dl-tls.c. The TLS Access ABI for powerpc64 states:

"Dynamic thread vector pointers point 0x8000 past the start of each TLS
block.  This allows the first 64K of each block to be addressed from a
dtv
pointer using fewer machine instructions. "

This also applies to powerpc32.

This would complicate the generic tls code substantially except it turns
out that compiler/linker generated code never reference the DTV directly
(they either call __tls_get_addr, or use TP relative addressing). So it
is not strictly necessary to bias each dtv .pointer entry. However the
generated code does expect the __tls_get_addr returns addresses of TLS
block+0x8000. It is sufficient to simply add +0x8000 to the
__tls_get_addr return value. 

This also impacts internal function (like _dl_tls_symaddr) that use
__tls_get_addr. In this case the 0x8000 must be subtracted from the
value returned by __tls_get_addr to get the correct address. 

Fortunately this is currently all contained in sysdeps/generic/dl-tls.c
and tls.h. In tls.h for powerpc64 I #define TLS_DTV_OFFSET 0x8000. Then
at the top of sysdeps/generic/dl-tls.c I make sure that TLS_DTV_OFFSET
is defined as "0" if it is not already defined. 

+#  ifndef TLS_DTV_OFFSET
+#   define TLS_DTV_OFFSET 0
+#  endif

Then I can safely add TLS_DTV_OFFSET to the __tls_get_addr return
statement.

-  return (char *) p + GET_ADDR_OFFSET;
+  return (char *) p + GET_ADDR_OFFSET + TLS_DTV_OFFSET; 

I also have to fix up the address for _dl_tls_symaddr:

-  return __TLS_GET_ADDR (&tmp);
+  return __TLS_GET_ADDR (&tmp) - TLS_DTV_OFFSET;
 #  else
-  return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value);
+  return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value) 
+                      - TLS_DTV_OFFSET;

2003-01-31  Steven Munroe  <sjmunroe at us dot ibm dot com>

	* elf/elf.h: Add new powerpc64 relocs.
	* elf/tls-macros.h [__powerpc64__] (TLS_LE, TLS_IE, TLS_LD, TLS_GD):
	Define.
	* linuxthreads/sysdeps/powerpc/powerpc64/tls.h: New file.
	* sysdeps/generic/dl-tls.c [!TLS_DVT_OFFSET]: Define as 0.
	(_dl_tls_symaddr): Subtract TLS_DVT_OFFSET from return value.
	(__tls_get_addr): Add TLS_DVT_OFFSET to return value.
	* sysdeps/powerpc/elf/libc-start.c(__libc_start_main) Do
	DL_SYSDEP_OSCHECK here.
	* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela) Add TLS
	specific relocations.
	* sysdeps/powerpc/powerpc64/dl-tls.h: New file.
	* sysdeps/powerpc/powerpc64/elf/configure.in: New file.

-- 
Steven Munroe
sjmunroe at us dot ibm dot com
Linux on PowerPC-64 Development
GLIBC for PowerPC-64 Development
diff -rupP  libc23-cvstip-20030221/elf/elf.h libc23/elf/elf.h
--- libc23-cvstip-20030221/elf/elf.h	Tue Jan 28 04:31:53 2003
+++ libc23/elf/elf.h	Fri Feb 21 14:21:24 2003
@@ -1953,8 +1953,50 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_PPC64_TOC16_LO_DS    64 /* half16ds  #lo(S + A - .TOC.) >> 2.  */
 #define R_PPC64_PLTGOT16_DS    65 /* half16ds* (M + A) >> 2.  */
 #define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds  #lo(M + A) >> 2.  */
+
+/* PowerPC64 relocations defined for the TLS access ABI.  */
+#define R_PPC64_TLS             67 /* none         (sym+add)@tls.  */
+#define R_PPC64_DTPMOD64        68 /* doubleword64 (sym+add)@dtpmod.  */
+#define R_PPC64_TPREL16         69 /* half16*      (sym+add)@tprel.  */
+#define R_PPC64_TPREL16_LO      60 /* half16       (sym+add)@tprel at l dot  */
+#define R_PPC64_TPREL16_HI      71 /* half16       (sym+add)@tprel at h dot   */
+#define R_PPC64_TPREL16_HA      72 /* half16       (sym+add)@tprel at ha dot   */
+#define R_PPC64_TPREL64         73 /* doubleword64 (sym+add)@tprel.  */
+#define R_PPC64_DTPREL16        74 /* half16*      (sym+add)@dtprel.  */
+#define R_PPC64_DTPREL16_LO     75 /* half16       (sym+add)@dtprel at l dot   */
+#define R_PPC64_DTPREL16_HI     76 /* half16       (sym+add)@dtprel at h dot   */
+#define R_PPC64_DTPREL16_HA     77 /* half16       (sym+add)@dtprel at ha dot   */
+#define R_PPC64_DTPREL64        78 /* doubleword64 (sym+add)@dtprel.  */
+#define R_PPC64_GOT_TLSGD16     79 /* half16*      (sym+add)@got at tlsgd dot   */
+#define R_PPC64_GOT_TLSGD16_LO  80 /* half16       (sym+add)@got at tlsgd@l.  */
+#define R_PPC64_GOT_TLSGD16_HI  81 /* half16       (sym+add)@got at tlsgd@h.  */
+#define R_PPC64_GOT_TLSGD16_HA  82 /* half16       (sym+add)@got at tlsgd@ha.  */
+#define R_PPC64_GOT_TLSLD16     83 /* half16*      (sym+add)@got at tlsld dot   */
+#define R_PPC64_GOT_TLSLD16_LO  84 /* half16       (sym+add)@got at tlsld@l.  */
+#define R_PPC64_GOT_TLSLD16_HI  85 /* half16       (sym+add)@got at tlsld@h.  */
+#define R_PPC64_GOT_TLSLD16_HA  86 /* half16       (sym+add)@got at tlsld@ha.  */
+#define R_PPC64_GOT_TPREL16_DS  87 /* half16ds*    (sym+add)@got at tprel dot   */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds   (sym+add)@got at tprel@l.  */
+#define R_PPC64_GOT_TPREL16_HI  89 /* half16       (sym+add)@got at tprel@h.  */
+#define R_PPC64_GOT_TPREL16_HA  90 /* half16       (sym+add)@got at tprel@ha.  */
+#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds*    (sym+add)@got at dtprel dot   */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds  (sym+add)@got at dtprel@l.  */
+#define R_PPC64_GOT_DTPREL16_HI 93 /* half16       (sym+add)@got at dtprel@h.  */
+#define R_PPC64_GOT_DTPREL16_HA 94 /* half16       (sym+add)@got at dtprel@ha.  */
+#define R_PPC64_TPREL16_DS      95 /* half16ds*    (sym+add)@tprel.  */
+#define R_PPC64_TPREL16_LO_DS   96 /* half16ds     (sym+add)@tprel at l dot   */
+#define R_PPC64_TPREL16_HIGHER  97 /* half16       (sym+add)@tprel at higher dot   */
+#define R_PPC64_TPREL16_HIGHERA 98 /* half16       (sym+add)@tprel at highera dot   */
+#define R_PPC64_TPREL16_HIGHEST 99 /* half16       (sym+add)@tprel at highest dot   */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16    (sym+add)@tprel at highesta dot   */
+#define R_PPC64_DTPREL16_DS    101 /* half16ds*    (sym+add)@dtprel.  */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds     (sym+add)@dtprel at l dot   */
+#define R_PPC64_DTPREL16_HIGHER 103 /* half16      (sym+add)@dtprel at higher dot   */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16    (sym+add)@dtprel at highera dot   */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16    (sym+add)@dtprel at highest dot   */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16  (sym+add)@dtprel at highesta dot   */
 /* Keep this the last entry.  */
-#define R_PPC64_NUM		67
+#define R_PPC64_NUM		107
 
 /* The remaining relocs are from the Embedded ELF ABI, and are not
    in the SVR4 ELF ABI.  */
diff -rupP  libc23-cvstip-20030221/elf/tls-macros.h libc23/elf/tls-macros.h
--- libc23-cvstip-20030221/elf/tls-macros.h	Fri Feb  7 20:30:16 2003
+++ libc23/elf/tls-macros.h	Fri Feb 21 14:21:24 2003
@@ -623,6 +623,58 @@ register void *__gp __asm__("$29");
      (int *) (__builtin_thread_pointer() + __offset); })
 # endif
 
+#elif defined __powerpc__ && defined __powerpc64__
+
+/* PowerPC64 Local Exec TLS access.  */
+# define TLS_LE(x) \
+  ({  int * __result;  \
+      asm ( \
+        "  addis %0,13," #x "@tprel at ha\n"  \
+        "  addi  %0,%0," #x "@tprel at l\n"   \
+        : "=b" (__result) );  \
+      __result;  \
+  })
+/* PowerPC64 Initial Exec TLS access.  */
+#  define TLS_IE(x) \
+  ({  int * __result;  \
+      asm (  \
+        "  ld  %0," #x "@got at tprel(2)\n"  \
+        "  add %0,%0," #x "@tls\n"   \
+        : "=b" (__result) );  \
+      __result;  \
+  })
+/* PowerPC64 Local Dynamic TLS access.  */
+#  define TLS_LD(x) \
+  ({  int * __result;  \
+      asm (  \
+        "  addi  3,2," #x "@got at tlsld\n"  \
+	      "  bl    .__tls_get_addr\n"  \
+	      "  nop   \n"  \
+        "  addis %0,3," #x "@dtprel at ha\n"  \
+        "  addi  %0,%0," #x "@dtprel at l\n"  \
+        : "=b" (__result) :  \
+	      : "0", "3", "4", "5", "6", "7",    \
+	        "8", "9", "10", "11", "12",      \
+		      "lr", "ctr",  \
+		      "cr0", "cr1", "cr5", "cr6", "cr7");  \
+      __result;  \
+  })
+/* PowerPC64 General Dynamic TLS access.  */
+#  define TLS_GD(x) \
+  ({  int * __result;  \
+      asm (  \
+        "  addi  3,2," #x "@got at tlsgd\n"  \
+	      "  bl    .__tls_get_addr\n"  \
+	      "  nop   \n"  \
+	      "  mr    %0,3\n"  \
+        : "=b" (__result) :  \
+	      : "0", "3", "4", "5", "6", "7",    \
+	        "8", "9", "10", "11", "12",      \
+		      "lr", "ctr",  \
+		      "cr0", "cr1", "cr5", "cr6", "cr7");  \
+      __result;  \
+  })
+
 #else
 # error "No support for this architecture so far."
 #endif
diff -rupP  libc23-cvstip-20030221/linuxthreads/sysdeps/powerpc/powerpc64/tls.h libc23/linuxthreads/sysdeps/powerpc/powerpc64/tls.h
--- libc23-cvstip-20030221/linuxthreads/sysdeps/powerpc/powerpc64/tls.h	Wed Dec 31 18:00:00 1969
+++ libc23/linuxthreads/sysdeps/powerpc/powerpc64/tls.h	Fri Feb 21 14:21:24 2003
@@ -0,0 +1,169 @@
+/* Definitions for thread-local data handling.  linuxthreads/Alpha version.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+
+typedef struct
+{
+  dtv_t *dtv;
+
+  /* Reserved for the thread implementation.  Unused in LinuxThreads.  */
+  void *private;
+} tcbhead_t;
+#endif
+
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+/* Get system call information.  */
+#  include <sysdep.h>
+
+/* This is the size of the initial TCB.  */
+#  define TLS_INIT_TCB_SIZE	sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+#  define TLS_INIT_TCB_ALIGN	__alignof__ (tcbhead_t)
+
+/* This is the size of the TCB.  */
+#  define TLS_TCB_SIZE		sizeof (tcbhead_t)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN		__alignof__ (tcbhead_t)
+
+/* This is the size we need before TCB.  */
+#  define TLS_PRE_TCB_SIZE	sizeof (struct _pthread_descr_struct)
+
+/* the following assumes that TP (R13) is points to the end of the tcb
+   + 0x7000 (per the ABI).  This implies that tcb address is 
+   R13-(TLS_TCB_SIZE + 0x7000).  As we define TLS_DTV_AT_TP we can 
+   assume that the pthread_descr is allocate immediately ahead of the 
+   tcb.  This implies that the pthread_descr address is 
+   R13-(TLS_PRE_TCB_SIZE + TLS_TCB_SIZE + 0x7000).  */
+
+/* The DTV is allocated at the TP; the TCB is placed elsewhere.  */
+/* This is not really true for powerpc64.  We are following alpha.  */
+#  define TLS_DTV_AT_TP 1 
+
+/* Dynamic thread vector pointers point 0x8000 past the start of each 
+   TLS block.  */
+#  define TLS_DTV_OFFSET 0x8000
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(TCBP, DTVP) \
+  (((tcbhead_t *) (TCBP))->dtv = (DTVP) + 1)
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(DTV) \
+  ({  \
+      asm ( \
+        "  std %0,-(0x7000+%1)(13)\n"  \
+        :  \
+	      :  "b" (DTV), "I" (TLS_TCB_SIZE) \
+	      :  "memory" );  \
+  })
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(TCBP) \
+  (((tcbhead_t *) (TCBP))->dtv)
+
+/* Code to initially initialize the thread pointer.  This might need
+   special attention since 'errno' is not yet available and if the
+   operation can cause a failure 'errno' must not be touched.  */
+# define TLS_INIT_TP(TCBP, SECONDCALL) \
+  ({  \
+      asm ( \
+        "  addi 13,%0,(0x7000+%1)\n"  \
+        : : "b" (TCBP), "I" (TLS_TCB_SIZE) );  \
+	    NULL;  \
+  })
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  ({  dtv_t * __dvtp;  \
+      asm ( \
+        "  ld  %0,-(0x7000+%1)(13)\n"  \
+        :  "=b" (__dvtp)  \
+	      :  "I" (TLS_TCB_SIZE) );  \
+      (__dvtp); \
+  })
+
+/* Return the thread descriptor for the current thread.  */
+#  undef THREAD_SELF
+#  define THREAD_SELF \
+  ({  pthread_descr __result;  \
+      asm ( \
+        "  addi %0,13,-(0x7000+%1+%2)\n"  \
+        : "=b" (__result)  \
+	      :  "I" (TLS_TCB_SIZE), "I" (TLS_PRE_TCB_SIZE) );  \
+      __result; \
+  })
+
+#  undef INIT_THREAD_SELF
+#  define INIT_THREAD_SELF(DESCR, NR) \
+  ({  \
+      asm ( \
+        "  addi 13,%0,(0x7000+%1+%2)\n"  \
+        :  \
+	      :  "b" (DESCR), "I" (TLS_TCB_SIZE), "I" (TLS_PRE_TCB_SIZE) ); \
+  })
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+/* ??? Generic bits of LinuxThreads may call these macros with
+   DESCR set to NULL.  We are expected to be able to reference
+   the "current" value.
+
+   In our case, we'd really prefer to use DESCR, since lots of
+   PAL_code calls would be expensive.  We can only trust that
+   the compiler does its job and unifies the multiple
+   __builtin_thread_pointer instances.  */
+
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+# endif	/* HAVE_TLS_SUPPORT */
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */
diff -rupP  libc23-cvstip-20030221/sysdeps/generic/dl-tls.c libc23/sysdeps/generic/dl-tls.c
--- libc23-cvstip-20030221/sysdeps/generic/dl-tls.c	Thu Jan 30 14:46:44 2003
+++ libc23/sysdeps/generic/dl-tls.c	Fri Feb 21 14:21:24 2003
@@ -458,6 +458,10 @@ rtld_hidden_def (_dl_deallocate_tls)
 #  endif
 
 
+#  ifndef TLS_DTV_OFFSET
+#   define TLS_DTV_OFFSET 0
+#  endif
+
 /* Return the symbol address given the map of the module it is in and
    the symbol record.  This is used in dl-sym.c.  */
 void *
@@ -471,9 +475,10 @@ _dl_tls_symaddr (struct link_map *map, c
       .ti_offset = ref->st_value
     };
 
-  return __TLS_GET_ADDR (&tmp);
+  return __TLS_GET_ADDR (&tmp) - TLS_DTV_OFFSET;
 #  else
-  return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value);
+  return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value) 
+                      - TLS_DTV_OFFSET;
 #  endif
 }
 
@@ -676,8 +681,7 @@ __tls_get_addr (GET_ADDR_ARGS)
 
       p = dtv[GET_ADDR_MODULE].pointer = allocate_and_init (the_map);
     }
-
-  return (char *) p + GET_ADDR_OFFSET;
+  return (char *) p + GET_ADDR_OFFSET + TLS_DTV_OFFSET;  
 }
 # endif
 
diff -rupP  libc23-cvstip-20030221/sysdeps/powerpc/elf/libc-start.c libc23/sysdeps/powerpc/elf/libc-start.c
--- libc23-cvstip-20030221/sysdeps/powerpc/elf/libc-start.c	Mon Feb 17 14:45:16 2003
+++ libc23/sysdeps/powerpc/elf/libc-start.c	Fri Feb 21 14:25:18 2003
@@ -129,6 +129,14 @@ BP_SYM (__libc_start_main) (int argc, ch
   __libc_stack_end = stack_on_entry + 8;
 
 #ifndef SHARED
+# ifdef DL_SYSDEP_OSCHECK
+  if (!__libc_multiple_libcs)
+    {
+      /* This needs to run to initiliaze _dl_osversion before TLS
+	 setup might check it.  */
+      DL_SYSDEP_OSCHECK (__libc_fatal);
+    }
+# endif
   /* Initialize the thread library at least a bit since the libgcc
      functions are using thread functions if these are available and
      we need to setup errno.  If there is no thread library and we
diff -rupP  libc23-cvstip-20030221/sysdeps/powerpc/powerpc64/dl-machine.h libc23/sysdeps/powerpc/powerpc64/dl-machine.h
--- libc23-cvstip-20030221/sysdeps/powerpc/powerpc64/dl-machine.h	Thu Jan 30 14:25:44 2003
+++ libc23/sysdeps/powerpc/powerpc64/dl-machine.h	Fri Feb 21 14:21:24 2003
@@ -328,9 +328,19 @@ elf_machine_dynamic (void)
    PLT entries should not be allowed to define the value.
    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
    of the main executable's symbols, as for a COPY reloc.  */
+
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+#define elf_machine_type_class(type) \
+  (   (((type) == R_PPC64_DTPMOD64	\
+    ||  (type) == R_PPC64_DTPREL64	\
+    ||  (type) == R_PPC64_TPREL64 \
+    ||  (type) == R_PPC64_ADDR24) * ELF_RTYPE_CLASS_PLT)	\
+    | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
 #define elf_machine_type_class(type) \
   ((((type) == R_PPC64_ADDR24) * ELF_RTYPE_CLASS_PLT)	\
    | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT	R_PPC64_JMP_SLOT
@@ -534,7 +544,7 @@ elf_machine_rela_relative (Elf64_Addr l_
 			   Elf64_Addr *const reloc_addr)
 {
   *reloc_addr = l_addr + reloc->r_addend;
-}			       
+}
 
 /* Perform the relocation specified by RELOC and SYM (which is fully
    resolved).  MAP is the object containing the reloc.  */
@@ -547,7 +557,7 @@ elf_machine_rela (struct link_map *map,
 {
   int r_type = ELF64_R_TYPE (reloc->r_info);
   struct link_map *sym_map;
-  Elf64_Addr value;
+  Elf64_Addr value, raw_value;
 #ifndef RTLD_BOOTSTRAP
   const Elf64_Sym *const refsym = sym;
   /* This is defined in rtld.c, but nowhere in the static libc.a; make the
@@ -564,28 +574,80 @@ elf_machine_rela (struct link_map *map,
       /* Already done in dynamic linker.  */
       if (map != &GL(dl_rtld_map))
 #endif
-	*reloc_addr = map->l_addr + reloc->r_addend;
+      *reloc_addr = map->l_addr + reloc->r_addend;
       return;
     }
 
   if (r_type == R_PPC64_NONE)
     return;
 
-  sym_map = RESOLVE_MAP (&sym, version, r_type);
   value = 0;
+  raw_value = 0;
+
+#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+  sym_map = RESOLVE_MAP (&sym, version, r_type);
+  raw_value = value = reloc->r_addend;
   if (sym_map)
-    {
-      if (sym)
-	value = sym_map->l_addr + sym->st_value;
-      value += reloc->r_addend;
-    }
+    if (sym)
+	  {
+	    raw_value += sym->st_value;
+	    value = raw_value + sym_map->l_addr;
+	  }
+#else
+  sym_map = RESOLVE_MAP (&sym, version, r_type);
+  if (sym_map)
+  {
+    if (sym)
+	  {
+	    raw_value = sym->st_value + sym_map->l_addr;
+	  }
+	  value = raw_value + reloc->r_addend;
+	}
+#endif
 
   switch (r_type)
     {
     case R_PPC64_ADDR64:
     case R_PPC64_GLOB_DAT:
-      *reloc_addr = value;
+      *reloc_addr = value;      
       return;
+      
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+
+    case R_PPC64_DTPMOD64:
+#ifdef RTLD_BOOTSTRAP
+	  /* During startup the dynamic linker is always index 1.  */
+      *reloc_addr = 1;
+#else
+	  /* Get the information from the link map returned by the
+	     resolv function.  */
+      if (sym_map != NULL)
+        {
+          *reloc_addr = sym_map->l_tls_modid;
+	      }
+#endif
+      return;
+      
+    case R_PPC64_TPREL64:
+#ifdef RTLD_BOOTSTRAP
+      *reloc_addr = raw_value + map->l_tls_offset - 0x7010;
+#else
+      if (sym_map)
+      {
+        CHECK_STATIC_TLS (map, sym_map);
+        *reloc_addr = raw_value + sym_map->l_tls_offset - 0x7010;
+      }
+#endif
+      return;
+      
+    case R_PPC64_DTPREL64:
+#ifndef RTLD_BOOTSTRAP
+      /* During relocation all TLS symbols are defined and used.
+       Therefore the offset is already correct.  */
+      *reloc_addr = raw_value - 0x8000;
+#endif
+      return;
+#endif      
 
     case R_PPC64_JMP_SLOT:
 
@@ -601,15 +663,61 @@ elf_machine_rela (struct link_map *map,
 					       value, 0xfffc);
       break;
 
+    case R_PPC64_TPREL16_LO_DS:
+      if (dont_expect ((value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_TPREL16_LO_DS", 
+                            reloc_addr, sym, refsym);
+      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
+					       value, 0xfffc);
+      break;
+
+    case R_PPC64_DTPREL16_LO_DS:
+      if (dont_expect ((value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_DTPREL16_LO_DS", 
+                            reloc_addr, sym, refsym);
+      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
+					       value, 0xfffc);
+      break;
+
+    case R_PPC64_GOT_TPREL16_LO_DS:
+      if (dont_expect ((value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_GOT_TPREL16_LO_DS", 
+                            reloc_addr, sym, refsym);
+      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
+					       value, 0xfffc);
+      break;
+
+    case R_PPC64_GOT_DTPREL16_LO_DS:
+      if (dont_expect ((value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_GOT_DTPREL16_LO_DS", 
+                            reloc_addr, sym, refsym);
+      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
+					       value, 0xfffc);
+      break;
+
     case R_PPC64_ADDR16_LO:
+    case R_PPC64_TPREL16_LO:
+    case R_PPC64_DTPREL16_LO:
+    case R_PPC64_GOT_TLSGD16_LO:
+    case R_PPC64_GOT_TLSLD16_LO:
       *(Elf64_Half *) reloc_addr = PPC_LO (value);
       break;
 
     case R_PPC64_ADDR16_HI:
+    case R_PPC64_TPREL16_HI:
+    case R_PPC64_DTPREL16_HI:
+    case R_PPC64_GOT_TPREL16_HI:
+    case R_PPC64_GOT_DTPREL16_HI:
+    case R_PPC64_GOT_TLSGD16_HI:
+    case R_PPC64_GOT_TLSLD16_HI:
       *(Elf64_Half *) reloc_addr = PPC_HI (value);
       break;
 
     case R_PPC64_ADDR16_HA:
+    case R_PPC64_TPREL16_HA:
+    case R_PPC64_DTPREL16_HA:
+    case R_PPC64_GOT_TLSGD16_HA:
+    case R_PPC64_GOT_TLSLD16_HA:
       *(Elf64_Half *) reloc_addr = PPC_HA (value);
       break;
 
@@ -690,19 +798,59 @@ elf_machine_rela (struct link_map *map,
 					       value, 0xfffc);
       break;
 
+    case R_PPC64_TPREL16_DS:
+      if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_TPREL16_DS", reloc_addr, 
+	                          sym, refsym);
+      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
+					       value, 0xfffc);
+      break;
+
+    case R_PPC64_DTPREL16_DS:
+      if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_DTPREL16_DS", reloc_addr, 
+	                          sym, refsym);
+      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
+					       value, 0xfffc);
+      break;
+
+    case R_PPC64_GOT_TPREL16_DS:
+      if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_GOT_TPREL16_DS", reloc_addr, 
+	                          sym, refsym);
+      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
+					       value, 0xfffc);
+      break;
+
+    case R_PPC64_GOT_DTPREL16_DS:
+      if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_GOT_DTPREL16_DS", 
+	                          reloc_addr, sym, refsym);
+      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
+					       value, 0xfffc);
+      break;
+
     case R_PPC64_ADDR16_HIGHER:
+    case R_PPC64_TPREL16_HIGHER:
+    case R_PPC64_DTPREL16_HIGHER:
       *(Elf64_Half *) reloc_addr = PPC_HIGHER (value);
       break;
 
     case R_PPC64_ADDR16_HIGHEST:
+    case R_PPC64_TPREL16_HIGHEST:
+    case R_PPC64_DTPREL16_HIGHEST:
       *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value);
       break;
 
     case R_PPC64_ADDR16_HIGHERA:
+    case R_PPC64_TPREL16_HIGHERA:
+    case R_PPC64_DTPREL16_HIGHERA:
       *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);
       break;
 
     case R_PPC64_ADDR16_HIGHESTA:
+    case R_PPC64_TPREL16_HIGHESTA:
+    case R_PPC64_DTPREL16_HIGHESTA:
       *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value);
       break;
 
diff -rupP  libc23-cvstip-20030221/sysdeps/powerpc/powerpc64/dl-tls.h libc23/sysdeps/powerpc/powerpc64/dl-tls.h
--- libc23-cvstip-20030221/sysdeps/powerpc/powerpc64/dl-tls.h	Wed Dec 31 18:00:00 1969
+++ libc23/sysdeps/powerpc/powerpc64/dl-tls.h	Fri Feb 21 14:21:24 2003
@@ -0,0 +1,29 @@
+/* Thread-local storage handling in the ELF dynamic linker.  Alpha version.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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.  */
+
+
+/* Type used for the representation of TLS information in the GOT.  */
+typedef struct
+{
+  unsigned long int ti_module;
+  unsigned long int ti_offset;
+} tls_index;
+
+
+extern void *__tls_get_addr (tls_index *ti);
diff -rupP  libc23-cvstip-20030221/sysdeps/powerpc/powerpc64/elf/configure.in libc23/sysdeps/powerpc/powerpc64/elf/configure.in
--- libc23-cvstip-20030221/sysdeps/powerpc/powerpc64/elf/configure.in	Wed Dec 31 18:00:00 1969
+++ libc23/sysdeps/powerpc/powerpc64/elf/configure.in	Fri Feb 21 14:21:24 2003
@@ -0,0 +1,61 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/powerpc64/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+AC_CACHE_CHECK(for powerpc64 TLS support, libc_cv_powerpc64_tls, [dnl
+cat > conftest.s <<\EOF
+        .section ".tdata","awT",@progbits
+x:      .quad   1
+x1:     .quad   1
+x2:     .quad   1
+x3:     .quad   1
+x4:     .long   1
+        .section ".toc","aw"
+.LC0:
+        .quad	x at dtpmod
+        .quad	x at dtprel
+.LC1:
+        .quad	x1 at dtpmod
+        .quad	0
+.LC2:
+	.quad	x at tprel
+        .text
+        addi    3,2,x at got@tlsgd
+        addi    3,2, dot LC0 at toc
+        addi    3,2,x1 at got@tlsld
+        addi    9,3,x1 at dtprel
+        addis   9,3,x2 at dtprel@ha
+        addi    9,9,x2 at dtprel@l
+        ld      9,x3 at got@dtprel(2)
+        addi    3,2, dot LC0 at toc
+        lwz     0,x1 at dtprel(3)
+        ld      0,x1 at dtprel(3)
+        addis   9,3,x2 at dtprel@ha
+        lwz     0,x2 at dtprel@l(9)
+        ld      0,x2 at dtprel@l(9)
+        ld      9,x3 at got@dtprel(2)
+        ld      9,x at got@tprel(2)
+        add     9,9,x at tls
+        ld      9, dot LC2 at toc(2)
+        add     9,9, dot LC2 at tls
+        addi    9,13,x1 at tprel
+        addis   9,13,x2 at tprel@ha
+        addi    9,9,x2 at tprel@l
+EOF
+dnl
+if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD); then
+  libc_cv_powerpc64_tls=yes
+else
+  libc_cv_powerpc64_tls=no
+fi
+rm -f conftest*])
+if test $libc_cv_powerpc64_tls = yes; then
+  AC_DEFINE(HAVE_TLS_SUPPORT)
+fi
+fi
+
+dnl It is always possible to access static and hidden symbols in an
+dnl position independent way.
+AC_DEFINE(PI_STATIC_AND_HIDDEN)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]