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.
This commit is contained in:
parent
772e3426a7
commit
e6ebd2e4db
34
ChangeLog
34
ChangeLog
|
@ -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
103
elf/elf.h
|
@ -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
|
||||
|
|
190
elf/tls-macros.h
190
elf/tls-macros.h
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
ld {
|
||||
GLIBC_2.3 {
|
||||
# runtime interface to TLS
|
||||
__tls_get_offset;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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)
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
Loading…
Reference in New Issue