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.
This commit is contained in:
Ulrich Drepper 2003-01-28 10:42:28 +00:00
parent 772e3426a7
commit e6ebd2e4db
30 changed files with 1344 additions and 349 deletions

View File

@ -1,3 +1,37 @@
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.
2003-01-28 Ulrich Drepper <drepper@redhat.com>
* sysdeps/unix/common/pause.c (do_pause): New function. Split

103
elf/elf.h
View File

@ -2228,36 +2228,83 @@ typedef Elf32_Addr Elf32_Conflict;
/* Additional s390 relocs */
#define R_390_NONE 0 /* No reloc. */
#define R_390_8 1 /* Direct 8 bit. */
#define R_390_12 2 /* Direct 12 bit. */
#define R_390_16 3 /* Direct 16 bit. */
#define R_390_32 4 /* Direct 32 bit. */
#define R_390_PC32 5 /* PC relative 32 bit. */
#define R_390_GOT12 6 /* 12 bit GOT offset. */
#define R_390_GOT32 7 /* 32 bit GOT offset. */
#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */
#define R_390_COPY 9 /* Copy symbol at runtime. */
#define R_390_GLOB_DAT 10 /* Create GOT entry. */
#define R_390_JMP_SLOT 11 /* Create PLT entry. */
#define R_390_RELATIVE 12 /* Adjust by program base. */
#define R_390_GOTOFF 13 /* 32 bit offset to GOT. */
#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */
#define R_390_GOT16 15 /* 16 bit GOT offset. */
#define R_390_PC16 16 /* PC relative 16 bit. */
#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */
#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */
#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */
#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */
#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */
#define R_390_64 22 /* Direct 64 bit. */
#define R_390_PC64 23 /* PC relative 64 bit. */
#define R_390_GOT64 24 /* 64 bit GOT offset. */
#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */
#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */
#define R_390_NONE 0 /* No reloc. */
#define R_390_8 1 /* Direct 8 bit. */
#define R_390_12 2 /* Direct 12 bit. */
#define R_390_16 3 /* Direct 16 bit. */
#define R_390_32 4 /* Direct 32 bit. */
#define R_390_PC32 5 /* PC relative 32 bit. */
#define R_390_GOT12 6 /* 12 bit GOT offset. */
#define R_390_GOT32 7 /* 32 bit GOT offset. */
#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */
#define R_390_COPY 9 /* Copy symbol at runtime. */
#define R_390_GLOB_DAT 10 /* Create GOT entry. */
#define R_390_JMP_SLOT 11 /* Create PLT entry. */
#define R_390_RELATIVE 12 /* Adjust by program base. */
#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */
#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */
#define R_390_GOT16 15 /* 16 bit GOT offset. */
#define R_390_PC16 16 /* PC relative 16 bit. */
#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */
#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */
#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */
#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */
#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */
#define R_390_64 22 /* Direct 64 bit. */
#define R_390_PC64 23 /* PC relative 64 bit. */
#define R_390_GOT64 24 /* 64 bit GOT offset. */
#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */
#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */
#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */
#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */
#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */
#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */
#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */
#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */
#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */
#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */
#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */
#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */
#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */
#define R_390_TLS_GDCALL 38 /* Tag for function call in general
dynamic TLS code. */
#define R_390_TLS_LDCALL 39 /* Tag for function call in local
dynamic TLS code. */
#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic
thread local data. */
#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic
thread local data. */
#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS
block offset. */
#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS
block offset. */
#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS
block offset. */
#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic
thread local data in LE code. */
#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic
thread local data in LE code. */
#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for
negated static TLS block offset. */
#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for
negated static TLS block offset. */
#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for
negated static TLS block offset. */
#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to
static TLS block. */
#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to
static TLS block. */
#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS
block. */
#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS
block. */
#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */
#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */
#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS
block. */
/* Keep this the last entry. */
#define R_390_NUM 27
#define R_390_NUM 57
/* CRIS relocations. */
#define R_CRIS_NONE 0

View File

