diff options
author | Alan Modra <amodra@gmail.com> | 2010-05-11 23:43:15 -0500 |
---|---|---|
committer | Ryan Arnold <ryanarn@etna.rchland.ibm.com> | 2010-05-11 23:43:41 -0500 |
commit | dd1f42ad8afb25e6930b0e7251520925208f5bc8 (patch) | |
tree | 9aa1304d21116a3b513652513c3d8e0d505708e0 | |
parent | 3ad0390e7f8f8401f714a9bd989f4f32df105a97 (diff) | |
download | glibc-dd1f42ad8afb25e6930b0e7251520925208f5bc8.tar.gz glibc-dd1f42ad8afb25e6930b0e7251520925208f5bc8.tar.xz glibc-dd1f42ad8afb25e6930b0e7251520925208f5bc8.zip |
Fix PowerPC64 glibc assembly to properly work with the linker automatic
multiple toc support, which may be needed when a static libc is linked into a large app. The requirements are: a) No tail calls are allowed to functions in a different object file, ie. a plain branch is not allowed. b) All calls to functions in a different object file must be followed by a nop. On PowerPC64, the parameter save area and the cr save location for the current function are in the previous frame, just like the lr save location. The parameter save area, cr save location and lr save location in the current frame are for use by *called* functions. In a number of places, glibc assembly used the wrong area, leaving those functions at the mercy of any called functions. We just happen to be lucky so far, but that may change with future versions of gcc.
-rw-r--r-- | ChangeLog | 36 | ||||
-rw-r--r-- | nptl/ChangeLog | 10 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h | 69 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc32/power4/memcmp.S | 2 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/bsd-_setjmp.S | 67 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/bsd-setjmp.S | 46 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/dl-trampoline.S | 71 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/fpu/s_copysign.S | 7 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/setjmp-common.S | 41 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/setjmp.S | 13 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/sysdep.h | 59 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S | 7 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S | 73 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S | 39 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S | 2 |
16 files changed, 309 insertions, 234 deletions
diff --git a/ChangeLog b/ChangeLog index e7f607fc2a..a16a1fba85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +2010-05-01 Alan Modra <amodra@gmail.com> + * sysdeps/powerpc/powerpc32/power4/memcmp.S: Correct cfi for r24. + * sysdeps/powerpc/powerpc64/bsd-_setjmp.S: Move contents.. + * sysdeps/powerpc/powerpc64/bsd-setjmp.S: ..and these too.. + * sysdeps/powerpc/powerpc64/setjmp.S: ..to here.. + * sysdeps/powerpc/powerpc64/setjmp-common.S: ..and here, with some + tidying. Don't tail-call __sigjmp_save for static lib. + * sysdeps/powerpc/powerpc64/sysdep.h (SAVE_ARG, REST_ARG): Correct + save location. + (CFI_SAVE_ARG, CFI_REST_ARG): New macros. + (CALL_MCOUNT): Add eh info, and nop after bl. + (TAIL_CALL_SYSCALL_ERROR): New macro. + (PSEUDO_RET): Use it. + * sysdeps/powerpc/powerpc64/dl-trampoline.S (_dl_runtime_resolve): + Correct save location of integer regs and cr. + (_dl_profile_resolve): Correct cr save location. Delete nops + after bl when SHARED. Reduce cfi size a little by better + placement of cfi directives. + * sysdeps/powerpc/powerpc64/fpu/s_copysign.S (__copysign): Don't + make a stack frame. Instead use parm save area as a temp. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S (__brk): Don't + make a stack frame. Use TAIL_CALL_SYSCALL_ERROR. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S (__clone): + Don't make a stack frame for parent, use parm save area. + Increase child stack frame to 112 bytes. Don't save unused reg, + and adjust reg usage. Set up cfi on error recovery and + epilogue of parent, and use TAIL_CALL_SYSCALL_ERROR, PSEUDO_RET. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S + (__makecontext): Add dummy nop after jump to exit. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S (__socket): + Use correct parm save area and cr save, reduce stack frame. + Correct cfi for possible PSEUDO_RET frame setup. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S (__vfork): + Branch to local label emitted by PSEUDO_RET rather than + __syscall_error. + 2010-03-10 Luis Machado <luisgpm@br.ibm.com> * sysdeps/powerpc/powerpc64/power7/memcpy.S: New file. * sysdeps/powerpc/powerpc32/power7/memcpy.S: New file. diff --git a/nptl/ChangeLog b/nptl/ChangeLog index dde74f45ee..d9f9ef635d 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,13 @@ +2010-05-01 Alan Modra <amodra@gmail.com> + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h + (PSEUDO): Use correct cr save. Don't use wrong parm save area + to save temps. Correct cfi for possible later frame manipulation. + (DOCARGS_1, UNDOCARGS_1): Use the correct parm save area. + (DOCARGS_2, UNDOCARGS_2, DOCARGS_3, UNDOCARGS_3): Likewise. + (DOCARGS_4, UNDOCARGS_4, DOCARGS_5, UNDOCARGS_5): Likewise. + (DOCARGS_6, UNDOCARGS_6): Likewise. + (CENABLE, CDISABLE): Add nops for non-shared calls. + 2010-03-23 Luis Machado <luisgpm@br.ibm.com> * pthread_cond_timedwait.c: Add check for diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h index 707765ab58..597630cea4 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -52,51 +52,70 @@ cfi_offset (lr, 16); \ DOCARGS_##args; /* save syscall args around CENABLE. */ \ CENABLE; \ - std 3,72(1); /* store CENABLE return value (MASK). */ \ + std 3,112(1); /* store CENABLE return value (MASK). */ \ UNDOCARGS_##args; /* restore syscall args. */ \ DO_CALL (SYS_ify (syscall_name)); \ mfcr 0; /* save CR/R3 around CDISABLE. */ \ - std 3,64(1); \ - std 0,8(1); \ - ld 3,72(1); /* pass MASK to CDISABLE. */ \ + std 3,120(1); \ + std 0,128+8(1); \ + cfi_offset (cr, 8); \ + ld 3,112(1); /* pass MASK to CDISABLE. */ \ CDISABLE; \ ld 9,128+16(1); \ - ld 0,8(1); /* restore CR/R3. */ \ - ld 3,64(1); \ + ld 0,128+8(1); /* restore CR/R3. */ \ + ld 3,120(1); \ mtlr 9; \ mtcr 0; \ - addi 1,1,128; + addi 1,1,128; \ + cfi_adjust_cfa_offset (-128); \ + cfi_restore (lr); \ + cfi_restore (cr) # define DOCARGS_0 # define UNDOCARGS_0 -# define DOCARGS_1 std 3,80(1); DOCARGS_0 -# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0 +# define DOCARGS_1 std 3,128+48(1); DOCARGS_0 +# define UNDOCARGS_1 ld 3,128+48(1); UNDOCARGS_0 -# define DOCARGS_2 std 4,88(1); DOCARGS_1 -# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1 +# define DOCARGS_2 std 4,128+56(1); DOCARGS_1 +# define UNDOCARGS_2 ld 4,128+56(1); UNDOCARGS_1 -# define DOCARGS_3 std 5,96(1); DOCARGS_2 -# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2 +# define DOCARGS_3 std 5,128+64(1); DOCARGS_2 +# define UNDOCARGS_3 ld 5,128+64(1); UNDOCARGS_2 -# define DOCARGS_4 std 6,104(1); DOCARGS_3 -# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3 +# define DOCARGS_4 std 6,128+72(1); DOCARGS_3 +# define UNDOCARGS_4 ld 6,128+72(1); UNDOCARGS_3 -# define DOCARGS_5 std 7,112(1); DOCARGS_4 -# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4 +# define DOCARGS_5 std 7,128+80(1); DOCARGS_4 +# define UNDOCARGS_5 ld 7,128+80(1); UNDOCARGS_4 -# define DOCARGS_6 std 8,120(1); DOCARGS_5 -# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5 +# define DOCARGS_6 std 8,128+88(1); DOCARGS_5 +# define UNDOCARGS_6 ld 8,128+88(1); UNDOCARGS_5 # ifdef IS_IN_libpthread -# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# ifdef SHARED +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# else +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel); nop +# endif # elif !defined NOT_IN_libc -# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# ifdef SHARED +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# else +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel); nop +# endif # elif defined IS_IN_librt -# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# ifdef SHARED +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# else +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel); nop +# endif # else # error Unsupported library # endif diff --git a/sysdeps/powerpc/powerpc32/power4/memcmp.S b/sysdeps/powerpc/powerpc32/power4/memcmp.S index 75b328403a..fe67833dff 100644 --- a/sysdeps/powerpc/powerpc32/power4/memcmp.S +++ b/sysdeps/powerpc/powerpc32/power4/memcmp.S @@ -646,7 +646,7 @@ L(Wunaligned): cfi_offset(r25,(24-64)) andi. rBITDIF, rN, 12 /* Get the W remainder */ stw r24,20(r1) - cfi_offset(r24,(24-64)) + cfi_offset(r24,(20-64)) slwi rSHL, rSHL, 3 lwz rWORD6, 0(rSTR2) lwzu rWORD8, 4(rSTR2) diff --git a/sysdeps/powerpc/powerpc64/bsd-_setjmp.S b/sysdeps/powerpc/powerpc64/bsd-_setjmp.S index 82b79a8098..86d49b1c6e 100644 --- a/sysdeps/powerpc/powerpc64/bsd-_setjmp.S +++ b/sysdeps/powerpc/powerpc64/bsd-_setjmp.S @@ -1,66 +1 @@ -/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. PowerPC32/64 version. - Copyright (C) 1994, 1997, 1999, 2000, 2002, 2003, 2004 - 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 <shlib-compat.h> -#include <libc-symbols.h> -#include <sysdep.h> -#include <bp-sym.h> - -#if defined NOT_IN_libc -/* Build a non-versioned object for rtld-*. */ -ENTRY (BP_SYM (_setjmp)) - CALL_MCOUNT 1 - li r4,0 /* Set second argument to 0. */ - b JUMPTARGET (__sigsetjmp_ent) -END (BP_SYM (_setjmp)) -libc_hidden_def (_setjmp) - -#else -/* Build a versioned object for libc. */ -# if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4) -symbol_version (__novmx_setjmp,_setjmp,GLIBC_2.3); - -ENTRY (BP_SYM (__novmx_setjmp)) - CALL_MCOUNT 1 - li r4,0 /* Set second argument to 0. */ - b JUMPTARGET (__novmx__sigsetjmp_ent) -END (BP_SYM (__novmx_setjmp)) -libc_hidden_def (__novmx_setjmp) -# endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4) */ - -default_symbol_version (__vmx_setjmp,_setjmp,GLIBC_2.3.4) -/* __GI__setjmp prototype is needed for ntpl i.e. _setjmp is defined - as a libc_hidden_proto & is used in sysdeps/generic/libc-start.c - if HAVE_CLEANUP_JMP_BUF is defined */ -ENTRY (BP_SYM (__GI__setjmp)) -#if defined SHARED && !defined IS_IN_rtld - std r2,40(r1) /* Save the callers TOC in the save area. */ -#endif - CALL_MCOUNT 1 - li r4,0 /* Set second argument to 0. */ - b JUMPTARGET (__vmx__sigsetjmp_ent) -END (BP_SYM (__GI__setjmp)) - -ENTRY (BP_SYM (__vmx_setjmp)) - CALL_MCOUNT 1 - li r4,0 /* Set second argument to 0. */ - b JUMPTARGET (__vmx__sigsetjmp_ent) -END (BP_SYM (__vmx_setjmp)) -libc_hidden_def (__vmx_setjmp) -#endif /* !NOT_IN_libc */ +/* _setjmp moved to setjmp-common.S */ diff --git a/sysdeps/powerpc/powerpc64/bsd-setjmp.S b/sysdeps/powerpc/powerpc64/bsd-setjmp.S index 543e83faa3..38b734fcb4 100644 --- a/sysdeps/powerpc/powerpc64/bsd-setjmp.S +++ b/sysdeps/powerpc/powerpc64/bsd-setjmp.S @@ -1,45 +1 @@ -/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. PowerPC32/64 version. - Copyright (C) 1994,1997,1999,2000,2003,2004 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 <shlib-compat.h> -#include <libc-symbols.h> -#include <sysdep.h> -#include <bp-sym.h> - -#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4) - - -ENTRY (__novmxsetjmp) - CALL_MCOUNT 1 - li r4,1 /* Set second argument to 1. */ - b JUMPTARGET (__novmx__sigsetjmp_ent) -END (__novmxsetjmp) -strong_alias (__novmxsetjmp, __novmx__setjmp) -symbol_version (__novmxsetjmp, setjmp, GLIBC_2.3) - -#endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4) */ - - -ENTRY (__vmxsetjmp) - CALL_MCOUNT 1 - li r4,1 /* Set second argument to 1. */ - b JUMPTARGET (__vmx__sigsetjmp_ent) -END (__vmxsetjmp) -strong_alias (__vmxsetjmp, __vmx__setjmp) -strong_alias (__vmx__sigsetjmp, __setjmp) -default_symbol_version (__vmxsetjmp, setjmp, GLIBC_2.3.4) +/* setjmp moved to setjmp-common.S */ diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S index 9ca394dda2..40029aff85 100644 --- a/sysdeps/powerpc/powerpc64/dl-trampoline.S +++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S @@ -27,42 +27,47 @@ parm1 (r3) and the index (r0) need to be converted to an offset (index * 24) in parm2 (r4). */ +#define FRAME_SIZE 112 +#define INT_PARMS FRAME_SIZE+48 EALIGN(_dl_runtime_resolve, 4, 0) /* We need to save the registers used to pass parameters, ie. r3 thru - r10; the registers are saved in a stack frame. */ - stdu r1,-128(r1) - cfi_adjust_cfa_offset (128) - std r3,48(r1) + r10; the registers are saved in the parameter save area. */ + stdu r1,-FRAME_SIZE(r1) + cfi_adjust_cfa_offset (FRAME_SIZE) + std r3,INT_PARMS+0(r1) mr r3,r11 - std r4,56(r1) + std r4,INT_PARMS+8(r1) sldi r4,r0,1 - std r5,64(r1) + std r5,INT_PARMS+16(r1) add r4,r4,r0 - std r6,72(r1) + std r6,INT_PARMS+24(r1) sldi r4,r4,3 - std r7,80(r1) + std r7,INT_PARMS+32(r1) mflr r0 - std r8,88(r1) -/* Store the LR in the LR Save area of the previous frame. */ - std r0,128+16(r1) + std r8,INT_PARMS+40(r1) +/* Store the LR in the LR Save area. */ + std r0,FRAME_SIZE+16(r1) cfi_offset (lr, 16) mfcr r0 - std r9,96(r1) - std r10,104(r1) + std r9,INT_PARMS+48(r1) + std r10,INT_PARMS+56(r1) /* I'm almost certain we don't have to save cr... be safe. */ - std r0,8(r1) + std r0,FRAME_SIZE+8(r1) bl JUMPTARGET(_dl_fixup) +#ifndef SHARED + nop +#endif /* Put the registers back. */ - ld r0,128+16(r1) - ld r10,104(r1) - ld r9,96(r1) - ld r8,88(r1) - ld r7,80(r1) + ld r0,FRAME_SIZE+16(r1) + ld r10,INT_PARMS+56(r1) + ld r9,INT_PARMS+48(r1) + ld r8,INT_PARMS+40(r1) + ld r7,INT_PARMS+32(r1) mtlr r0 - ld r0,8(r1) - ld r6,72(r1) - ld r5,64(r1) - ld r4,56(r1) + ld r0,FRAME_SIZE+8(r1) + ld r6,INT_PARMS+24(r1) + ld r5,INT_PARMS+16(r1) + ld r4,INT_PARMS+8(r1) mtcrf 0xFF,r0 /* Load the target address, toc and static chain reg from the function descriptor returned by fixup. */ @@ -70,11 +75,13 @@ EALIGN(_dl_runtime_resolve, 4, 0) ld r2,8(r3) mtctr r0 ld r11,16(r3) - ld r3,48(r1) + ld r3,INT_PARMS+0(r1) /* Unwind the stack frame, and jump. */ - addi r1,r1,128 + addi r1,r1,FRAME_SIZE bctr END(_dl_runtime_resolve) +#undef FRAME_SIZE +#undef INT_PARMS /* Stack layout: +592 previous backchain @@ -176,13 +183,13 @@ EALIGN(_dl_profile_resolve, 4, 0) /* Spill r30, r31 to preserve the link_map* and reloc_addr, in case we need to call _dl_call_pltexit. */ std r31,-8(r1) - cfi_offset(r31,-8) std r30,-16(r1) - cfi_offset(r30,-16) /* We need to save the registers used to pass parameters, ie. r3 thru r10; the registers are saved in a stack frame. */ stdu r1,-FRAME_SIZE(r1) cfi_adjust_cfa_offset (FRAME_SIZE) + cfi_offset(r31,-8) + cfi_offset(r30,-16) std r3,INT_PARMS+0(r1) mr r3,r11 std r4,INT_PARMS+8(r1) @@ -205,7 +212,7 @@ EALIGN(_dl_profile_resolve, 4, 0) std r10,INT_PARMS+56(r1) std r8,CALLING_SP(r1) /* I'm almost certain we don't have to save cr... be safe. */ - std r0,8(r1) + std r0,FRAME_SIZE+8(r1) ld r12,.LC__dl_hwcap@toc(r2) #ifdef SHARED /* Load _rtld-global._dl_hwcap. */ @@ -265,7 +272,9 @@ L(saveFP): mr r30,r4 std r0,0(r7) bl JUMPTARGET(_dl_profile_fixup) +#ifndef SHARED nop +#endif /* Test *framesizep > 0 to see if need to do pltexit processing. */ ld r0,STACK_FRAME(r1) /* Put the registers back. */ @@ -306,7 +315,7 @@ L(restoreFXR): ld r8,INT_PARMS+40(r1) ld r7,INT_PARMS+32(r1) mtlr r0 - ld r0,8(r1) + ld r0,FRAME_SIZE+8(r1) ld r6,INT_PARMS+24(r1) ld r5,INT_PARMS+16(r1) ld r4,INT_PARMS+8(r1) @@ -370,7 +379,7 @@ L(restoreFXR2): ld r8,INT_PARMS+40(r1) ld r7,INT_PARMS+32(r1) mtlr r0 - ld r0,8(r1) + ld r0,FRAME_SIZE+8(r1) ld r6,INT_PARMS+24(r1) ld r5,INT_PARMS+16(r1) ld r4,INT_PARMS+8(r1) @@ -418,7 +427,9 @@ L(callpltexit): addi r5,r1,INT_PARMS addi r6,r1,INT_RTN bl JUMPTARGET(_dl_call_pltexit) +#ifndef SHARED nop +#endif /* Restore the return values from target function. */ lwz r12,VR_VRSAVE(r1) ld r3,INT_RTN(r1) diff --git a/sysdeps/powerpc/powerpc64/fpu/s_copysign.S b/sysdeps/powerpc/powerpc64/fpu/s_copysign.S index 38171e31d7..ff7490629e 100644 --- a/sysdeps/powerpc/powerpc64/fpu/s_copysign.S +++ b/sysdeps/powerpc/powerpc64/fpu/s_copysign.S @@ -28,15 +28,12 @@ ENTRY(__copysign) /* double [f1] copysign (double [f1] x, double [f2] y); copysign(x,y) returns a value with the magnitude of x and with the sign bit of y. */ - stdu r1,-48(r1) - cfi_adjust_cfa_offset (48) - stfd fp2,24(r1) + stfd fp2,56(r1) nop nop nop - ld r3,24(r1) + ld r3,56(r1) cmpdi r3,0 - addi r1,r1,48 blt L(0) fabs fp1,fp1 blr diff --git a/sysdeps/powerpc/powerpc64/setjmp-common.S b/sysdeps/powerpc/powerpc64/setjmp-common.S index 606eef5935..a059a91f8b 100644 --- a/sysdeps/powerpc/powerpc64/setjmp-common.S +++ b/sysdeps/powerpc/powerpc64/setjmp-common.S @@ -39,10 +39,33 @@ #endif .machine "altivec" +ENTRY (setjmp) + CALL_MCOUNT 1 + li r4,1 /* Set second argument to 1. */ + b JUMPTARGET (GLUE(__sigsetjmp,_ent)) +END (setjmp) + +#if defined SHARED && !defined IS_IN_rtld && !defined __NO_VMX__ +/* When called from within libc we need a special version of _setjmp + that saves r2 since the call won't go via a plt call stub. See + bugz #269. __GI__setjmp is used in csu/libc-start.c when + HAVE_CLEANUP_JMP_BUF is defined. */ +ENTRY (BP_SYM (__GI__setjmp)) + std r2,40(r1) /* Save the callers TOC in the save area. */ + cfi_endproc +END_2 (BP_SYM (__GI__setjmp)) +/* Fall thru. */ +#endif + +ENTRY (BP_SYM (_setjmp)) + CALL_MCOUNT 1 + li r4,0 /* Set second argument to 0. */ + b JUMPTARGET (GLUE(__sigsetjmp,_ent)) +END (BP_SYM (_setjmp)) +libc_hidden_def (_setjmp) + ENTRY (BP_SYM (__sigsetjmp)) CALL_MCOUNT 2 - .globl JUMPTARGET(GLUE(__sigsetjmp,_ent)) - .hidden JUMPTARGET(GLUE(__sigsetjmp,_ent)) JUMPTARGET(GLUE(__sigsetjmp,_ent)): CHECK_BOUNDS_BOTH_WIDE_LIT (r3, r8, r9, JB_SIZE) #ifdef PTR_MANGLE @@ -190,7 +213,19 @@ L(no_vmx): #if defined NOT_IN_libc && defined IS_IN_rtld li r3,0 blr +#elif defined SHARED + b JUMPTARGET (BP_SYM (__sigjmp_save)) #else - b JUMPTARGET (BP_SYM (__sigjmp_save)) + mflr r0 + std r0,16(r1) + stdu r1,-112(r1) + cfi_adjust_cfa_offset(112) + cfi_offset(lr,16) + bl JUMPTARGET (BP_SYM (__sigjmp_save)) + nop + ld r0,112+16(r1) + addi r1,r1,112 + mtlr r0 + blr #endif END (BP_SYM (__sigsetjmp)) diff --git a/sysdeps/powerpc/powerpc64/setjmp.S b/sysdeps/powerpc/powerpc64/setjmp.S index acbf3728e5..83b237ba2a 100644 --- a/sysdeps/powerpc/powerpc64/setjmp.S +++ b/sysdeps/powerpc/powerpc64/setjmp.S @@ -27,19 +27,32 @@ #else /* !NOT_IN_libc */ /* Build a versioned object for libc. */ +default_symbol_version (__vmxsetjmp, setjmp, GLIBC_2.3.4) +default_symbol_version (__vmx_setjmp,_setjmp,GLIBC_2.3.4) default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4) +# define setjmp __vmxsetjmp +# define _setjmp __vmx_setjmp # define __sigsetjmp __vmx__sigsetjmp # define __sigjmp_save __vmx__sigjmp_save # include "setjmp-common.S" +strong_alias (__vmxsetjmp, __vmx__setjmp) +strong_alias (__vmx__sigsetjmp, __setjmp) # if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4) +# undef setjmp +# undef _setjmp # undef __sigsetjmp # undef __sigjmp_save # undef JB_SIZE # define __NO_VMX__ +symbol_version (__novmxsetjmp, setjmp, GLIBC_2.3) +symbol_version (__novmx_setjmp,_setjmp,GLIBC_2.3); symbol_version (__novmx__sigsetjmp,__sigsetjmp,GLIBC_2.3) +# define setjmp __novmxsetjmp +# define _setjmp __novmx_setjmp # define __sigsetjmp __novmx__sigsetjmp # define __sigjmp_save __novmx__sigjmp_save # include "setjmp-common.S" +strong_alias (__novmxsetjmp, __novmx__setjmp) # endif #endif /* !NOT_IN_libc */ diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h index 2745d7eb71..5fc6e4f2f3 100644 --- a/sysdeps/powerpc/powerpc64/sysdep.h +++ b/sysdeps/powerpc/powerpc64/sysdep.h @@ -27,14 +27,28 @@ .macro SAVE_ARG NARG .if \NARG SAVE_ARG \NARG-1 - std 2+\NARG,-72+8*(\NARG)(1) + std 2+\NARG,40+8*(\NARG)(1) .endif .endm .macro REST_ARG NARG .if \NARG REST_ARG \NARG-1 - ld 2+\NARG,40+8*(\NARG)(1) + ld 2+\NARG,112+40+8*(\NARG)(1) + .endif + .endm + + .macro CFI_SAVE_ARG NARG + .if \NARG + CFI_SAVE_ARG \NARG-1 + cfi_offset(2+\NARG,40+8*(\NARG)) + .endif + .endm + + .macro CFI_REST_ARG NARG + .if \NARG + CFI_REST_ARG \NARG-1 + cfi_restore(2+\NARG) .endif .endm @@ -46,11 +60,20 @@ SAVE_ARG \NARG std r0,16(r1) stdu r1,-112(r1) + cfi_adjust_cfa_offset(112) + cfi_offset(lr,16) + CFI_SAVE_ARG \NARG bl JUMPTARGET (_mcount) +#ifndef SHARED + nop +#endif ld r0,128(r1) REST_ARG \NARG - addi r1,r1,112 mtlr r0 + addi r1,r1,112 + cfi_adjust_cfa_offset(-112) + cfi_restore(lr) + CFI_REST_ARG \NARG #endif .endm @@ -198,9 +221,37 @@ LT_LABELSUFFIX(name,_name_end): ; \ ENTRY (name) \ DO_CALL (SYS_ify (syscall_name)); +#ifdef SHARED +#define TAIL_CALL_SYSCALL_ERROR \ + b JUMPTARGET(__syscall_error) +#else +/* Static version might be linked into a large app with a toc exceeding + 64k. We can't put a toc adjusting stub on a plain branch, so can't + tail call __syscall_error. */ +#define TAIL_CALL_SYSCALL_ERROR \ + .ifdef .Local_syscall_error; \ + b .Local_syscall_error; \ + .else; \ +.Local_syscall_error: \ + mflr 0; \ + std 0,16(1); \ + stdu 1,-112(1); \ + cfi_adjust_cfa_offset(112); \ + cfi_offset(lr,16); \ + bl JUMPTARGET(__syscall_error); \ + nop; \ + ld 0,112+16(1); \ + addi 1,1,112; \ + cfi_adjust_cfa_offset(-112); \ + mtlr 0; \ + cfi_restore(lr); \ + blr; \ + .endif +#endif + #define PSEUDO_RET \ bnslr+; \ - b JUMPTARGET(__syscall_error) + TAIL_CALL_SYSCALL_ERROR #define ret PSEUDO_RET diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S index f2ac00d4c7..ef574c14fc 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S @@ -32,19 +32,16 @@ ENTRY (BP_SYM (__brk)) CALL_MCOUNT 1 DISCARD_BOUNDS (r3) /* the bounds are meaningless, so toss 'em. */ - stdu r1,-64(r1) - cfi_adjust_cfa_offset (64) std r3,48(r1) DO_CALL(SYS_ify(brk)) - ld r6,48(r1) + ld r6,48(r1) ld r5,.LC__curbrk@toc(r2) std r3,0(r5) cmpld r6,r3 - addi r1,r1,64 li r3,0 blelr+ li r3,ENOMEM - b JUMPTARGET(__syscall_error) + TAIL_CALL_SYSCALL_ERROR END (BP_SYM (__brk)) weak_alias (BP_SYM (__brk), BP_SYM (brk)) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S index f1a55e64db..d14da54fd7 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S @@ -46,35 +46,32 @@ ENTRY (BP_SYM (__clone)) cror cr0*4+eq,cr1*4+eq,cr0*4+eq beq- cr0,L(badargs) - /* Set up stack frame for parent. */ - stdu r1,-80(r1) - cfi_adjust_cfa_offset (80) - std r29,56(r1) - std r30,64(r1) - std r31,72(r1) - cfi_offset(r29,-56) - cfi_offset(r30,-64) - cfi_offset(r31,-72) + /* Save some regs in parm save area. */ #ifdef RESET_PID - std r28,48(r1) - cfi_offset(r28,-48) + std r29,48(r1) #endif + std r30,56(r1) + std r31,64(r1) +#ifdef RESET_PID + cfi_offset(r29,48) +#endif + cfi_offset(r30,56) + cfi_offset(r31,64) /* Set up stack frame for child. */ clrrdi r4,r4,4 li r0,0 - stdu r0,-48(r4) /* min stack frame is 48 bytes per ABI */ + stdu r0,-112(r4) /* min stack frame is 112 bytes per ABI */ /* Save fn, args, stack across syscall. */ - mr r29,r3 /* Function in r29. */ - mr r30,r4 /* Stack pointer in r30. */ + mr r30,r3 /* Function in r30. */ #ifdef RESET_PID - mr r28,r5 /* Flags in r28. */ + mr r29,r5 /* Flags in r29. */ #endif mr r31,r6 /* Argument in r31. */ - /* 'flags' argument is first parameter to clone syscall. (The other - argument is the stack pointer, already in r4.) */ + /* 'flags' argument is first parameter to clone syscall. + Second is the stack pointer, already in r4. */ mr r3,r5 /* Move the parent_tid, child_tid and tls arguments. */ mr r5,r7 @@ -94,9 +91,9 @@ ENTRY (BP_SYM (__clone)) bne- cr1,L(parent) /* The '-' is to minimise the race. */ #ifdef RESET_PID - andis. r0,r28,CLONE_THREAD>>16 + andis. r0,r29,CLONE_THREAD>>16 bne+ cr0,L(oldpid) - andi. r0,r28,CLONE_VM + andi. r0,r29,CLONE_VM li r3,-1 bne- cr0,L(nomoregetpid) DO_CALL(SYS_ify(getpid)) @@ -108,8 +105,8 @@ L(oldpid): std r2,40(r1) /* Call procedure. */ - ld r0,0(r29) - ld r2,8(r29) + ld r0,0(r30) + ld r2,8(r30) mtctr r0 mr r3,r31 bctrl @@ -119,25 +116,35 @@ L(oldpid): b JUMPTARGET(__GI__exit) #else b JUMPTARGET(_exit) + /* We won't ever get here but provide a nop so that the linker + will insert a toc adjusting stub if necessary. */ + nop #endif +L(badargs): + cfi_startproc + li r3,EINVAL + TAIL_CALL_SYSCALL_ERROR + L(parent): /* Parent. Restore registers & return. */ #ifdef RESET_PID - ld r28,48(r1) + cfi_offset(r29,48) #endif - ld r31,72(r1) - ld r30,64(r1) - ld r29,56(r1) - addi r1,r1,80 - bnslr+ - b JUMPTARGET(__syscall_error) - -L(badargs): - li r3,EINVAL - b JUMPTARGET(__syscall_error) + cfi_offset(r30,56) + cfi_offset(r31,64) +#ifdef RESET_PID + ld r29,48(r1) +#endif + ld r30,56(r1) + ld r31,64(r1) +#ifdef RESET_PID + cfi_restore(r29) +#endif + cfi_restore(r30) + cfi_restore(r31) + PSEUDO_RET - cfi_startproc END (BP_SYM (__clone)) weak_alias (BP_SYM (__clone), BP_SYM (clone)) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S index 4a82802d96..18baa39d6a 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S @@ -154,6 +154,7 @@ L(BADSTATUS): b JUMPTARGET(__GI_exit); #else b JUMPTARGET(exit); + nop #endif /* The address of the exit code is in the link register. Store the lr diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S index 15d8e84c1f..a0ae11594a 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S @@ -39,8 +39,6 @@ #define NARGS 3 #endif -#define stackblock 80 /* offset to socket parm area. */ - #ifndef __socket # ifndef NO_WEAK_ALIAS # define __socket P(__,socket) @@ -49,11 +47,14 @@ # endif #endif +#define FRAMESIZE 128 +#define stackblock FRAMESIZE+48 /* offset to parm save area. */ + .text ENTRY(__socket) CALL_MCOUNT NARGS - stdu r1,-144(r1) - cfi_adjust_cfa_offset(144) + stdu r1,-FRAMESIZE(r1) + cfi_adjust_cfa_offset(FRAMESIZE) #if NARGS >= 1 std r3,stackblock(r1) #endif @@ -87,33 +88,39 @@ ENTRY(__socket) bne- .Lsocket_cancel #endif - li r3,P(SOCKOP_,socket) + li r3,P(SOCKOP_,socket) addi r4,r1,stackblock DO_CALL(SYS_ify(socketcall)) - addi r1,r1,144 + addi r1,r1,FRAMESIZE + cfi_adjust_cfa_offset(-FRAMESIZE) PSEUDO_RET #if defined NEED_CANCELLATION && defined CENABLE .Lsocket_cancel: + cfi_adjust_cfa_offset(FRAMESIZE) mflr r9 - std r9,144+16(r1) + std r9,FRAMESIZE+16(r1) cfi_offset (lr, 16) CENABLE - std r3,72(r1) - li r3,P(SOCKOP_,socket) + std r3,120(r1) + li r3,P(SOCKOP_,socket) addi r4,r1,stackblock DO_CALL(SYS_ify(socketcall)) mfcr r0 - std r3,64(r1) - std r0,8(r1) - ld r3,72(r1) + std r3,112(r1) + std r0,FRAMESIZE+8(r1) + cfi_offset (cr, 8) + ld r3,120(r1) CDISABLE - ld r4,144+16(r1) - ld r0,8(r1) - ld r3,64(r1) + ld r4,FRAMESIZE+16(r1) + ld r0,FRAMESIZE+8(r1) + ld r3,112(r1) mtlr r4 mtcr r0 - addi r1,r1,144 + addi r1,r1,FRAMESIZE + cfi_adjust_cfa_offset(-FRAMESIZE) + cfi_restore(lr) + cfi_restore(cr) PSEUDO_RET #endif PSEUDO_END (__socket) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S index 2f5df38cf8..14d0c2bf10 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S @@ -39,7 +39,7 @@ ENTRY (__vfork) bnslr+ /* Check if vfork syscall is known at all. */ cmpdi r3,ENOSYS - bne JUMPTARGET(__syscall_error) + bne .Local_syscall_error # endif #endif |