diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-01-12 10:11:16 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-01-12 10:11:16 +0000 |
commit | aff4519d380c863ed0f259a1387cb473d3f3bad2 (patch) | |
tree | 825718efb1a8a4598d6de379d70a05ee034ab4f2 /sysdeps | |
parent | 26a676d0aae53e2e770581c133356d8c0e39268c (diff) | |
download | glibc-aff4519d380c863ed0f259a1387cb473d3f3bad2.tar glibc-aff4519d380c863ed0f259a1387cb473d3f3bad2.tar.gz glibc-aff4519d380c863ed0f259a1387cb473d3f3bad2.tar.bz2 glibc-aff4519d380c863ed0f259a1387cb473d3f3bad2.zip |
Update.
2003-01-11 Jim Meyering <jim@meyering.net>
* io/ftw.c [HAVE_CONFIG_H]: Include <config.h>.
[HAVE_SYS_PARAM_H || _LIBC]: Guard inclusion of <sys/param.h>.
Include <sys/stat.h>, not <include/sys/stat.h>, if !_LIBC.
[!_LIBC] (__chdir, __closedir, __fchdir, __getcwd, __opendir): Define.
[!_LIBC] (__readdir64, __tdestroy, __tfind, __tsearch): Define.
[!_LIBC] (internal_function, dirent64, MAX): Define.
(__set_errno): Define if not already defined.
(open_dir_stream): When FTW_CHDIR is enabled, invoke opendir on
the basename, not the entire file name.
(process_entry): When FTW_CHDIR is enabled, invoke XSTAT or LXSTAT on
the basename, not the entire file name.
2003-01-12 Ulrich Drepper <drepper@redhat.com>
* string/tester.c (test_strcpy): Disable last added strcpy until
it is fixed.
2003-01-11 Philip Blundell <philb@gnu.org>
* sysdeps/unix/sysv/linux/arm/socket.S: Add cancellation support.
2003-01-11 Andreas Schwab <schwab@suse.de>
* Makerules: Add vpath for %.dynsym and %.so so that the
implicit rule chaining for check-abi works.
2003-01-11 Kaz Kojima <kkojima@rr.iij4u.or.jp>
* sysdeps/unix/sysv/linux/sh/sysdep.h (SYSCALL_ERROR_HANDLER):
Add non-PIC case.
2003-01-11 Jakub Jelinek <jakub@redhat.com>
* elf/tls-macros.h [__ia64__] (__TLS_CALL_CLOBBERS): Define.
[__ia64__] (TLS_LE, TLS_IE): Fix typos. Add ;; at start of asm if
gp is used early.
[__ia64__] (TLS_LD, TLS_GD): Likewise. Use __TLS_CALL_CLOBBERS.
* elf/Makefile ($(objpfx)tst-tlsmod5.so, $(objpfx)tst-tlsmod6.so):
Ensure libc.so in DT_NEEDED.
* sysdeps/alpha/dl-machine.h (elf_machine_rela): Move
CHECK_STATIC_TLS before l_tls_offset use.
* sysdeps/i386/dl-machine.h (elf_machine_rel, elf_machine_rela):
Likewise.
* sysdeps/sh/dl-machine.h (elf_machine_rela): Likewise.
* sysdeps/generic/dl-tls.c (_dl_allocate_tls_storage) [TLS_DTV_AT_TP]:
Allocate TLS_PRE_TCB_SIZE bytes below result.
(_dl_deallocate_tls) [TLS_DTV_AT_TP]: Adjust before freeing.
* sysdeps/generic/libc-tls.c (__libc_setup_tls): If
TLS_INIT_TP_EXPENSIVE is not defined, allocate even if no PT_TLS
segment has been found. If TLS_DTV_AT_TP, allocate TLS_PRE_TCB_SIZE
bytes below result and add tcb_offset to memsz.
* sysdeps/ia64/dl-tls.h (__tls_get_addr): New prototype.
* sysdeps/ia64/dl-machine.h: Include tls.h.
(elf_machine_type_class): Return ELF_RTYPE_CLASS_PLT for TLS relocs
too.
(elf_machine_rela): Assume if sym_map != NULL sym is non-NULL too.
Handle R_IA64_DTPMOD*, R_IA64_DTPREL* and R_IA64_TPREL* relocations.
* sysdeps/ia64/libc-tls.c: New file.
2003-01-10 Steven Munroe <sjmunroe@us.ibm.com>
* sysdeps/powerpc/powerpc64/sysdep.h (PSEUDO_RET): Add branch hit.
* sysdeps/unix/sysv/linux/powerpc/bits/stat.h (STAT_VER_LINUX):
Fix type. Move definition out of #if.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S: Add cancellation
support.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list: Remove
ftruncate64, pread64, pwrite64, truncate64 entries.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
(INLINE_SYSCALL): New version that supports function call like
syscalls. Add __builtin_expect.
(LOADARGS_n): Add argument size safety checks.
(INTERNAL_SYSCALL): New Macro.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c: New file.
* sysdeps/unix/sysv/linux/powerpc/sys/procfs.h [__PPC_ELF_H]: Avoid
redefinition of elf_fpreg_t and elf_fpregset_t.
2003-01-12 Ulrich Drepper <drepper@redhat.com>
* elf/dl-close.c (_dl_close): Add several asserts. Correct and
simplify test for unloading. If loader of a DSO is unloaded do not
use its scope anymore. Fall back to own scope and adjust opencounts.
Fix several comments.
* elf/dl-deps.c (_dl_map_object_deps): Always allocate memory for
the l_searchlist, not only for l_initfini.
* elf/dl-lookup.c (add_dependencies): Avoid creating relocation
dependencies if objects cannot be removed. Remove object with the
definition as not unloadable if necessary.
* elf/reldep6.c: Create relocation dependency before closing the first
module.
2003-01-10 Guido Günther <agx@sigxcpu.org>
* elf/Makefile: Add rules to build and run reldep9 test.
* elf/reldep9.c: New file.
* elf/reldep9mod1.c: New file.
* elf/reldep9mod2.c: New file.
* elf/reldep9mod3.c: New file.
2003-01-09 Jakub Jelinek <jakub@redhat.com>
* elf/Makefile: Add rules to build and run nodelete2 test.
* elf/nodelete2.c: New file.
* elf/nodel2mod1.c: New file.
* elf/nodel2mod2.c: New file.
* elf/nodel2mod3.c: New file.
2003-01-09 Jakub Jelinek <jakub@redhat.com>
Diffstat (limited to 'sysdeps')
22 files changed, 756 insertions, 114 deletions
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h index 711bf10fdd..3a182ca99f 100644 --- a/sysdeps/alpha/dl-machine.h +++ b/sysdeps/alpha/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. Alpha version. - Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1996-2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson <rth@tamu.edu>. @@ -610,8 +610,8 @@ elf_machine_rela (struct link_map *map, #else if (sym_map) { - *reloc_addr = sym_value - sym_map->l_tls_offset; CHECK_STATIC_TLS (map, sym_map); + *reloc_addr = sym_value - sym_map->l_tls_offset; } #endif } diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c index 6791d765ee..0afe379ae6 100644 --- a/sysdeps/generic/dl-tls.c +++ b/sysdeps/generic/dl-tls.c @@ -282,9 +282,18 @@ internal_function _dl_allocate_tls_storage (void) { void *result; + size_t size = GL(dl_tls_static_size); + +# if TLS_DTV_AT_TP + /* Memory layout is: + [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ] + ^ This should be returned. */ + size += (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); +# endif /* Allocate a correctly aligned chunk of memory. */ - result = __libc_memalign (GL(dl_tls_static_align), GL(dl_tls_static_size)); + result = __libc_memalign (GL(dl_tls_static_align), size); if (__builtin_expect (result != NULL, 0)) { /* Allocate the DTV. */ @@ -292,12 +301,20 @@ _dl_allocate_tls_storage (void) # if TLS_TCB_AT_TP /* The TCB follows the TLS blocks. */ - result = (char *) result + GL(dl_tls_static_size) - TLS_TCB_SIZE; -# endif + result = (char *) result + size - TLS_TCB_SIZE; /* Clear the TCB data structure. We can't ask the caller (i.e. libpthread) to do it, because we will initialize the DTV et al. */ memset (result, 0, TLS_TCB_SIZE); +# elif TLS_DTV_AT_TP + result = (char *) result + size - GL(dl_tls_static_size); + + /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it. + We can't ask the caller (i.e. libpthread) to do it, because we will + initialize the DTV et al. */ + memset ((char *) result - TLS_PRE_TCB_SIZE, 0, + TLS_PRE_TCB_SIZE + TLS_TCB_SIZE); +# endif result = allocate_dtv (result); if (result == NULL) @@ -405,6 +422,10 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb) # if TLS_TCB_AT_TP /* The TCB follows the TLS blocks. Back up to free the whole block. */ tcb -= GL(dl_tls_static_size) - TLS_TCB_SIZE; +# elif TLS_DTV_AT_TP + /* Back up the TLS_PRE_TCB_SIZE bytes. */ + tcb -= (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); # endif free (tcb); } diff --git a/sysdeps/generic/libc-tls.c b/sysdeps/generic/libc-tls.c index 1461bf8543..b5ecc36436 100644 --- a/sysdeps/generic/libc-tls.c +++ b/sysdeps/generic/libc-tls.c @@ -1,5 +1,5 @@ /* Initialization code for TLS in statically linked application. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -134,15 +134,16 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) break; } +#ifdef TLS_INIT_TP_EXPENSIVE if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE) { /* We do not need a TLS block and no thread descriptor. */ -#ifdef NONTLS_INIT_TP +# ifdef NONTLS_INIT_TP NONTLS_INIT_TP; -#endif +# endif return; } - +#endif /* We have to set up the TCB block which also (possibly) contains 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. @@ -157,8 +158,10 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign); tlsblock = __sbrk (tcb_offset + tcbsize + max_align); # elif TLS_DTV_AT_TP - tlsblock = __sbrk (roundup (tcbsize, align) + memsz + max_align - + GL(dl_tls_static_size)); + tcb_offset = roundup (tcbsize, align ?: 1); + tlsblock = __sbrk (tcb_offset + memsz + max_align + + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); + tlsblock += TLS_PRE_TCB_SIZE; # else /* In case a model with a different layout for the TCB and DTV is defined add another #elif here and in the following #ifs. */ @@ -179,7 +182,6 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) - roundup (memsz, align ?: 1)); static_map.l_tls_offset = roundup (memsz, align ?: 1); # elif TLS_DTV_AT_TP - tcb_offset = roundup (tcbsize, align); static_dtv[2].pointer = (char *) tlsblock + tcb_offset; static_map.l_tls_offset = tcb_offset; # else @@ -222,6 +224,8 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) # if TLS_TCB_AT_TP memsz += tcbsize; +# elif TLS_DTV_AT_TP + memsz += tcb_offset; # endif init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align)); diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index add6f8e01b..fa5076e3e5 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. i386 version. - Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc. + Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -445,8 +445,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, block we subtract the offset from that of the TLS block. */ if (sym != NULL) { - *reloc_addr += sym_map->l_tls_offset - sym->st_value; CHECK_STATIC_TLS (map, sym_map); + *reloc_addr += sym_map->l_tls_offset - sym->st_value; } # endif break; @@ -460,8 +460,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, thread pointer. */ if (sym != NULL) { - *reloc_addr += sym->st_value - sym_map->l_tls_offset; CHECK_STATIC_TLS (map, sym_map); + *reloc_addr += sym->st_value - sym_map->l_tls_offset; } # endif break; @@ -555,20 +555,20 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, It is a positive value which will be subtracted from the thread pointer. To get the variable position in the TLS block we subtract the offset from that of the TLS block. */ + CHECK_STATIC_TLS (map, sym_map); *reloc_addr = (sym == NULL ? 0 : sym_map->l_tls_offset - sym->st_value) + reloc->r_addend; - CHECK_STATIC_TLS (map, sym_map); break; case R_386_TLS_TPOFF: /* The offset is negative, forward from the thread pointer. */ /* We know the offset of object the symbol is contained in. It is a negative value which will be added to the thread pointer. */ + CHECK_STATIC_TLS (map, sym_map); *reloc_addr = (sym == NULL ? 0 : sym->st_value - sym_map->l_tls_offset) + reloc->r_addend; - CHECK_STATIC_TLS (map, sym_map); break; # endif /* use TLS */ # ifndef RESOLVE_CONFLICT_FIND_MAP diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h index 16a1ff3000..f5eeef67db 100644 --- a/sysdeps/ia64/dl-machine.h +++ b/sysdeps/ia64/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. IA-64 version. - Copyright (C) 1995,1996,1997,2000,2001,2002 Free Software Foundation, Inc. + Copyright (C) 1995-1997, 2000-2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -26,7 +26,7 @@ #include <string.h> #include <link.h> #include <errno.h> - +#include <tls.h> /* Translate a processor specific dynamic tag to the index in l_info array. */ @@ -448,14 +448,22 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) #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, which we don't use. */ -/* ??? Ignore IPLTMSB for now. */ +/* ??? Ignore *MSB for now. */ +#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) +#define elf_machine_type_class(type) \ + (((type) == R_IA64_IPLTLSB || (type) == R_IA64_DTPMOD64LSB \ + || (type) == R_IA64_DTPREL64LSB || (type) == R_IA64_TPREL64LSB) \ + * ELF_RTYPE_CLASS_PLT) +#else #define elf_machine_type_class(type) \ (((type) == R_IA64_IPLTLSB) * ELF_RTYPE_CLASS_PLT) +#endif /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ #define ELF_MACHINE_JMP_SLOT R_IA64_IPLTLSB @@ -557,8 +565,7 @@ elf_machine_rela (struct link_map *map, /* RESOLVE_MAP() will return NULL if it fail to locate the symbol. */ if ((sym_map = RESOLVE_MAP (&sym, version, r_type))) { - value = sym ? sym_map->l_addr + sym->st_value : 0; - value += reloc->r_addend; + value = sym_map->l_addr + sym->st_value + reloc->r_addend; if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DIR64LSB)) ;/* No adjustment. */ @@ -571,6 +578,26 @@ elf_machine_rela (struct link_map *map, value = __ia64_make_fptr (sym_map, sym, value); else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_PCREL64LSB)) value -= (Elf64_Addr) reloc_addr & -16; +#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || defined USE___THREAD) + else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DTPMOD64LSB)) +# ifdef RTLD_BOOTSTRAP + /* During startup the dynamic linker is always index 1. */ + value = 1; +# else + /* Get the information from the link map returned by the + resolv function. */ + value = sym_map->l_tls_modid; + else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DTPREL64LSB)) + value -= sym_map->l_addr; +# endif + else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_TPREL64LSB)) + { +# ifndef RTLD_BOOTSTRAP + CHECK_STATIC_TLS (map, sym_map); +# endif + value += sym_map->l_tls_offset - sym_map->l_addr; + } +#endif else assert (! "unexpected dynamic reloc type"); } diff --git a/sysdeps/ia64/dl-tls.h b/sysdeps/ia64/dl-tls.h index 738c820a44..26f3d2adf1 100644 --- a/sysdeps/ia64/dl-tls.h +++ b/sysdeps/ia64/dl-tls.h @@ -1,5 +1,5 @@ /* Thread-local storage handling in the ELF dynamic linker. IA-64 version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -26,3 +26,5 @@ /* We have no tls_index type. */ #define DONT_USE_TLS_INDEX 1 + +extern void *__tls_get_addr (size_t m, size_t offset); diff --git a/sysdeps/ia64/libc-tls.c b/sysdeps/ia64/libc-tls.c new file mode 100644 index 0000000000..f1df4cd12e --- /dev/null +++ b/sysdeps/ia64/libc-tls.c @@ -0,0 +1,37 @@ +/* Thread-local storage handling in the ELF dynamic linker. IA-64 version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdeps/generic/libc-tls.c> + +#if USE_TLS + +/* On IA-64, as it lacks linker optimizations, __tls_get_addr can be + called even in statically linked binaries. + In this case module must be always 1 and PT_TLS segment + exist in the binary, otherwise it would not link. */ + +void * +__tls_get_addr (size_t m, size_t offset) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer + offset; +} + +#endif + diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h index c25df403b6..9b895df3f0 100644 --- a/sysdeps/powerpc/powerpc64/sysdep.h +++ b/sysdeps/powerpc/powerpc64/sysdep.h @@ -216,7 +216,7 @@ LT_LABELSUFFIX(name,_name_end): ; \ DO_CALL (SYS_ify (syscall_name)); #define PSEUDO_RET \ - bnslr; \ + bnslr+; \ b JUMPTARGET(__syscall_error) #define ret PSEUDO_RET diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h index c6d094d26a..6607d9b2f8 100644 --- a/sysdeps/sh/dl-machine.h +++ b/sysdeps/sh/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. SH version. - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -579,10 +579,10 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, It is a positive value which will be added to the thread pointer. To get the variable position in the TLS block we add the offset from that of the TLS block. */ + CHECK_STATIC_TLS (map, sym_map); *reloc_addr = ((sym == NULL ? 0 : sym_map->l_tls_offset + sym->st_value) + reloc->r_addend); - CHECK_STATIC_TLS (map, sym_map); # endif break; #endif /* use TLS */ diff --git a/sysdeps/unix/sysv/linux/arm/socket.S b/sysdeps/unix/sysv/linux/arm/socket.S index f4ccc5465d..3e93ceb6d2 100644 --- a/sysdeps/unix/sysv/linux/arm/socket.S +++ b/sysdeps/unix/sysv/linux/arm/socket.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1998, 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 @@ -16,7 +16,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include <sysdep.h> +#include <sysdep-cancel.h> #include <socketcall.h> #define P(a, b) P2(a, b) @@ -53,6 +53,10 @@ #define NARGS 3 /* If we were called with no wrapper, this is really socket() */ #endif +#if defined NEED_CANCELLATION && defined CENABLE + PSEUDO_PROLOGUE +#endif + .globl __socket ENTRY (__socket) /* This code previously moved sp into ip and stored the args using @@ -68,6 +72,15 @@ ENTRY (__socket) /* Push args onto the stack. */ P(PUSHARGS_,NARGS) +#if defined NEED_CANCELLATION && defined CENABLE +#ifdef PIC + SINGLE_THREAD_P_PIC(r3) +#else + SINGLE_THREAD_P +#endif + bne 1f +#endif + /* Do the system call trap. */ mov a1, $P(SOCKOP_,socket) mov a2, sp @@ -81,6 +94,30 @@ ENTRY (__socket) RETINSTR(movcc, pc, r14) b PLTJMP(SYSCALL_ERROR) +#if defined NEED_CANCELLATION && defined CENABLE +1: + str lr, [sp, #-4]! + CENABLE + mov ip, r0 + + mov r0, #P(SOCKOP_,socket) + add r1, sp, #4 + swi SYS_ify(socketcall) + + str r0, [sp, #-4]! + mov r0, ip + CDISABLE + ldr r0, [sp], #4 + ldr lr, [sp], #4 + + P(POPARGS_,NARGS) + + /* r0 is < 0 if there was an error. */ + cmn r0, $124 + RETINSTR(movcc, pc, r14) + b PLTJMP(SYSCALL_ERROR) +#endif + PSEUDO_END (__socket) weak_alias (__socket, socket) diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/stat.h b/sysdeps/unix/sysv/linux/powerpc/bits/stat.h index 3cff5c8d81..cf3dd1c293 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/stat.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/stat.h @@ -27,11 +27,11 @@ #define _STAT_VER_LINUX_OLD 1 #define _STAT_VER_KERNEL 1 #define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 #if __WORDSIZE == 32 -# define _STAT_VER_LINUX 3 -# define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ +# define _STAT_VER _STAT_VER_LINUX #else -# define _STAT_VER _STAT_VER_KERNEL /* The one defined below. */ +# define _STAT_VER _STAT_VER_KERNEL #endif /* Versions of the `xmknod' interface. */ diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c new file mode 100644 index 0000000000..f733001abe --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include "kernel-features.h" + +#ifdef __NR_ftruncate64 +#ifndef __ASSUME_TRUNCATE64_SYSCALL +/* The variable is shared between all wrappers around *truncate64 calls. */ +extern int have_no_truncate64; +#endif + + +/* Truncate the file FD refers to to LENGTH bytes. */ +int +__ftruncate64 (fd, length) + int fd; + off64_t length; +{ +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (! have_no_truncate64) +#endif + { +#ifndef __ASSUME_TRUNCATE64_SYSCALL + int saved_errno = errno; +#endif + int result = INLINE_SYSCALL (ftruncate64, 2, fd, length); + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (result != -1 || errno != ENOSYS) +#endif + return result; + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + __set_errno (saved_errno); + have_no_truncate64 = 1; +#endif + } + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if ((off_t) length != length) + { + __set_errno (EINVAL); + return -1; + } + return __ftruncate (fd, (off_t) length); +#endif +} +weak_alias (__ftruncate64, ftruncate64) + +#else +/* Use the generic implementation. */ +# include <sysdeps/generic/ftruncate64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c new file mode 100644 index 0000000000..d5b77e0b57 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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 <assert.h> +#include <errno.h> +#include <unistd.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 + +# if __ASSUME_PREAD_SYSCALL == 0 +static ssize_t __emulate_pread (int fd, void *buf, size_t count, + off_t offset) internal_function; +# endif + + +ssize_t +__libc_pread (fd, buf, count, offset) + int fd; + void *buf; + size_t count; + off_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +strong_alias (__libc_pread, __pread) +weak_alias (__libc_pread, pread) + +# define __libc_pread(fd, buf, count, offset) \ + static internal_function __emulate_pread (fd, buf, count, offset) +#endif + +#if __ASSUME_PREAD_SYSCALL == 0 +# include <sysdeps/posix/pread.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c new file mode 100644 index 0000000000..9bbe389420 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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 <errno.h> +#include <unistd.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 + +# if __ASSUME_PREAD_SYSCALL == 0 +static ssize_t __emulate_pread64 (int fd, void *buf, size_t count, + off64_t offset) internal_function; +# endif + + +ssize_t +__libc_pread64 (fd, buf, count, offset) + int fd; + void *buf; + size_t count; + off64_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread64 (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread64 (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +weak_alias (__libc_pread64, __pread64) +weak_alias (__libc_pread64, pread64) + +# define __libc_pread64(fd, buf, count, offset) \ + static internal_function __emulate_pread64 (fd, buf, count, offset) +#endif + +# if __ASSUME_PREAD_SYSCALL == 0 +# include <sysdeps/posix/pread64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c new file mode 100644 index 0000000000..96b72e18a5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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 <assert.h> +#include <errno.h> +#include <unistd.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 + +# if __ASSUME_PWRITE_SYSCALL == 0 +static ssize_t __emulate_pwrite (int fd, const void *buf, size_t count, + off_t offset) internal_function; +# endif + + +ssize_t +__libc_pwrite (fd, buf, count, offset) + int fd; + const void *buf; + size_t count; + off_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +strong_alias (__libc_pwrite, __pwrite) +weak_alias (__libc_pwrite, pwrite) + +# define __libc_pwrite(fd, buf, count, offset) \ + static internal_function __emulate_pwrite (fd, buf, count, offset) +#endif + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include <sysdeps/posix/pwrite.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c new file mode 100644 index 0000000000..9e68acdf08 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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 <errno.h> +#include <unistd.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 + +# if __ASSUME_PWRITE_SYSCALL == 0 +static ssize_t __emulate_pwrite64 (int fd, const void *buf, size_t count, + off64_t offset) internal_function; +# endif + + +ssize_t +__libc_pwrite64 (fd, buf, count, offset) + int fd; + const void *buf; + size_t count; + off64_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite64 (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite64 (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +weak_alias (__libc_pwrite64, __pwrite64) +libc_hidden_weak (__pwrite64) +weak_alias (__libc_pwrite64, pwrite64) + +# define __libc_pwrite64(fd, buf, count, offset) \ + static internal_function __emulate_pwrite64 (fd, buf, count, offset) +#endif + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include <sysdeps/posix/pwrite64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S index 08696c3cf3..a4e27c3611 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1999, 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 @@ -39,7 +39,7 @@ #define NARGS 3 #endif -#define stackblock 48 /* offset to parm save area */ +#define stackblock 80 /* offset to socket parm area. */ #ifndef socket /* If this is just socket.S leave it alone! */ @@ -51,7 +51,7 @@ .text ENTRY(__socket) - stdu r1,-112(r1) + stdu r1,-144(r1) #if NARGS >= 1 std r3,stackblock(r1) #endif @@ -79,11 +79,40 @@ ENTRY(__socket) #if NARGS >= 9 #error too many arguments! #endif - li r3,P(SOCKOP_,socket) + +#if defined NEED_CANCELLATION && defined CENABLE + SINGLE_THREAD_P + bne- .Lsocket_cancel +#endif + + li r3,P(SOCKOP_,socket) + addi r4,r1,stackblock + DO_CALL(SYS_ify(socketcall)) + addi r1,r1,144 + PSEUDO_RET + +#if defined NEED_CANCELLATION && defined CENABLE +.Lsocket_cancel: + mflr r9 + std r9,144+16(r1) + CENABLE + std r3,72(r1) + li r3,P(SOCKOP_,socket) addi r4,r1,stackblock DO_CALL(SYS_ify(socketcall)) - addi r1,r1,112 + mfcr r0 + std r3,64(r1) + std r0,8(r1) + ld r3,72(r1) + CDISABLE + ld r4,144+16(r1) + ld r0,8(r1) + ld r3,64(r1) + mtlr r4 + mtcr r0 + addi r1,r1,144 PSEUDO_RET +#endif PSEUDO_END (__socket) weak_alias (__socket, socket) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list index d8303a60f6..5266c4f59f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list @@ -16,7 +16,6 @@ rt_sigtimedwait - rt_sigtimedwait i:pppi __syscall_rt_sigtimedwait s_fcntl fcntl fcntl i:iiF __syscall_fcntl s_fcntl64 fcntl64 fcntl64 i:iiF __syscall_fcntl64 s_fstat64 fxstat64 fstat64 i:ip __syscall_fstat64 -s_ftruncate64 ftruncate64 ftruncate64 i:iii __syscall_ftruncate64 s_getcwd getcwd getcwd i:pi __syscall_getcwd s_getdents getdents getdents i:ipi __syscall_getdents s_getdents64 getdents getdents64 i:ipi __syscall_getdents64 @@ -26,10 +25,8 @@ s_getrlimit getrlimit getrlimit i:ip __syscall_getrlimit s_lstat64 lxstat64 lstat64 i:sp __syscall_lstat64 s_mmap2 mmap64 mmap2 b:aniiii __syscall_mmap2 s_poll poll poll i:pii __syscall_poll -s_pread64 pread64 pread i:ibnii __syscall_pread s_ptrace ptrace ptrace i:iipp __syscall_ptrace s_putpmsg putpmsg putpmsg i:ippii __syscall_putpmsg -s_pwrite64 pwrite64 pwrite i:ibnii __syscall_pwrite s_reboot reboot reboot i:iii __syscall_reboot s_setrlimit setrlimit setrlimit i:ip __syscall_setrlimit s_sigaction sigaction sigaction i:ipp __syscall_sigaction @@ -38,7 +35,6 @@ s_sigprocmask sigprocmask sigprocmask i:ipp __syscall_sigprocmask s_sigsuspend sigsuspend sigsuspend i:iii __syscall_sigsuspend s_stat64 xstat64 stat64 i:sp __syscall_stat64 s_sysctl sysctl _sysctl i:p __syscall__sysctl -s_truncate64 truncate64 truncate64 i:sii __syscall_truncate64 s_ugetrlimit getrlimit ugetrlimit i:ip __syscall_ugetrlimit s_ustat ustat ustat i:ip __syscall_ustat s_vfork vfork vfork i: __syscall_vfork diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h index d56ff877ac..d37be2ef4f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h @@ -69,65 +69,7 @@ #endif /* __ASSEMBLER__ */ #undef INLINE_SYSCALL -#if 1 -#define INLINE_SYSCALL(name, nr, args...) \ - ({ \ - DECLARGS_##nr; \ - long ret, err; \ - LOADARGS_##nr(name, args); \ - __asm __volatile ("sc\n\t" \ - "mfcr %1\n\t" \ - : "=r" (r3), "=r" (err) \ - : ASM_INPUT_##nr \ - : "cc", "memory"); \ - ret = r3; \ - if (err & 1 << 28) \ - { \ - __set_errno (ret); \ - ret = -1L; \ - } \ - ret; \ - }) - -#define DECLARGS_0 register long r0 __asm__ ("r0"); \ - register long r3 __asm__ ("r3") -#define DECLARGS_1 DECLARGS_0 -#define DECLARGS_2 DECLARGS_1; register long r4 __asm__ ("r4") -#define DECLARGS_3 DECLARGS_2; register long r5 __asm__ ("r5") -#define DECLARGS_4 DECLARGS_3; register long r6 __asm__ ("r6") -#define DECLARGS_5 DECLARGS_4; register long r7 __asm__ ("r7") -#define DECLARGS_6 DECLARGS_5; register long r8 __asm__ ("r8") - -#define LOADARGS_0(name) \ - r0 = __NR_##name -#define LOADARGS_1(name, arg1) \ - LOADARGS_0(name); \ - r3 = (long) (arg1) -#define LOADARGS_2(name, arg1, arg2) \ - LOADARGS_1(name, arg1); \ - r4 = (long) (arg2) -#define LOADARGS_3(name, arg1, arg2, arg3) \ - LOADARGS_2(name, arg1, arg2); \ - r5 = (long) (arg3) -#define LOADARGS_4(name, arg1, arg2, arg3, arg4) \ - LOADARGS_3(name, arg1, arg2, arg3); \ - r6 = (long) (arg4) -#define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ - LOADARGS_4(name, arg1, arg2, arg3, arg4); \ - r7 = (long) (arg5) -#define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ - LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ - r8 = (long) (arg6) - -#define ASM_INPUT_0 "r" (r0) -#define ASM_INPUT_1 ASM_INPUT_0, "0" (r3) -#define ASM_INPUT_2 ASM_INPUT_1, "r" (r4) -#define ASM_INPUT_3 ASM_INPUT_2, "r" (r5) -#define ASM_INPUT_4 ASM_INPUT_3, "r" (r6) -#define ASM_INPUT_5 ASM_INPUT_4, "r" (r7) -#define ASM_INPUT_6 ASM_INPUT_5, "r" (r8) -#else /* This version is for kernels that implement system calls that behave like function calls as far as register saving. */ #define INLINE_SYSCALL(name, nr, args...) \ @@ -149,40 +91,89 @@ : ASM_INPUT_##nr \ : "r9", "r10", "r11", "r12", \ "fr0", "fr1", "fr2", "fr3", \ - "fr4", "fr5", "fr6", "fr7", \ - "fr8", "fr9", "fr10", "fr11", \ - "fr12", "fr13", \ - "ctr", "lr", \ - "cr0", "cr1", "cr5", "cr6", "cr7", \ - "memory"); \ + "fr4", "fr5", "fr6", "fr7", \ + "fr8", "fr9", "fr10", "fr11", \ + "fr12", "fr13", \ + "ctr", "lr", \ + "cr0", "cr1", "cr5", "cr6", "cr7", \ + "memory"); \ ret = r3; \ - if (err & 1 << 28) \ + if (__builtin_expect ((err & (1 << 28)), 0)) \ { \ - __set_errno (ret); \ - ret = -1L; \ + __set_errno (ret); \ + ret = -1L; \ } \ ret; \ }) -#define LOADARGS_0(name) \ +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. This returns just what the kernel + gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set) + the negation of the return value in the kernel gets reverted. */ + +# undef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL(name, nr, args...) \ + ({ \ + register long r0 __asm__ ("r0"); \ + register long r3 __asm__ ("r3"); \ + register long r4 __asm__ ("r4"); \ + register long r5 __asm__ ("r5"); \ + register long r6 __asm__ ("r6"); \ + register long r7 __asm__ ("r7"); \ + register long r8 __asm__ ("r8"); \ + LOADARGS_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc\n\t" \ + "bns+ 0f\n\t" \ + "neg %1,%1\n" \ + "0:" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), \ + "=&r" (r6), "=&r" (r7), "=&r" (r8) \ + : ASM_INPUT_##nr \ + : "r9", "r10", "r11", "r12", \ + "cr0", "ctr", "memory"); \ + (int) r3; \ + }) + +# undef INTERNAL_SYSCALL_ERROR_P +# define INTERNAL_SYSCALL_ERROR_P(val) ((unsigned long) (val) >= 0xfffffffffffff001u) + +# undef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val) (-(val)) + +#define LOADARGS_0(name, dummy) \ r0 = __NR_##name #define LOADARGS_1(name, arg1) \ - LOADARGS_0(name); \ + LOADARGS_0(name, 0); \ + extern void __illegally_sized_syscall_##name##_arg1 (void); \ + if (sizeof (arg1) > 8) __illegally_sized_syscall_##name##_arg1 (); \ r3 = (long) (arg1) #define LOADARGS_2(name, arg1, arg2) \ LOADARGS_1(name, arg1); \ + extern void __illegally_sized_syscall_##name##_arg2 (void); \ + if (sizeof (arg2) > 8) __illegally_sized_syscall_##name##_arg2 (); \ r4 = (long) (arg2) #define LOADARGS_3(name, arg1, arg2, arg3) \ LOADARGS_2(name, arg1, arg2); \ + extern void __illegally_sized_syscall_##name##_arg3 (void); \ + if (sizeof (arg3) > 8) __illegally_sized_syscall_##name##_arg3 (); \ r5 = (long) (arg3) #define LOADARGS_4(name, arg1, arg2, arg3, arg4) \ LOADARGS_3(name, arg1, arg2, arg3); \ + extern void __illegally_sized_syscall_##name##_arg4 (void); \ + if (sizeof (arg4) > 8) __illegally_sized_syscall_##name##_arg4 (); \ r6 = (long) (arg4) #define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ LOADARGS_4(name, arg1, arg2, arg3, arg4); \ + extern void __illegally_sized_syscall_##name##_arg5 (void); \ + if (sizeof (arg5) > 8) __illegally_sized_syscall_##name##_arg5 (); \ r7 = (long) (arg5) #define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ + extern void __illegally_sized_syscall_##name##_arg6 (void); \ + if (sizeof (arg6) > 8) __illegally_sized_syscall_##name##_arg6 (); \ r8 = (long) (arg6) #define ASM_INPUT_0 "0" (r0) @@ -193,6 +184,4 @@ #define ASM_INPUT_5 ASM_INPUT_4, "5" (r7) #define ASM_INPUT_6 ASM_INPUT_5, "6" (r8) -#endif - #endif /* linux/powerpc/powerpc64/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c new file mode 100644 index 0000000000..cbf0669082 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#ifdef __NR_truncate64 +#ifndef __ASSUME_TRUNCATE64_SYSCALL +/* The variable is shared between all wrappers around *truncate64 calls. */ +int have_no_truncate64; +#endif + + +/* Truncate the file FD refers to to LENGTH bytes. */ +int +truncate64 (path, length) + const char *path; + off64_t length; +{ +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (! have_no_truncate64) +#endif + { +#ifndef __ASSUME_TRUNCATE64_SYSCALL + int saved_errno = errno; +#endif + int result = INLINE_SYSCALL (truncate64, 2, CHECK_STRING (path), + length); + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (result != -1 || errno != ENOSYS) +#endif + return result; + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + __set_errno (saved_errno); + have_no_truncate64 = 1; +#endif + } + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if ((off_t) length != length) + { + __set_errno (EINVAL); + return -1; + } + return truncate (path, (off_t) length); +#endif +} + +#else +/* Use the generic implementation. */ +# include <sysdeps/generic/truncate64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h b/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h index e42f848bc5..1322971da4 100644 --- a/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h +++ b/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h @@ -32,6 +32,10 @@ __BEGIN_DECLS +/* These definitions are normally provided by ucontext.h via + asm/sigcontext.h, asm/ptrace.h, and asm/elf.h. Otherwise we define + them here. */ +#ifndef __PPC64_ELF_H #define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ #define ELF_NFPREG 33 /* includes fpscr */ #define ELF_NVRREG 33 /* includes vscr */ @@ -41,6 +45,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +#endif /* gcc 3.1 and newer support __uint128_t. */ #if !__GNUC_PREREQ(3,1) diff --git a/sysdeps/unix/sysv/linux/sh/sysdep.h b/sysdeps/unix/sysv/linux/sh/sysdep.h index ee39121755..75557f554e 100644 --- a/sysdeps/unix/sysv/linux/sh/sysdep.h +++ b/sysdeps/unix/sysv/linux/sh/sysdep.h @@ -66,7 +66,12 @@ END (name) #ifndef PIC -# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +# define SYSCALL_ERROR_HANDLER \ + mov.l 0f,r1; \ + jmp @r1; \ + mov r0,r4; \ + .align 2; \ + 0: .long __syscall_error #else # if RTLD_PRIVATE_ERRNO # define SYSCALL_ERROR_HANDLER \ |