@ -367,6 +367,196 @@ register void *__gp __asm__("$29");
"o5", "o7"); \
__o0; })
#elif defined __s390x__
# define TLS_LE(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.quad " #x "@ntpoff\n" \
"1:\tlg %0,0(%0)" \
: "=a" (__offset) : : "cc" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# ifdef PIC
# define TLS_IE(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.quad " #x "@gotntpoff\n" \
"1:\tlg %0,0(%0)\n\t" \
"lg %0,0(%0,%%r12):tls_load:" #x \
: "=&a" (__offset) : : "cc" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# else
# define TLS_IE(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.quad " #x "@indntpoff\n" \
"1:\t lg %0,0(%0)\n\t" \
"lg %0,0(%0):tls_load:" #x \
: "=&a" (__offset) : : "cc" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# endif
# ifdef PIC
# define TLS_LD(x) \
({ unsigned long __offset, __save12; \
asm ("bras %0,1f\n" \
"0:\t.quad " #x "@tlsldm\n\t" \
".quad " #x "@dtpoff\n" \
"1:\tlgr %1,%%r12\n\t" \
"larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
"lg %%r2,0(%0)\n\t" \
"brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \
"lg %0,8(%0)\n\t" \
"algr %0,%%r2\n\t" \
"lgr %%r12,%1" \
: "=&a" (__offset), "=&a" (__save12) \
: : "cc", "0", "1", "2", "3", "4", "5" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# else
# define TLS_LD(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.quad " #x "@tlsldm\n\t" \
".quad " #x "@dtpoff\n" \
"1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
"lg %%r2,0(%0)\n\t" \
"brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \
"lg %0,8(%0)\n\t" \
"algr %0,%%r2" \
: "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# endif
# ifdef PIC
# define TLS_GD(x) \
({ unsigned long __offset, __save12; \
asm ("bras %0,1f\n" \
"0:\t.quad " #x "@tlsgd\n" \
"1:\tlgr %1,%%r12\n\t" \
"larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
"lg %%r2,0(%0)\n\t" \
"brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \
"lgr %0,%%r2\n\t" \
"lgr %%r12,%1" \
: "=&a" (__offset), "=&a" (__save12) \
: : "cc", "0", "1", "2", "3", "4", "5" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# else
# define TLS_GD(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.quad " #x "@tlsgd\n" \
"1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
"lg %%r2,0(%0)\n\t" \
"brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \
"lgr %0,%%r2" \
: "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# endif
#elif defined __s390__
# define TLS_LE(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.long " #x "@ntpoff\n" \
"1:\tl %0,0(%0)" \
: "=a" (__offset) : : "cc" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# ifdef PIC
# define TLS_IE(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.long " #x "@gotntpoff\n" \
"1:\tl %0,0(%0)\n\t" \
"l %0,0(%0,%%r12):tls_load:" #x \
: "=&a" (__offset) : : "cc" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# else
# define TLS_IE(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.long " #x "@indntpoff\n" \
"1:\t l %0,0(%0)\n\t" \
"l %0,0(%0):tls_load:" #x \
: "=&a" (__offset) : : "cc" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# endif
# ifdef PIC
# define TLS_LD(x) \
({ unsigned long __offset, __save12; \
asm ("bras %0,1f\n" \
"0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \
".long __tls_get_offset@plt-0b\n\t" \
".long " #x "@tlsldm\n\t" \
".long " #x "@dtpoff\n" \
"1:\tlr %1,%%r12\n\t" \
"l %%r12,0(%0)\n\t" \
"la %%r12,0(%%r12,%0)\n\t" \
"l %%r1,4(%0)\n\t" \
"l %%r2,8(%0)\n\t" \
"bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t" \
"l %0,12(%0)\n\t" \
"alr %0,%%r2\n\t" \
"lr %%r12,%1" \
: "=&a" (__offset), "=&a" (__save12) \
: : "cc", "0", "1", "2", "3", "4", "5" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# else
# define TLS_LD(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \
".long __tls_get_offset@plt\n\t" \
".long " #x "@tlsldm\n\t" \
".long " #x "@dtpoff\n" \
"1:\tl %%r12,0(%0)\n\t" \
"l %%r1,4(%0)\n\t" \
"l %%r2,8(%0)\n\t" \
"bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t" \
"l %0,12(%0)\n\t" \
"alr %0,%%r2" \
: "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# endif
# ifdef PIC
# define TLS_GD(x) \
({ unsigned long __offset, __save12; \
asm ("bras %0,1f\n" \
"0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \
".long __tls_get_offset@plt-0b\n\t" \
".long " #x "@tlsgd\n" \
"1:\tlr %1,%%r12\n\t" \
"l %%r12,0(%0)\n\t" \
"la %%r12,0(%%r12,%0)\n\t" \
"l %%r1,4(%0)\n\t" \
"l %%r2,8(%0)\n\t" \
"bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t" \
"lr %0,%%r2\n\t" \
"lr %%r12,%1" \
: "=&a" (__offset), "=&a" (__save12) \
: : "cc", "0", "1", "2", "3", "4", "5" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# else
# define TLS_GD(x) \
({ unsigned long __offset; \
asm ("bras %0,1f\n" \
"0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \
".long __tls_get_offset@plt\n\t" \
".long " #x "@tlsgd\n" \
"1:\tl %%r12,0(%0)\n\t" \
"l %%r1,4(%0)\n\t" \
"l %%r2,8(%0)\n\t" \
"bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t" \
"lr %0,%%r2" \
: "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" ); \
(int *) (__builtin_thread_pointer() + __offset); })
# endif
#else
# error "No support for this architecture so far."
#endif

View File

@ -1,3 +1,17 @@
2003-01-27 Martin Schwidefsky <schwidefsky@de.ibm.com>
* sysdeps/s390/s390-32/pt-machine.h (THREAD_SELF, INIT_THREAD_SELF):
Define TLS versions.
* sysdeps/s390/s390-64/pt-machine.h (THREAD_SELF, INIT_THREAD_SELF):
Likewise.
* sysdeps/s390/tls.h [HAVE_TLS_SUPPORT] (USE_TLS, TLS_INIT_TCB_SIZE,
TLS_INIT_TCB_ALIGN, TLS_TCB_SIZE, TLS_TCB_ALIGN, TLS_TCB_AT_TP,
INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV, TLS_INIT_TP, THREAD_DTV):
Define.
* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): Use
branch with 32 bit offset.
* sysdeps/unix/sysv/linux/s390/s390-64/vfork.S: Likewise.
2003-01-24 Jakub Jelinek <jakub@redhat.com>
* sysdeps/sparc/sparc32/pt-machine.h (__thread_self): Change to %g7,

View File

@ -58,6 +58,13 @@ testandset (int *spinlock)
#define CURRENT_STACK_FRAME stack_pointer
register char * stack_pointer __asm__ ("15");
#ifdef USE_TLS
/* Return the thread descriptor for the current thread. */
# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ())
/* Initialize the thread-unique value. */
#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr)
#else
/* Return the thread descriptor for the current thread.
S/390 registers uses access register 0 as "thread register". */
#define THREAD_SELF ({ \
@ -70,6 +77,7 @@ register char * stack_pointer __asm__ ("15");
#define INIT_THREAD_SELF(descr, nr) ({ \
__asm__ ("sar %%a0,%0" : : "d" (descr) ); \
})
#endif
/* Access to data in the thread descriptor is easy. */
#define THREAD_GETMEM(descr, member) THREAD_SELF->member

View File

@ -58,6 +58,13 @@ testandset (int *spinlock)
#define CURRENT_STACK_FRAME stack_pointer
register char * stack_pointer __asm__ ("15");
#ifdef USE_TLS
/* Return the thread descriptor for the current thread. */
# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ())
/* Initialize the thread-unique value. */
#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr)
#else
/* Return the thread descriptor for the current thread.
64 bit S/390 uses access register 0 and 1 as "thread register". */
#define THREAD_SELF ({ \
@ -76,6 +83,7 @@ register char * stack_pointer __asm__ ("15");
" sar %%a0,0\n" \
: : "d" (descr) : "0" ); \
})
#endif
/* Access to data in the thread descriptor is easy. */
#define THREAD_GETMEM(descr, member) THREAD_SELF->member

View File

@ -45,19 +45,96 @@ typedef struct
# include <tcb-offsets.h>
#endif /* __ASSEMBLER__ */
#undef USE_TLS
/* TLS is always supported if the tools support it. There are no
kernel dependencies. To avoid bothering with the TLS support code
at all, use configure --without-tls.
#if USE_TLS
We need USE_TLS to be consistently defined, for ldsodefs.h
conditionals. */
#else
#ifdef HAVE_TLS_SUPPORT
#define NONTLS_INIT_TP \
/* Signal that TLS support is available. */
# define USE_TLS 1
# ifndef __ASSEMBLER__
/* Get system call information. */
# include <sysdep.h>
/* Get the thread descriptor definition. */
# include <linuxthreads/descr.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 (struct _pthread_descr_struct)
/* Alignment requirements for the TCB. */
# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
/* The TCB can have any size and the memory following the address the
thread pointer points to is unspecified. Allocate the TCB there. */
# define TLS_TCB_AT_TP 1
/* Install the dtv pointer. The pointer passed is to the element with
index -1 which contain the length. */
# define INSTALL_DTV(descr, dtvp) \
((tcbhead_t *) (descr))->dtv = (dtvp) + 1
/* Install new dtv for current thread. */
# define INSTALL_NEW_DTV(dtv) \
(((tcbhead_t *) __builtin_thread_pointer ())->dtv = (dtv))
/* Return dtv of given thread descriptor. */
# define GET_DTV(descr) \
(((tcbhead_t *) (descr))->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.
The value of this macro is null if successful, or an error string. */
# define TLS_INIT_TP(descr, secondcall) \
({ \
void *_descr = (descr); \
tcbhead_t *head = _descr; \
\
head->tcb = _descr; \
/* For now the thread descriptor is at the same address. */ \
head->self = _descr; \
\
__builtin_set_thread_pointer (_descr); \
0; \
})
/* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \
(((tcbhead_t *) __builtin_thread_pointer ())->dtv)
# endif /* __ASSEMBLER__ */
#else /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
# ifndef __ASSEMBLER__
/* Get the thread descriptor definition. */
# include <linuxthreads/descr.h>
# define NONTLS_INIT_TP \
do { \
static const tcbhead_t nontls_init_tp \
= { .multiple_threads = 0 }; \
INIT_THREAD_SELF (&nontls_init_tp, 0); \
} while (0)
#endif /* USE_TLS */
# endif /* __ASSEMBLER__ */
#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
#endif /* tls.h */

View File

@ -51,7 +51,7 @@ ENTRY(name) \
L(pseudo_check): \
lghi %r4,-4095; \
clgr %r2,%r4; \
jnl SYSCALL_ERROR_LABEL; \
jgnl SYSCALL_ERROR_LABEL; \
L(pseudo_end):
# ifdef IS_IN_libpthread

View File

@ -36,7 +36,7 @@ ENTRY (__vfork)
/* Check for error. */
lghi %r4,-4095
clgr %r2,%r4
jnl SYSCALL_ERROR_LABEL
jgnl SYSCALL_ERROR_LABEL
/* Normal return. */
br %r14

View File

@ -1,3 +1,10 @@
2003-01-28 Ulrich Drepper <drepper@redhat.com>
* sysdeps/unix/sysv/linux/i386/createthread.c: Define
PREPARE_CREATE and TLS_VALUE with x86-specific bits. All the rest
of the code is moved to ...
* sysdeps/pthread/createthread.c: ...here. New file.
2003-01-27 Ulrich Drepper <drepper@redhat.com>
* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S

View File

@ -0,0 +1,145 @@
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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 <sched.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <atomic.h>
#include <ldsodefs.h>
#include <tls.h>
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
/* Unless otherwise specified, the thread "register" is going to be
initialized with a pointer to the TCB. */
#ifndef TLS_VALUE
# define TLS_VALUE pd
#endif
static int
create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
{
#ifdef PREPARE_CREATE
PREPARE_CREATE;
#endif
assert (pd->header.data.tcb != NULL);
if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
{
/* The parent thread is supposed to report events. Check whether
the TD_CREATE event is needed, too. */
const int _idx = __td_eventword (TD_CREATE);
const uint32_t _mask = __td_eventmask (TD_CREATE);
if ((_mask & (__nptl_threads_events.event_bits[_idx]
| pd->eventbuf.eventmask.event_bits[_idx])) != 0)
{
/* We have to report the new thread. Make sure the thread
does not run far by forcing it to get a lock. We lock it
here too so that the new thread cannot continue until we
tell it to. */
lll_lock (pd->lock);
/* Create the thread. */
if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
CLONE_SETTLS | CLONE_PARENT_SETTID |
CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
/* Failed. */
return errno;
/* We now have for sure more than one thread. */
pd->header.data.multiple_threads = 1;
/* Now fill in the information about the new thread in
the newly created thread's data structure. We cannot let
the new thread do this since we don't know whether it was
already scheduled when we send the event. */
pd->eventbuf.eventnum = TD_CREATE;
pd->eventbuf.eventdata = pd;
/* Enqueue the descriptor. */
do
pd->nextevent = __nptl_last_event;
while (atomic_compare_and_exchange_acq (&__nptl_last_event, pd,
pd->nextevent) != 0);
/* Now call the function which signals the event. */
__nptl_create_event ();
/* And finally restart the new thread. */
lll_unlock (pd->lock);
return 0;
}
}
#ifdef NEED_DL_SYSINFO
assert (THREAD_GETMEM (THREAD_SELF, header.data.sysinfo)
== pd->header.data.sysinfo);
#endif
/* We rely heavily on various flags the CLONE function understands:
CLONE_VM, CLONE_FS, CLONE_FILES
These flags select semantics with shared address space and
file descriptors according to what POSIX requires.
CLONE_SIGNAL
This flag selects the POSIX signal semantics.
CLONE_SETTLS
The sixth parameter to CLONE determines the TLS area for the
new thread.
CLONE_PARENT_SETTID
The kernels writes the thread ID of the newly created thread
into the location pointed to by the fifth parameters to CLONE.
Note that it would be semantically equivalent to use
CLONE_CHILD_SETTID but it is be more expensive in the kernel.
CLONE_CHILD_CLEARTID
The kernels clears the thread ID of a thread that has called
sys_exit() - using the same parameter as CLONE_SETTID.
CLONE_DETACHED
No signal is generated if the thread exists and it is
automatically reaped.
The termination signal is chosen to be zero which means no signal
is sent. */
if (__clone (start_thread, STACK_VARIABLES_ARGS,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
/* Failed. */
return errno;
/* We now have for sure more than one thread. */
THREAD_SETMEM (THREAD_SELF, header.data.multiple_threads, 1);
return 0;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2002 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -17,141 +17,33 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <sched.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <atomic.h>
#include <ldsodefs.h>
#include <tls.h>
/* The "thread register" gets initialized from a segment descriptor.
Initialize such a descriptor first. */
#define PREPARE_CREATE \
union user_desc_init desc; \
\
/* Describe the thread-local storage segment. */ \
\
/* The 'entry_number' field. The first three bits of the segment \
register value select the GDT, ignore them. We get the index \
from the value of the %gs register in the current thread. */ \
desc.vals[0] = TLS_GET_GS () >> 3; \
/* The 'base_addr' field. Pointer to the TCB. */ \
desc.vals[1] = (unsigned long int) pd; \
/* The 'limit' field. We use 4GB which is 0xfffff pages. */ \
desc.vals[2] = 0xfffff; \
/* Collapsed value of the bitfield: \
.seg_32bit = 1 \
.contents = 0 \
.read_exec_only = 0 \
.limit_in_pages = 1 \
.seg_not_present = 0 \
.useable = 1 */ \
desc.vals[3] = 0x51
/* Value passed to 'clone' for initialization of the thread register. */
#define TLS_VALUE &desc.desc
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
static int
create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
{
union user_desc_init desc;
/* Describe the thread-local storage segment. */
/* The 'entry_number' field. The first three bits of the segment
register value select the GDT, ignore them. We get the index
from the value of the %gs register in the current thread. */
desc.vals[0] = TLS_GET_GS () >> 3;
/* The 'base_addr' field. Pointer to the TCB. */
desc.vals[1] = (unsigned long int) pd;
/* The 'limit' field. We use 4GB which is 0xfffff pages. */
desc.vals[2] = 0xfffff;
/* Collapsed value of the bitfield:
.seg_32bit = 1
.contents = 0
.read_exec_only = 0
.limit_in_pages = 1
.seg_not_present = 0
.useable = 1 */
desc.vals[3] = 0x51;
assert (pd->header.data.tcb != NULL);
if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
{
/* The parent thread is supposed to report events. Check whether
the TD_CREATE event is needed, too. */
const int _idx = __td_eventword (TD_CREATE);
const uint32_t _mask = __td_eventmask (TD_CREATE);
if ((_mask & (__nptl_threads_events.event_bits[_idx]
| pd->eventbuf.eventmask.event_bits[_idx])) != 0)
{
/* We have to report the new thread. Make sure the thread
does not run far by forcing it to get a lock. We lock it
here too so that the new thread cannot continue until we
tell it to. */
lll_lock (pd->lock);
/* Create the thread. */
if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
CLONE_SETTLS | CLONE_PARENT_SETTID |
CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
pd, &pd->tid, &desc.desc, &pd->tid) == -1)
/* Failed. */
return errno;
/* We now have for sure more than one thread. */
pd->header.data.multiple_threads = 1;
/* Now fill in the information about the new thread in
the newly created thread's data structure. We cannot let
the new thread do this since we don't know whether it was
already scheduled when we send the event. */
pd->eventbuf.eventnum = TD_CREATE;
pd->eventbuf.eventdata = pd;
/* Enqueue the descriptor. */
do
pd->nextevent = __nptl_last_event;
while (atomic_compare_and_exchange_acq (&__nptl_last_event, pd,
pd->nextevent) != 0);
/* Now call the function which signals the event. */
__nptl_create_event ();
/* And finally restart the new thread. */
lll_unlock (pd->lock);
return 0;
}
}
#ifdef NEED_DL_SYSINFO
assert (THREAD_GETMEM (THREAD_SELF, header.data.sysinfo)
== pd->header.data.sysinfo);
#endif
/* We rely heavily on various flags the CLONE function understands:
CLONE_VM, CLONE_FS, CLONE_FILES
These flags select semantics with shared address space and
file descriptors according to what POSIX requires.
CLONE_SIGNAL
This flag selects the POSIX signal semantics.
CLONE_SETTLS
The sixth parameter to CLONE determines the TLS area for the
new thread.
CLONE_PARENT_SETTID
The kernels writes the thread ID of the newly created thread
into the location pointed to by the fifth parameters to CLONE.
Note that it would be semantically equivalent to use
CLONE_CHILD_SETTID but it is be more expensive in the kernel.
CLONE_CHILD_CLEARTID
The kernels clears the thread ID of a thread that has called
sys_exit() - using the same parameter as CLONE_SETTID.
CLONE_DETACHED
No signal is generated if the thread exists and it is
automatically reaped.
The termination signal is chosen to be zero which means no signal
is sent. */
if (__clone (start_thread, STACK_VARIABLES_ARGS,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
CLONE_DETACHED | 0, pd, &pd->tid, &desc.desc, &pd->tid) == -1)
/* Failed. */
return errno;
/* We now have for sure more than one thread. */
THREAD_SETMEM (THREAD_SELF, header.data.multiple_threads, 1);
return 0;
}
/* Get the real implementation. */
#include <nptl/sysdeps/pthread/createthread.c>

6
sysdeps/s390/Versions Normal file
View File

@ -0,0 +1,6 @@
ld {
GLIBC_2.3 {
# runtime interface to TLS
__tls_get_offset;
}
}

73
sysdeps/s390/dl-tls.h Normal file
View File

@ -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

37
sysdeps/s390/libc-tls.c Normal file
View File

@ -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

View File

@ -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)

52
sysdeps/s390/s390-32/elf/configure vendored Normal file
View File

@ -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

View File

@ -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)

View File

@ -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))
{

52
sysdeps/s390/s390-64/elf/configure vendored Normal file
View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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: