aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-01-28 10:42:28 +0000
committerUlrich Drepper <drepper@redhat.com>2003-01-28 10:42:28 +0000
commite6ebd2e4db59da6c1726ecfa3516f1f1b3048442 (patch)
treedfa3797737a8e4dc76ed38e52cf7baa27e936003 /sysdeps
parent772e3426a7b6f5200cb1029d41308b8b666cdbab (diff)
downloadglibc-e6ebd2e4db59da6c1726ecfa3516f1f1b3048442.tar
glibc-e6ebd2e4db59da6c1726ecfa3516f1f1b3048442.tar.gz
glibc-e6ebd2e4db59da6c1726ecfa3516f1f1b3048442.tar.bz2
glibc-e6ebd2e4db59da6c1726ecfa3516f1f1b3048442.zip
Update.
2003-01-27 Martin Schwidefsky <schwidefsky@de.ibm.com> * elf/elf.h: Add new s390 relocs. * elf/tls-macros.h: Add s390 versions. * sysdeps/s390/Versions [GLIBC_2.3] (ld): Export __tls_get_offset. * sysdeps/s390/dl-tls.h: New file. * sysdeps/s390/libc-tls.c: New file. * sysdeps/s390/s390-32/dl-machine.h (elf_machine_type_class): Add TLS relocs for class PLT. (elf_machine_rela): Handle TLS relocs. * sysdeps/s390/s390-64/dl-machine.h: Likewise. * sysdeps/s390/s390-32/elf/configure.in: Add TLS check. * sysdeps/s390/s390-64/elf/configure.in: Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/clone.S: Add support for CLONE_CHILD_*TID flags. * sysdeps/unix/sysv/linux/s390/s390-64/clone.S: Likewise. * sysdeps/unix/sysv/linux/s390/s390-64/mmap.S: Use branch with 32 bit offset. * sysdeps/unix/sysv/linux/s390/s390-64/socket.S: Likewise. * sysdeps/unix/sysv/linux/s390/s390-64/syscall.S: Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S (__syscall_error): Support USE___THREAD. Define RTLD_PRIVATE_ERRNO variant. * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S (__syscall_error): Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h: (SYSCALL_ERROR_LABEL): Move define next to SYSCALL_ERROR_HANDLER. (SYSCALL_ERROR_HANDLER): Add USE___THREAD and RTLD_PRIVATE_ERRNO variants. * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h: (SYSCALL_ERROR_LABEL): Move define next to SYSCALL_ERROR_HANDLER. Use direct branch to syscall_error for !PIC and PIC && !_LIBC_REENTRANT. (SYSCALL_ERROR_HANDLER): Add USE___THREAD and RTLD_PRIVATE_ERRNO variants.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/s390/Versions6
-rw-r--r--sysdeps/s390/dl-tls.h73
-rw-r--r--sysdeps/s390/libc-tls.c37
-rw-r--r--sysdeps/s390/s390-32/dl-machine.h92
-rw-r--r--sysdeps/s390/s390-32/elf/configure52
-rw-r--r--sysdeps/s390/s390-32/elf/configure.in37
-rw-r--r--sysdeps/s390/s390-64/dl-machine.h92
-rw-r--r--sysdeps/s390/s390-64/elf/configure52
-rw-r--r--sysdeps/s390/s390-64/elf/configure.in37
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/clone.S16
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S139
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h84
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/clone.S26
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/mmap.S2
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/socket.S2
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/syscall.S2
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S113
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h65
18 files changed, 750 insertions, 177 deletions
diff --git a/sysdeps/s390/Versions b/sysdeps/s390/Versions
new file mode 100644
index 0000000000..7136af2760
--- /dev/null
+++ b/sysdeps/s390/Versions
@@ -0,0 +1,6 @@
+ld {
+ GLIBC_2.3 {
+ # runtime interface to TLS
+ __tls_get_offset;
+ }
+} \ No newline at end of file
diff --git a/sysdeps/s390/dl-tls.h b/sysdeps/s390/dl-tls.h
new file mode 100644
index 0000000000..fbd85c1753
--- /dev/null
+++ b/sysdeps/s390/dl-tls.h
@@ -0,0 +1,73 @@
+/* Thread-local storage handling in the ELF dynamic linker. s390 version.
+ Copyright (C) 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. */
+
+
+/* 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;
+
+
+#ifdef SHARED
+/* This is the prototype for the GNU version. */
+extern void *__tls_get_addr (tls_index *ti) attribute_hidden;
+extern unsigned long __tls_get_offset (unsigned long got_offset);
+
+/* The special thing about the s390 TLS ABI is that we do not have the
+ standard __tls_get_addr function but the __tls_get_offset function
+ which differs in two important aspects:
+ 1) __tls_get_offset gets a got offset instead of a pointer to the
+ tls_index structure
+ 2) __tls_get_offset returns the offset of the requested variable to
+ the thread descriptor instead of a pointer to the variable.
+ */
+#if defined __s390x__
+asm("\n\
+ .text\n\
+ .globl __tls_get_offset\n\
+ .type __tls_get_offset, @function\n\
+ .align 4\n\
+__tls_get_offset:\n\
+ la %r2,0(%r2,%r12)\n\
+ jg __tls_get_addr\n\
+");
+#elif defined __s390__
+asm("\n\
+ .text\n\
+ .globl __tls_get_offset\n\
+ .type __tls_get_offset, @function\n\
+ .align 4\n\
+__tls_get_offset:\n\
+ basr %r3,0\n\
+0: la %r2,0(%r2,%r12)\n\
+ l %r4,1f-0b(%r3)\n\
+ b 0(%r4,%r3)\n\
+1: .long __tls_get_addr - 0b\n\
+");
+#endif
+
+#define GET_ADDR_OFFSET \
+ (ti->ti_offset - (unsigned long) __builtin_thread_pointer ())
+
+#define __TLS_GET_ADDR(__ti) \
+ (__tls_get_addr(__ti) + (unsigned long) __builtin_thread_pointer ())
+
+#endif
diff --git a/sysdeps/s390/libc-tls.c b/sysdeps/s390/libc-tls.c
new file mode 100644
index 0000000000..bc433f8f6f
--- /dev/null
+++ b/sysdeps/s390/libc-tls.c
@@ -0,0 +1,37 @@
+/* Thread-local storage handling in the ELF dynamic linker. IA-64 version.
+ Copyright (C) 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. */
+
+#include <sysdeps/generic/libc-tls.c>
+
+#if USE_TLS
+
+/* On s390, the literal pool entry that refers to __tls_get_offset
+ is not removed, even if all branches that use the literal pool
+ entry gets removed by TLS optimizations. To get binaries
+ statically linked __tls_get_offset is defined here but
+ aborts if it is used. */
+
+void *
+__tls_get_offset (size_t m, size_t offset)
+{
+ abort ();
+}
+
+#endif
+
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
index 557c04e4ea..6905814c41 100644
--- a/sysdeps/s390/s390-32/dl-machine.h
+++ b/sysdeps/s390/s390-32/dl-machine.h
@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. S390 Version.
- Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Carl Pederson & Martin Schwidefsky.
This file is part of the GNU C Library.
@@ -312,13 +312,22 @@ _dl_start_user:\n\
#define RTLD_START_SPECIAL_INIT /* nothing */
#endif
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
- PLT entries should not be allowed to define the value.
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable, so undefined references 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. */
-#define elf_machine_type_class(type) \
+#ifdef USE_TLS
+# define elf_machine_type_class(type) \
+ ((((type) == R_390_JMP_SLOT || (type) == R_390_TLS_DTPMOD \
+ || (type) == R_390_TLS_DTPOFF || (type) == R_390_TLS_TPOFF) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
+# define elf_machine_type_class(type) \
((((type) == R_390_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_390_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_390_JMP_SLOT
@@ -372,25 +381,90 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
{
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_390_RELATIVE, 0))
- *reloc_addr = map->l_addr + reloc->r_addend;
-#ifndef RTLD_BOOTSTRAP
- else if (__builtin_expect (r_type == R_390_NONE, 0))
- return;
+ {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+ /* This is defined in rtld.c, but nowhere in the static libc.a;
+ make the reference weak so static programs can still link.
+ This declaration cannot be done when compiling rtld.c
+ (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
+ common defn for _dl_rtld_map, which is incompatible with a
+ weak decl in the same file. */
+# ifndef SHARED
+ weak_extern (GL(dl_rtld_map));
+# endif
+ if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
+# endif
+ *reloc_addr = map->l_addr + reloc->r_addend;
+ }
+ else
#endif
+ if (__builtin_expect (r_type == R_390_NONE, 0))
+ return;
else
{
const Elf32_Sym *const refsym = sym;
+#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+ Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
+#else
Elf32_Addr value = RESOLVE (&sym, version, r_type);
+
+# ifndef RTLD_BOOTSTRAP
if (sym)
+# endif
value += sym->st_value;
+#endif /* use TLS and !RTLD_BOOTSTRAP */
switch (r_type)
{
case R_390_GLOB_DAT:
case R_390_JMP_SLOT:
- *reloc_addr = value;
+ *reloc_addr = value + reloc->r_addend;
+ break;
+
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+ case R_390_TLS_DTPMOD:
+# ifdef RTLD_BOOTSTRAP
+ /* During startup the dynamic linker is always the module
+ with index 1.
+ XXX If this relocation is necessary move before RESOLVE
+ call. */
+ *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
+ break;
+ case R_390_TLS_DTPOFF:
+# ifndef RTLD_BOOTSTRAP
+ /* During relocation all TLS symbols are defined and used.
+ Therefore the offset is already correct. */
+ if (sym != NULL)
+ *reloc_addr = sym->st_value + reloc->r_addend;
+# endif
break;
+ case R_390_TLS_TPOFF:
+ /* The offset is negative, forward from the thread pointer. */
+# ifdef RTLD_BOOTSTRAP
+ *reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset;
+# else
+ /* We know the offset of the object the symbol is contained in.
+ It is a negative value which will be added to the
+ thread pointer. */
+ if (sym != NULL)
+ {
+ CHECK_STATIC_TLS (map, sym_map);
+ *reloc_addr = (sym->st_value + reloc->r_addend
+ - sym_map->l_tls_offset);
+ }
+#endif
+ break;
+#endif /* use TLS */
+
#ifndef RTLD_BOOTSTRAP
case R_390_COPY:
if (sym == NULL)
diff --git a/sysdeps/s390/s390-32/elf/configure b/sysdeps/s390/s390-32/elf/configure
new file mode 100644
index 0000000000..64eff1f05f
--- /dev/null
+++ b/sysdeps/s390/s390-32/elf/configure
@@ -0,0 +1,52 @@
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/s390/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+echo "$as_me:$LINENO: checking for s390 TLS support" >&5
+echo $ECHO_N "checking for s390 TLS support... $ECHO_C" >&6
+if test "${libc_cv_390_tls+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat > conftest.s <<\EOF
+ .section ".tdata", "awT", @progbits
+foo: .long 25
+ .text
+ .long foo@TLSGD
+ .long foo@TLSLDM
+ .long foo@DTPOFF
+ .long foo@NTPOFF
+ .long foo@GOTNTPOFF
+ .long foo@INDNTPOFF
+ l %r1,foo@GOTNTPOFF(%r12)
+ l %r1,0(%r1):tls_load:foo
+ bas %r14,0(%r1,%r13):tls_gdcall:foo
+ bas %r14,0(%r1,%r13):tls_ldcall:foo
+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_390_tls=yes
+else
+ libc_cv_390_tls=no
+fi
+rm -f conftest*
+fi
+echo "$as_me:$LINENO: result: $libc_cv_390_tls" >&5
+echo "${ECHO_T}$libc_cv_390_tls" >&6
+if test $libc_cv_390_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/s390/s390-32/elf/configure.in b/sysdeps/s390/s390-32/elf/configure.in
new file mode 100644
index 0000000000..fcf9329995
--- /dev/null
+++ b/sysdeps/s390/s390-32/elf/configure.in
@@ -0,0 +1,37 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/s390/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+AC_CACHE_CHECK(for s390 TLS support, libc_cv_390_tls, [dnl
+cat > conftest.S <<\EOF
+ .section ".tdata", "awT", @progbits
+foo: .long 25
+ .text
+ .long foo@TLSGD
+ .long foo@TLSLDM
+ .long foo@DTPOFF
+ .long foo@NTPOFF
+ .long foo@GOTNTPOFF
+ .long foo@INDNTPOFF
+ l %r1,foo@GOTNTPOFF(%r12)
+ l %r1,0(%r1):tls_load:foo
+ bas %r14,0(%r1,%r13):tls_gdcall:foo
+ bas %r14,0(%r1,%r13):tls_ldcall:foo
+EOF
+dnl
+if AC_TRY_COMMAND(${CC-cc} -S $CFLAGS conftest.S 1>&AS_MESSAGE_LOG_FD); then
+ libc_cv_390_tls=yes
+else
+ libc_cv_390_tls=no
+fi
+rm -f conftest*])
+if test $libc_cv_390_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)
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
index a4033eeed1..e7ae3f77f8 100644
--- a/sysdeps/s390/s390-64/dl-machine.h
+++ b/sysdeps/s390/s390-64/dl-machine.h
@@ -1,6 +1,6 @@
/* Machine-dependent ELF dynamic relocation inline functions.
64 bit S/390 Version.
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
@@ -284,13 +284,22 @@ _dl_start_user:\n\
#define RTLD_START_SPECIAL_INIT /* nothing */
#endif
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
- PLT entries should not be allowed to define the value.
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable, so undefined references 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. */
-#define elf_machine_type_class(type) \
+#ifdef USE_TLS
+# define elf_machine_type_class(type) \
+ ((((type) == R_390_JMP_SLOT || (type) == R_390_TLS_DTPMOD \
+ || (type) == R_390_TLS_DTPOFF || (type) == R_390_TLS_TPOFF) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
+# define elf_machine_type_class(type) \
((((type) == R_390_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_390_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_390_JMP_SLOT
@@ -340,18 +349,41 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
{
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_390_RELATIVE, 0))
- *reloc_addr = map->l_addr + reloc->r_addend;
-#ifndef RTLD_BOOTSTRAP
- else if (__builtin_expect (r_type == R_390_NONE, 0))
- return;
+ {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+ /* This is defined in rtld.c, but nowhere in the static libc.a;
+ make the reference weak so static programs can still link.
+ This declaration cannot be done when compiling rtld.c
+ (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
+ common defn for _dl_rtld_map, which is incompatible with a
+ weak decl in the same file. */
+# ifndef SHARED
+ weak_extern (GL(dl_rtld_map));
+# endif
+ if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
+# endif
+ *reloc_addr = map->l_addr + reloc->r_addend;
+ }
+ else
#endif
+ if (__builtin_expect (r_type == R_390_NONE, 0))
+ return;
else
{
const Elf64_Sym *const refsym = sym;
+#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+ Elf64_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
+#else
Elf64_Addr value = RESOLVE (&sym, version, r_type);
+
+# ifndef RTLD_BOOTSTRAP
if (sym)
+# endif
value += sym->st_value;
+#endif /* use TLS and !RTLD_BOOTSTRAP */
switch (r_type)
{
@@ -359,6 +391,48 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
case R_390_JMP_SLOT:
*reloc_addr = value + reloc->r_addend;
break;
+
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+ case R_390_TLS_DTPMOD:
+# ifdef RTLD_BOOTSTRAP
+ /* During startup the dynamic linker is always the module
+ with index 1.
+ XXX If this relocation is necessary move before RESOLVE
+ call. */
+ *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
+ break;
+ case R_390_TLS_DTPOFF:
+# ifndef RTLD_BOOTSTRAP
+ /* During relocation all TLS symbols are defined and used.
+ Therefore the offset is already correct. */
+ if (sym != NULL)
+ *reloc_addr = sym->st_value + reloc->r_addend;
+# endif
+ break;
+ case R_390_TLS_TPOFF:
+ /* The offset is negative, forward from the thread pointer. */
+# ifdef RTLD_BOOTSTRAP
+ *reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset;
+# else
+ /* We know the offset of the object the symbol is contained in.
+ It is a negative value which will be added to the
+ thread pointer. */
+ if (sym != NULL)
+ {
+ CHECK_STATIC_TLS (map, sym_map);
+ *reloc_addr = (sym->st_value + reloc->r_addend
+ - sym_map->l_tls_offset);
+ }
+#endif
+ break;
+#endif /* use TLS */
+
#ifndef RTLD_BOOTSTRAP
case R_390_COPY:
if (sym == NULL)
@@ -439,7 +513,7 @@ elf_machine_lazy_rel (struct link_map *map,
Elf64_Addr l_addr, const Elf64_Rela *reloc)
{
Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
- const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+ const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
/* Check for unexpected PLT reloc type. */
if (__builtin_expect (r_type == R_390_JMP_SLOT, 1))
{
diff --git a/sysdeps/s390/s390-64/elf/configure b/sysdeps/s390/s390-64/elf/configure
new file mode 100644
index 0000000000..42fc6e6a5f
--- /dev/null
+++ b/sysdeps/s390/s390-64/elf/configure
@@ -0,0 +1,52 @@
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/s390/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+echo "$as_me:$LINENO: checking for s390 TLS support" >&5
+echo $ECHO_N "checking for s390 TLS support... $ECHO_C" >&6
+if test "${libc_cv_390_tls+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat > conftest.s <<\EOF
+ .section ".tdata", "awT", @progbits
+foo: .long 25
+ .text
+ .quad foo@TLSGD
+ .quad foo@TLSLDM
+ .quad foo@DTPOFF
+ .quad foo@NTPOFF
+ .quad foo@GOTNTPOFF
+ .quad foo@INDNTPOFF
+ lg %r1,foo@GOTNTPOFF(%r12)
+ lg %r1,0(%r1):tls_load:foo
+ brasl %r14,__tls_get_offset@plt:tls_gdcall:foo
+ brasl %r14,__tls_get_offset@plt:tls_ldcall:foo
+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_390_tls=yes
+else
+ libc_cv_390_tls=no
+fi
+rm -f conftest*
+fi
+echo "$as_me:$LINENO: result: $libc_cv_390_tls" >&5
+echo "${ECHO_T}$libc_cv_390_tls" >&6
+if test $libc_cv_390_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/s390/s390-64/elf/configure.in b/sysdeps/s390/s390-64/elf/configure.in
new file mode 100644
index 0000000000..ac953fcff3
--- /dev/null
+++ b/sysdeps/s390/s390-64/elf/configure.in
@@ -0,0 +1,37 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/s390/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+AC_CACHE_CHECK(for s390 TLS support, libc_cv_390_tls, [dnl
+cat > conftest.S <<\EOF
+ .section ".tdata", "awT", @progbits
+foo: .long 25
+ .text
+ .quad foo@TLSGD
+ .quad foo@TLSLDM
+ .quad foo@DTPOFF
+ .quad foo@NTPOFF
+ .quad foo@GOTNTPOFF
+ .quad foo@INDNTPOFF
+ lg %r1,foo@GOTNTPOFF(%r12)
+ lg %r1,0(%r1):tls_load:foo
+ brasl %r14,__tls_get_offset@plt:tls_gdcall:foo
+ brasl %r14,__tls_get_offset@plt:tls_ldcall:foo
+EOF
+dnl
+if AC_TRY_COMMAND(${CC-cc} -S $CFLAGS conftest.S 1>&AS_MESSAGE_LOG_FD); then
+ libc_cv_390_tls=yes
+else
+ libc_cv_390_tls=no
+fi
+rm -f conftest*])
+if test $libc_cv_390_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)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
index c93570ed72..23fb4647ee 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
@@ -24,20 +24,24 @@
#define _ERRNO_H 1
#include <bits/errno.h>
-/*int __clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg);*/
-/* sys_clone(void *child_stack, unsigned long flags) */
+/* int __clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ void *tls, pid_t *parent_tid, pid_t *child_tid); */
+/* sys_clone (void *child_stack, unsigned long flags,
+ pid_t *parent_tid, pid_t *child_tid, void *tls); */
.text
ENTRY(__clone)
/* Sanity check arguments & move registers */
+ lr %r0,%r5 /* move *arg out of the way */
ltr %r1,%r2 /* no NULL function pointers */
lhi %r2,-EINVAL
jz SYSCALL_ERROR_LABEL
ltr %r3,%r3 /* no NULL stack pointers */
jz SYSCALL_ERROR_LABEL
- /* move child_stack and flags, then call SVC */
+ /* set up registers, then call SVC */
lr %r2,%r3
lr %r3,%r4
+ lm %r4,%r5,96(%r15)
svc SYS_ify(clone)
ltr %r2,%r2 /* check return code */
jm SYSCALL_ERROR_LABEL
@@ -45,10 +49,10 @@ ENTRY(__clone)
br %r14
thread_start:
- /* fn is in gpr 1, arg in gpr 5 */
- lr %r2,%r5 /* set first parameter to void *arg */
- sr %r11,%r11 /* terminate the stack frame */
+ /* fn is in gpr 1, arg in gpr 0 */
+ lr %r2,%r0 /* set first parameter to void *arg */
ahi %r15,-96 /* make room on the stack for the save area */
+ xc 0(4,%r15),0(%r15)
basr %r14,%r1 /* jump to fn */
#ifdef PIC
basr %r12,0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S
index 98b00722d8..94d772f67e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
@@ -31,59 +31,94 @@
.text
ENTRY(__syscall_error)
#ifndef PIC
-#ifndef _LIBC_REENTRANT
- lcr %r2,%r2
- basr %r1,0
-.L0: l %r1,.L1-.L0(%r1)
- st %r2,0(0,%r1)
- lhi %r2,-1
- br %r14
-.L1: .long errno
-#else
- stm %r11,%r15,44(%r15)
- lr %r0,%r15
- ahi %r15,-96
- st %r0,0(%r15)
- lcr %r11,%r2
- basr %r13,0
-.L0: l %r1,.L1-.L0(%r13)
- basr %r14,%r1
- st %r11,0(%r2)
- lhi %r2,-1
- l %r15,0(%r15)
- lm %r11,%r15,44(%r15)
- br %r14
-.L1: .long __errno_location
+# if USE___THREAD
+# ifndef NOT_IN_libc
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+ basr %r1,0
+0: l %r1,1f-0b(%r1)
+ ear %r3,%a0
+ lcr %r2,%r2
+ st %r2,0(%r1,%r3)
+ lhi %r2,-1
+ br %r14
+1: .long SYSCALL_ERROR_ERRNO@ntpoff
+# elif !defined _LIBC_REENTRANT
+ basr %r1,0
+0: l %r1,1f-0b(%r1)
+ lcr %r2,%r2
+ st %r2,0(%r1)
+ lhi %r2,-1
+ br %r14
+1: .long errno
+# else
+ stm %r13,%r15,52(%r15)
+ lr %r0,%r15
+ ahi %r15,-96
+ lcr %r13,%r2
+ st %r0,0(%r15)
+ basr %r1,0
+0: l %r1,1f-0b(%r1)
+ basr %r14,%r1
+ st %r13,0(%r2)
+ lm %r13,%r15,148(%r15)
+ lhi %r2,-1
+ br %r14
+1: .long __errno_location
#endif
#else
-#ifndef _LIBC_REENTRANT
- basr %r1,0
-.L0: al %r1,.L1-.L0(%r1)
- l %r1,errno@GOT12(%r1)
- lcr %r2,%r2
- st %r2,0(0,%r1)
- lhi %r2,-1
- br %r14
-.L1: .long _GLOBAL_OFFSET_TABLE_-0b
-#else
- stm %r11,%r15,44(%r15)
- lr %r0,%r15
- ahi %r15,-96
- st %r0,0(%r15)
- lcr %r11,%r2
- basr %r13,0
-.L0: l %r12,.L1-.L0(%r13)
- ar %r12,%r13
- l %r14,.L2-.L0(%r13)
- bas %r14,0(%r14,%r13)
- st %r11,0(0,%r2)
- lhi %r2,-1
- l %r15,0(%r15)
- lm %r11,%r15,44(%r15)
- br %r14
-.L1: .long _GLOBAL_OFFSET_TABLE_ - .L0
-.L2: .long __errno_location@PLT - .L0
-#endif
+# if RTLD_PRIVATE_ERRNO
+ basr %r1,0
+0: al %r1,1f-0b(%r1)
+ lcr %r2,%r2
+ st %r2,0(%r1)
+ lhi %r2,-1
+ br %r14
+1: .long errno - 0b
+# elif USE___THREAD
+# ifndef NOT_IN_libc
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+ basr %r1,0
+0: al %r1,1f-0b(%r1)
+ ear %r3,%a0
+ l %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1)
+ lcr %r2,%r2
+ st %r2,0(%r1,%r3)
+ lhi %r2,-1
+ br %r14
+1: .long _GLOBAL_OFFSET_TABLE_-0b
+# elif !defined _LIBC_REENTRANT
+ basr %r1,0
+0: al %r1,1f-0b(%r1)
+ l %r1,errno@GOT(%r1)
+ lcr %r2,%r2
+ st %r2,0(0,%r1)
+ lhi %r2,-1
+ br %r14
+1: .long _GLOBAL_OFFSET_TABLE_-0b
+# else
+ stm %r11,%r15,44(%r15)
+ lr %r0,%r15
+ ahi %r15,-96
+ lcr %r11,%r2
+ st %r0,0(%r15)
+ basr %r13,0
+0: l %r12,1f-0b(%r13)
+ l %r1,2f-0b(%r13)
+ la %r12,0(%r12,%r13)
+ bas %r14,0(%r1,%r13)
+ st %r11,0(%r2)
+ lm %r11,%r15,140(%r15)
+ lhi %r2,-1
+ br %r14
+1: .long _GLOBAL_OFFSET_TABLE_-0b
+2: .long __errno_location@PLT-0b
+# endif
#endif
END (__syscall_error)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
index e89e6a1425..f7bfb8dac1 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
@@ -45,8 +45,6 @@
number. Linus said he will make sure the no syscall returns a value
in -1 .. -4095 as a valid result so we can savely test with -4095. */
-#define SYSCALL_ERROR_LABEL 0f
-
#undef PSEUDO
#define PSEUDO(name, syscall_name, args) \
.text; \
@@ -54,42 +52,70 @@
DO_CALL (syscall_name, args); \
lhi %r4,-4095 ; \
clr %r2,%r4 ; \
- jnl SYSCALL_ERROR_LABEL ; \
- L(pseudo_end):
+ jnl SYSCALL_ERROR_LABEL
#undef PSEUDO_END
#define PSEUDO_END(name) \
SYSCALL_ERROR_HANDLER; \
END (name)
-#ifndef _LIBC_REENTRANT
#ifndef PIC
-#define SYSCALL_ERROR_HANDLER \
-0: lcr %r2,%r2 ; \
- basr %r1,0 ; \
-1: l %r1,2f-1b(%r1) \
- st %r2,0(%r1) \
- lhi %r2,-1 \
- br %r14 \
-2: .long errno
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0: basr %r1,0; \
+1: l %r1,2f-1b(%r1); \
+ br %r1; \
+2: .long syscall_error
#else
-#define SYSCALL_ERROR_HANDLER \
-0: basr %r1,0 ; \
-1: al %r1,2f-1b(%r1) ; \
- l %r1,errno@GOT12(%r1) ; \
- lcr %r2,%r2 ; \
- st %r2,0(%r1) ; \
- lhi %r2,-1 ; \
- br %r14 ; \
-2: .long _GLOBAL_OFFSET_TABLE_-1b
+# if RTLD_PRIVATE_ERRNO
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0: basr %r1,0; \
+1: al %r1,2f-1b(%r1); \
+ lcr %r2,%r2; \
+ st %r2,0(%r1); \
+ lhi %r2,-1; \
+ br %r14; \
+2: .long errno-1b
+# elif defined _LIBC_REENTRANT
+# if USE___THREAD
+# ifndef NOT_IN_libc
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0: lcr %r0,%r2; \
+ basr %r1,0; \
+1: al %r1,2f-1b(%r1); \
+ l %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1) \
+ ear %r2,%a0 \
+ st %r0,0(%r1,%r2); \
+ lhi %r2,-1; \
+ br %r14; \
+2: .long _GLOBAL_OFFSET_TABLE_-1b
+# else
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0: basr %r1,0; \
+1: al %r1,2f-1b(%r1); \
+ br %r1; \
+2: .long syscall_error@plt-1b
+# endif
+# else
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0: basr %r1,0; \
+1: al %r1,2f-1b(%r1); \
+ l %r1,errno@GOT(%r1); \
+ lcr %r2,%r2; \
+ st %r2,0(%r1); \
+ lhi %r2,-1; \
+ br %r14; \
+2: .long _GLOBAL_OFFSET_TABLE_-1b
+# endif /* _LIBC_REENTRANT */
#endif /* PIC */
-#else
-#define SYSCALL_ERROR_HANDLER \
-0: basr %r1,0 ; \
-1: al %r1,2f-1b(%r1) ; \
- br %r1 ; \
-2: .long __syscall_error@PLT-1b
-#endif /* _LIBC_REENTRANT */
/* Linux takes system call arguments in registers:
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
index 992cb2f10f..117411824f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
@@ -25,32 +25,40 @@
#define _ERRNO_H 1
#include <bits/errno.h>
+/* int __clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ void *tls, pid_t *parent_tid, pid_t *child_tid); */
+/* sys_clone (void *child_stack, unsigned long flags,
+ pid_t *parent_tid, pid_t *child_tid, void *tls); */
+
.text
ENTRY(__clone)
/* Sanity check arguments & move registers */
+ lgr %r0,%r5 /* move *arg out of the way */
ltgr %r1,%r2 /* no NULL function pointers */
lghi %r2,-EINVAL
- jz SYSCALL_ERROR_LABEL
+ jgz SYSCALL_ERROR_LABEL
ltgr %r3,%r3 /* no NULL stack pointers */
- jz SYSCALL_ERROR_LABEL
- /* move child_stack and flags, then call SVC */
+ jgz SYSCALL_ERROR_LABEL
+ /* set up registers, then call SVC */
lgr %r2,%r3
lgr %r3,%r4
+ lmg %r4,%r5,160(%r15)
svc SYS_ify(clone)
ltgr %r2,%r2 /* check return code */
- jm SYSCALL_ERROR_LABEL
+ jgm SYSCALL_ERROR_LABEL
jz thread_start
br %r14
thread_start:
- /* fn is in gpr 1, arg in gpr 5 */
- lgr %r2,%r5 /* set first parameter to void *arg */
- sgr %r11,%r11 /* terminate the stack frame */
+ /* fn is in gpr 1, arg in gpr 0 */
+ lgr %r2,%r0 /* set first parameter to void *arg */
aghi %r15,-160 /* make room on the stack for the save area */
+ xc 0(8,%r15),0(%r15)
basr %r14,%r1 /* jump to fn */
#ifdef PIC
- larl %r12,_GLOBAL_OFFSET_TABLE_
-#endif
jg _exit@PLT /* branch to _exit -> thread termination */
+#else
+ jg _exit /* branch to _exit -> thread termination */
+#endif
PSEUDO_END (__clone)
weak_alias (__clone, clone)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S b/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
index 23205901d4..8c94fd4c28 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
@@ -55,7 +55,7 @@ ENTRY(__mmap)
/* Check gpr 2 for error. */
lghi %r0,-4096
clgr %r2,%r0
- jnl SYSCALL_ERROR_LABEL
+ jgnl SYSCALL_ERROR_LABEL
/* Successful; return the syscall's value. */
br %r14
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/socket.S b/sysdeps/unix/sysv/linux/s390/s390-64/socket.S
index c9bd02baee..3a2454eba4 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/socket.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/socket.S
@@ -93,7 +93,7 @@ ENTRY(__socket)
/* gpr2 is < 0 if there was an error. */
lghi %r0,-125
clgr %r2,%r0
- jnl SYSCALL_ERROR_LABEL
+ jgnl SYSCALL_ERROR_LABEL
/* Successful; return the syscall's value. */
br %r14
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/syscall.S b/sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
index 047c667542..718d559c3b 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
@@ -45,7 +45,7 @@ ENTRY (syscall)
lghi %r0,-4095
clgr %r2,%r0 /* Check R2 for error. */
- jnl SYSCALL_ERROR_LABEL
+ jgnl SYSCALL_ERROR_LABEL
br %r14 /* Return to caller. */
.L1: .word 0x0A00 /* Opcode for SVC 0. */
PSEUDO_END (syscall)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S
index a29b0b983a..84c747aef0 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
@@ -29,47 +29,84 @@
#undef CALL_MCOUNT
#define CALL_MCOUNT
- .text
+.text
ENTRY(__syscall_error)
#ifndef PIC
-#ifndef _LIBC_REENTRANT
- lcr %r2,%r2
- larl %r1,errno
- st %r2,0(%r1)
- lghi %r2,-1
- br %r14
-#else
- stmg %r13,%r15,104(%r15)
- lgr %r0,%r15
- aghi %r15,-160
- lcr %r13,%r2
- stg %r0,0(%r15)
- brasl %r14,__errno_location
- st %r13,0(%r2)
- lmg %r13,%r15,264(%r15)
- lghi %r2,-1
- br %r14
+# if USE___THREAD
+# ifndef NOT_IN_libc
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+ basr %r1,0
+0: lg %r1,1f-0b(%r1)
+ ear %r3,%a0
+ sllg %r3,%r3,32
+ ear %r3,%a1
+ lcr %r2,%r2
+ st %r2,0(%r1,%r3)
+ lghi %r2,-1
+ br %r14
+1: .quad SYSCALL_ERROR_ERRNO@ntpoff
+# elif !defined _LIBC_REENTRANT
+ larl %r1,errno
+ lcr %r2,%r2
+ st %r2,0(%r1)
+ lghi %r2,-1
+ br %r14
+# else
+ stmg %r13,%r15,104(%r15)
+ lgr %r0,%r15
+ aghi %r15,-160
+ lcr %r13,%r2
+ stg %r0,0(%r15)
+ brasl %r14,__errno_location
+ st %r13,0(%r2)
+ lmg %r13,%r15,264(%r15)
+ lghi %r2,-1
+ br %r14
#endif
#else
-#ifndef _LIBC_REENTRANT
- larl %r1,_GLOBAL_OFFSET_TABLE_
- lg %r1,errno@GOT(%r1)
- lcr %r2,%r2
- st %r2,0(%r1)
- lghi %r2,-1
- br %r14
-#else
- stmg %r13,%r15,104(%r15)
- lgr %r0,%r15
- aghi %r15,-160
- lcr %r13,%r2
- stg %r0,0(%r15)
- brasl %r14,__errno_location@PLT
- st %r13,0(%r2)
- lmg %r13,%r15,264(%r15)
- lghi %r2,-1
- br %r14
-#endif
+# if RTLD_PRIVATE_ERRNO
+ larl %r1,errno
+ lcr %r2,%r2
+ st %r2,0(%r1)
+ lghi %r2,-1
+ br %r14
+# elif USE___THREAD
+# ifndef NOT_IN_libc
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+ larl %r1,_GLOBAL_OFFSET_TABLE_
+ lg %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1)
+ ear %r3,%a0
+ sllg %r3,%r3,32
+ ear %r3,%a1
+ lcr %r2,%r2
+ st %r2,0(%r1,%r3)
+ lghi %r2,-1
+ br %r14
+# elif !defined _LIBC_REENTRANT
+ larl %r1,_GLOBAL_OFFSET_TABLE_
+ lg %r1,errno@GOT(%r1)
+ lcr %r2,%r2
+ st %r2,0(%r1)
+ lghi %r2,-1
+ br %r14
+# else
+ stmg %r13,%r15,104(%r15)
+ lgr %r0,%r15
+ aghi %r15,-160
+ lcr %r13,%r2
+ stg %r0,0(%r15)
+ brasl %r14,__errno_location@PLT
+ st %r13,0(%r2)
+ lmg %r13,%r15,264(%r15)
+ lghi %r2,-1
+ br %r14
+# endif
#endif
END (__syscall_error)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
index dbe77df979..976fd26f50 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
@@ -46,8 +46,6 @@
number. Linus said he will make sure the no syscall returns a value
in -1 .. -4095 as a valid result so we can savely test with -4095. */
-#define SYSCALL_ERROR_LABEL 0f
-
#undef PSEUDO
#define PSEUDO(name, syscall_name, args) \
.text; \
@@ -55,35 +53,58 @@
DO_CALL (syscall_name, args); \
lghi %r4,-4095 ; \
clgr %r2,%r4 ; \
- jnl SYSCALL_ERROR_LABEL ; \
- L(pseudo_end):
+ jgnl SYSCALL_ERROR_LABEL
#undef PSEUDO_END
#define PSEUDO_END(name) \
SYSCALL_ERROR_HANDLER; \
END (name)
-#ifndef _LIBC_REENTRANT
#ifndef PIC
-#define SYSCALL_ERROR_HANDLER \
-0: lcr %r2,%r2 ; \
- larl %r1,errno ; \
- st %r2,0(%r1) ; \
- lghi %r2,-1 ; \
- br %r14
+# define SYSCALL_ERROR_LABEL syscall_error
+# define SYSCALL_ERROR_HANDLER
#else
-#define SYSCALL_ERROR_HANDLER \
-0: larl %r1,_GLOBAL_OFFSET_TABLE_ ; \
- lg %r1,errno@GOT(%r1) ; \
- lcr %r2,%r2 ; \
- st %r2,0(%r1) ; \
- lghi %r2,-1 ; \
- br %r14
+# if RTLD_PRIVATE_ERRNO
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0: larl %r1,errno; \
+ lcr %r2,%r2; \
+ st %r2,0(%r1); \
+ lghi %r2,-1; \
+ br %r14
+# elif defined _LIBC_REENTRANT
+# if USE___THREAD
+# ifndef NOT_IN_libc
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0: lcr %r0,%r2; \
+ larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \
+ lg %r1,0(%r1); \
+ ear %r2,%a0; \
+ sllg %r2,%r2,32; \
+ ear %r2,%a1; \
+ st %r0,0(%r1,%r2); \
+ lghi %r2,-1; \
+ br %r14
+# else
+# define SYSCALL_ERROR_LABEL syscall_error@plt
+# define SYSCALL_ERROR_HANDLER
+# endif
+# else
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0: larl %r1,_GLOBAL_OFFSET_TABLE_; \
+ lg %r1,errno@GOT(%r1); \
+ lcr %r2,%r2; \
+ st %r2,0(%r1); \
+ lghi %r2,-1; \
+ br %r14
+# endif /* _LIBC_REENTRANT */
#endif /* PIC */
-#else
-#define SYSCALL_ERROR_HANDLER \
-0: jg __syscall_error@PLT
-#endif /* _LIBC_REENTRANT */
/* Linux takes system call arguments in registers: