aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/powerpc/powerpc32
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2003-03-02 11:45:12 +0000
committerRoland McGrath <roland@gnu.org>2003-03-02 11:45:12 +0000
commitbb0ddc2f1eca652aa8af56825b2ba3182498cc5a (patch)
tree8b03305facff745ff0bd14c50e811dfd77cef343 /sysdeps/powerpc/powerpc32
parent3093b1c70cd227c3329d2bbb77cd59ce2cbdcbd4 (diff)
downloadglibc-bb0ddc2f1eca652aa8af56825b2ba3182498cc5a.tar
glibc-bb0ddc2f1eca652aa8af56825b2ba3182498cc5a.tar.gz
glibc-bb0ddc2f1eca652aa8af56825b2ba3182498cc5a.tar.bz2
glibc-bb0ddc2f1eca652aa8af56825b2ba3182498cc5a.zip
* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_fixup_plt):
Don't use weak_extern for dl_rtld_map. Instead check only if [SHARED]. (elf_machine_rela): Clean up. * sysdeps/powerpc/powerpc32/dl-machine.h (elf_machine_rela): Clean up. PowerPC TLS support contributed by Paul Mackerras <paulus@samba.org>. * sysdeps/powerpc/powerpc32/elf/configure.in: New file. * sysdeps/powerpc/powerpc32/elf/configure: New generated file. * elf/tls-macros.h [__powerpc__ && !__powerpc64__] (TLS_LE, TLS_IE, TLS_LD, TLS_GD): Define them. * sysdeps/powerpc/powerpc32/dl-machine.h (elf_machine_rela): Support new relocs for TLS. * sysdeps/powerpc/dl-tls.h (TLS_TP_OFFSET, TLS_DTV_OFFSET): Move these macros out of [SHARED]. (TLS_TPREL_VALUE, TLS_DTPREL_VALUE): New macros. * elf/elf.h: Define R_PPC_* relocs for TLS support. Clean up R_PPC64_* macro definition comments.
Diffstat (limited to 'sysdeps/powerpc/powerpc32')
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.h117
-rwxr-xr-xsysdeps/powerpc/powerpc32/elf/configure57
-rw-r--r--sysdeps/powerpc/powerpc32/elf/configure.in42
3 files changed, 176 insertions, 40 deletions
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index 88408a4287..39dbbb412c 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -23,6 +23,7 @@
#define ELF_MACHINE_NAME "powerpc"
#include <assert.h>
+#include <dl-tls.h>
/* Return nonzero iff ELF header is compatible with the running host. */
static inline int
@@ -275,11 +276,22 @@ __elf_preferred_address(struct link_map *loader, size_t maplength,
/* We never want to use a PLT entry as the destination of a
reloc, when what is being relocated is a branch. This is
partly for efficiency, but mostly so we avoid loops. */
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+#define elf_machine_type_class(type) \
+ ((((type) == R_PPC_JMP_SLOT \
+ || (type) == R_PPC_REL24 \
+ || (type) == R_PPC_DTPMOD32 \
+ || (type) == R_PPC_DTPREL32 \
+ || (type) == R_PPC_TPREL32 \
+ || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
#define elf_machine_type_class(type) \
((((type) == R_PPC_JMP_SLOT \
|| (type) == R_PPC_REL24 \
|| (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_PPC_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_PPC_JMP_SLOT
@@ -341,44 +353,29 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
Elf32_Addr *const reloc_addr)
{
const Elf32_Sym *const refsym = sym;
- Elf32_Word finaladdr;
- const int rinfo = ELF32_R_TYPE (reloc->r_info);
-
-#ifndef RESOLVE_CONFLICT_FIND_MAP
- if (__builtin_expect (rinfo == R_PPC_NONE, 0))
- return;
+ Elf32_Addr value;
+ const int r_type = ELF32_R_TYPE (reloc->r_info);
- /* The condition on the next two lines is a hack around a bug in Solaris
- tools on Sparc. It's not clear whether it should really be here at all,
- but if not the binutils need to be changed. */
- if (rinfo == R_PPC_RELATIVE
- || (sym->st_shndx != SHN_UNDEF
- && ELF32_ST_BIND (sym->st_info) == STB_LOCAL))
+ if (r_type == R_PPC_RELATIVE)
{
- /* Has already been relocated. */
- Elf32_Word loadbase = map->l_addr;
- finaladdr = loadbase + reloc->r_addend;
- }
- else
- {
- Elf32_Word loadbase
- = (Elf32_Word) (char *) (RESOLVE (&sym, version,
- ELF32_R_TYPE(reloc->r_info)));
- if (sym == NULL)
- {
- /* Weak symbol that wasn't actually defined anywhere. */
- assert (loadbase == 0);
- finaladdr = reloc->r_addend;
- }
- else
- finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value
- + reloc->r_addend);
+ *reloc_addr = map->l_addr + reloc->r_addend;
+ return;
}
+
+ if (__builtin_expect (r_type == R_PPC_NONE, 0))
+ return;
+
+#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+ value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
#else
- finaladdr = reloc->r_addend;
- if (rinfo == R_PPC_JMP_SLOT)
- RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
+ value = RESOLVE (&sym, version, r_type);
+# ifndef RTLD_BOOTSTRAP
+ if (sym != NULL)
+# endif
+ value += sym->st_value;
#endif
+ value += reloc->r_addend;
/* A small amount of code is duplicated here for speed. In libc,
more than 90% of the relocs are R_PPC_RELATIVE; in the X11 shared
@@ -386,15 +383,55 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
R_PPC_ADDR32, and 16% are R_PPC_JMP_SLOT (which this routine
wouldn't usually handle). As an bonus, doing this here allows
the switch statement in __process_machine_rela to work. */
- if (rinfo == R_PPC_RELATIVE
- || rinfo == R_PPC_GLOB_DAT
- || rinfo == R_PPC_ADDR32)
+ switch (r_type)
{
- *reloc_addr = finaladdr;
+ case R_PPC_GLOB_DAT:
+ case R_PPC_ADDR32:
+ *reloc_addr = value;
+ break;
+
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+ case R_PPC_DTPMOD32:
+# 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
+ RESOLVE_MAP function. */
+ if (sym_map != NULL)
+ *reloc_addr = sym_map->l_tls_modid;
+# endif
+ break;
+ case R_PPC_DTPREL32:
+ /* During relocation all TLS symbols are defined and used.
+ Therefore the offset is already correct. */
+# ifndef RTLD_BOOTSTRAP
+ *reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
+# endif
+ break;
+ case R_PPC_TPREL32:
+# ifndef RTLD_BOOTSTRAP
+ if (sym_map)
+ {
+ CHECK_STATIC_TLS (map, sym_map);
+# endif
+ *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
+# ifndef RTLD_BOOTSTRAP
+ }
+# endif
+ break;
+#endif /* USE_TLS etc. */
+
+#ifdef RESOLVE_CONFLICT_FIND_MAP
+ case R_PPC_JMP_SLOT:
+ RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
+ /* FALLTHROUGH */
+#endif
+
+ default:
+ __process_machine_rela (map, reloc, sym, refsym,
+ reloc_addr, value, r_type);
}
- else
- __process_machine_rela (map, reloc, sym, refsym,
- reloc_addr, finaladdr, rinfo);
}
static inline void
diff --git a/sysdeps/powerpc/powerpc32/elf/configure b/sysdeps/powerpc/powerpc32/elf/configure
new file mode 100755
index 0000000000..c4bed2b8d5
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/elf/configure
@@ -0,0 +1,57 @@
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/powerpc32/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+echo "$as_me:$LINENO: checking for powerpc32 TLS support" >&5
+echo $ECHO_N "checking for powerpc32 TLS support... $ECHO_C" >&6
+if test "${libc_cv_powerpc32_tls+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat > conftest.s <<\EOF
+ .section ".tdata","awT",@progbits
+x: .long 1
+x1: .long 1
+x2: .long 1
+ .text
+ addi 3,31,x@got@tlsgd
+ addi 3,31,x1@got@tlsld
+ addi 9,3,x1@dtprel
+ addis 9,3,x2@dtprel@ha
+ addi 9,9,x2@dtprel@l
+ lwz 0,x1@dtprel(3)
+ addis 9,3,x2@dtprel@ha
+ lwz 0,x2@dtprel@l(9)
+ lwz 9,x3@got@tprel(31)
+ add 9,9,x@tls
+ addi 9,2,x1@tprel
+ addis 9,2,x2@tprel@ha
+ addi 9,9,x2@tprel@l
+EOF
+if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ libc_cv_powerpc32_tls=yes
+else
+ libc_cv_powerpc32_tls=no
+fi
+rm -f conftest*
+fi
+echo "$as_me:$LINENO: result: $libc_cv_powerpc32_tls" >&5
+echo "${ECHO_T}$libc_cv_powerpc32_tls" >&6
+if test $libc_cv_powerpc32_tls = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_TLS_SUPPORT 1
+_ACEOF
+
+fi
+fi
+
+cat >>confdefs.h <<\_ACEOF
+#define PI_STATIC_AND_HIDDEN 1
+_ACEOF
+
diff --git a/sysdeps/powerpc/powerpc32/elf/configure.in b/sysdeps/powerpc/powerpc32/elf/configure.in
new file mode 100644
index 0000000000..97c300c20b
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/elf/configure.in
@@ -0,0 +1,42 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/powerpc32/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+AC_CACHE_CHECK(for powerpc32 TLS support, libc_cv_powerpc32_tls, [dnl
+cat > conftest.s <<\EOF
+ .section ".tdata","awT",@progbits
+x: .long 1
+x1: .long 1
+x2: .long 1
+ .text
+ addi 3,31,x@got@tlsgd
+ addi 3,31,x1@got@tlsld
+ addi 9,3,x1@dtprel
+ addis 9,3,x2@dtprel@ha
+ addi 9,9,x2@dtprel@l
+ lwz 0,x1@dtprel(3)
+ addis 9,3,x2@dtprel@ha
+ lwz 0,x2@dtprel@l(9)
+ lwz 9,x3@got@tprel(31)
+ add 9,9,x@tls
+ addi 9,2,x1@tprel
+ addis 9,2,x2@tprel@ha
+ addi 9,9,x2@tprel@l
+EOF
+dnl
+if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD); then
+ libc_cv_powerpc32_tls=yes
+else
+ libc_cv_powerpc32_tls=no
+fi
+rm -f conftest*])
+if test $libc_cv_powerpc32_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)