diff --git a/ports/ChangeLog.hppa b/ports/ChangeLog.hppa index 41b594c..609670e 100644 --- a/ports/ChangeLog.hppa +++ b/ports/ChangeLog.hppa @@ -1,3 +1,11 @@ +2012-11-18 Carlos O'Donell + + * ports/sysdeps/hppa/__longjmp.S: Removed. + * ports/sysdeps/hppa/__longjmp.c: New file. + * ports/sysdeps/unix/sysv/linux/hppa/____longjmp_chk.c: New file. + * ports/sysdeps/hppa/bits/setjmp.h: Use union for __jmp_buf. + * ports/sysdeps/hppa/setjmp.S: Comment byte offsets and padding. + 2012-10-29 Carlos O'Donell * sysdeps/unix/sysv/linux/hppa/sysdep.h (ENTRY): Add cfi_startproc. diff --git a/ports/sysdeps/hppa/__longjmp.S b/ports/sysdeps/hppa/__longjmp.S deleted file mode 100644 index 4ef219e..0000000 --- a/ports/sysdeps/hppa/__longjmp.S +++ /dev/null @@ -1,71 +0,0 @@ -/* longjmp for PA-RISC. - Copyright (C) 1997, 1998 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, see - . */ - -#include -#define _SETJMP_H -#define _ASM -#include - -/* __longjmp(jmpbuf, val) */ - - .text - .align 4 - .globl __longjmp - .export __longjmp, code - .proc - .callinfo -__longjmp: - /* set return value */ - copy %r25, %r28 - - ldw 0(%r26), %r3 - ldw 8(%r26), %r4 - ldw 12(%r26), %r5 - ldw 16(%r26), %r6 - ldw 20(%r26), %r7 - ldw 24(%r26), %r8 - ldw 28(%r26), %r9 - ldw 32(%r26), %r10 - ldw 36(%r26), %r11 - ldw 40(%r26), %r12 - ldw 44(%r26), %r13 - ldw 48(%r26), %r14 - ldw 52(%r26), %r15 - ldw 56(%r26), %r16 - ldw 60(%r26), %r17 - ldw 64(%r26), %r18 - ldw 68(%r26), %r19 - ldw 72(%r26), %r27 - ldw 76(%r26), %r30 - - ldw 80(%r26), %rp - - ldo 88(%r26),%r20 - fldds,ma 8(%r20), %fr12 - fldds,ma 8(%r20), %fr13 - fldds,ma 8(%r20), %fr14 - fldds,ma 8(%r20), %fr15 - fldds,ma 8(%r20), %fr16 - fldds,ma 8(%r20), %fr17 - fldds,ma 8(%r20), %fr18 - fldds,ma 8(%r20), %fr19 - fldds,ma 8(%r20), %fr20 - fldds 0(%r20), %fr21 - - bv,n %r0(%r2) - .procend diff --git a/ports/sysdeps/hppa/__longjmp.c b/ports/sysdeps/hppa/__longjmp.c new file mode 100644 index 0000000..8ad5105 --- /dev/null +++ b/ports/sysdeps/hppa/__longjmp.c @@ -0,0 +1,83 @@ +/* longjmp for PA-RISC. + Copyright (C) 1997-2012 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, see + . */ + +#include +#include + +/* Jump to the position specified by ENV, causing the + setjmp call there to return VAL, or 1 if VAL is 0. */ +void +__longjmp (__jmp_buf env, int val) +{ + /* We must use one of the non-callee saves registers + for env. */ + register unsigned long r26 asm ("r26") = (unsigned long)&env[0]; + +#ifdef CHECK_SP + CHECK_SP (env[0].__jmp_buf.__sp); +#endif + + asm volatile( + /* Set return value. */ + "copy %0, %%r28\n\t" + /* Load callee saves from r3 to r18. */ + "ldw 0(%1), %%r3\n\t" + "ldw 8(%1), %%r4\n\t" + "ldw 12(%1), %%r5\n\t" + "ldw 16(%1), %%r6\n\t" + "ldw 20(%1), %%r7\n\t" + "ldw 24(%1), %%r8\n\t" + "ldw 28(%1), %%r9\n\t" + "ldw 32(%1), %%r10\n\t" + "ldw 36(%1), %%r11\n\t" + "ldw 40(%1), %%r12\n\t" + "ldw 44(%1), %%r13\n\t" + "ldw 48(%1), %%r14\n\t" + "ldw 52(%1), %%r15\n\t" + "ldw 56(%1), %%r16\n\t" + "ldw 60(%1), %%r17\n\t" + "ldw 64(%1), %%r18\n\t" + /* Load PIC register. */ + "ldw 68(%1), %%r19\n\t" + /* Load static link register. */ + "ldw 72(%1), %%r27\n\t" + /* Load stack pointer. */ + "ldw 76(%1), %%r30\n\t" + /* Load return pointer. */ + "ldw 80(%1), %%rp\n\t" + /* Ues a spare caller saves register. */ + "ldo 88(%1),%%r20\n\t" + /* Load callee saves from fr12 to fr21. */ + "fldds,ma 8(%%r20), %%fr12\n\t" + "fldds,ma 8(%%r20), %%fr13\n\t" + "fldds,ma 8(%%r20), %%fr14\n\t" + "fldds,ma 8(%%r20), %%fr15\n\t" + "fldds,ma 8(%%r20), %%fr16\n\t" + "fldds,ma 8(%%r20), %%fr17\n\t" + "fldds,ma 8(%%r20), %%fr18\n\t" + "fldds,ma 8(%%r20), %%fr19\n\t" + "fldds,ma 8(%%r20), %%fr20\n\t" + "fldds 0(%%r20), %%fr21\n\t" + /* Jump back to stored return address. */ + "bv,n %%r0(%%r2)\n\t" + : /* No outputs. */ + : "r" (val == 0 ? 1 : val), "r" (r26) + : /* No point in clobbers. */ ); + /* Avoid `volatile function does return' warnings. */ + for (;;); +} diff --git a/ports/sysdeps/hppa/bits/setjmp.h b/ports/sysdeps/hppa/bits/setjmp.h index 19a0cfe..7283cc1 100644 --- a/ports/sysdeps/hppa/bits/setjmp.h +++ b/ports/sysdeps/hppa/bits/setjmp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2000-2012 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 @@ -23,13 +23,38 @@ # error "Never include directly; use instead." #endif -/* The previous bits/setjmp.h had __jmp_buf defined as a structure. - We use an array of 'double' instead, to make writing the assembler - easier, and to ensure proper alignment. Naturally, user code should - not depend on either representation. */ - #ifndef _ASM -typedef double __jmp_buf[21]; +/* The entire jump buffer must be 168 bytes long and laid + out in exactly as follows for ABI consistency. + * 20 x 32-bit gprs, with 8-bytes of padding, arranged so: + - r3 (callee saves) + - 4 bytes of padding. + - r4-r18 (callee saves) + - r19 (PIC register) + - r27 (static link register) + - r30 (stcack pointer) + - r2 (return pointer) + - 4 bytes of padding. + * 10 x 64-bit fprs in this order: + - fr12-fr21 (callee saves) + Note: We have 8 bytes of free space for future uses. */ +typedef union + { + struct __jmp_buf_internal_tag + { + int __r3; + int __pad0; + int __r4_r18[15]; + int __r19; + int __r27; + int __sp; + int __rp; + int __pad1; + double __fr12_fr21[10]; + } __jmp_buf; + /* Legacy definition. Ensures double alignment for fpsrs. */ + double __align[21]; + } __jmp_buf[1]; #endif #endif /* bits/setjmp.h */ diff --git a/ports/sysdeps/hppa/setjmp.S b/ports/sysdeps/hppa/setjmp.S index 146e4d1..0f05fd9 100644 --- a/ports/sysdeps/hppa/setjmp.S +++ b/ports/sysdeps/hppa/setjmp.S @@ -1,5 +1,5 @@ /* setjmp for HPPA. - Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + Copyright (C) 1995-2012 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 @@ -31,6 +31,8 @@ .callinfo __sigsetjmp: stw %r3, 0(%r26) + /* This padding exists for unknown historical reasons. */ + /* 4 - 4 bytes of padding. */ stw %r4, 8(%r26) stw %r5, 12(%r26) stw %r6, 16(%r26) @@ -51,7 +53,8 @@ __sigsetjmp: stw %r30, 76(%r26) stw %rp, 80(%r26) - + /* This padding exists to ensure double alignment for fprs. */ + /* 84 - 4 bytes of padding. */ ldo 88(%r26),%r1 fstds,ma %fr12, 8(%r1) /* 88 */ fstds,ma %fr13, 8(%r1) /* 96 */ @@ -63,6 +66,7 @@ __sigsetjmp: fstds,ma %fr19, 8(%r1) /* 144 */ fstds,ma %fr20, 8(%r1) /* 152 */ fstds %fr21, 0(%r1) /* 160 */ + /* Total of 168 bytes. */ b __sigjmp_save nop .procend diff --git a/ports/sysdeps/unix/sysv/linux/hppa/____longjmp_chk.c b/ports/sysdeps/unix/sysv/linux/hppa/____longjmp_chk.c new file mode 100644 index 0000000..46357dd --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/hppa/____longjmp_chk.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2009-2012 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 General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include +#include +#define __longjmp ____longjmp_chk +#define CHECK_SP(sp) \ + do { \ + register unsigned long this_sp asm ("r30"); \ + /* The stack grows up, therefore frames that were created and then \ + destroyed must all have stack values higher than ours. */ \ + if ((unsigned long) (sp) > this_sp) \ + { \ + struct sigaltstack oss; \ + INTERNAL_SYSCALL_DECL (err); \ + int result = INTERNAL_SYSCALL (sigaltstack, err, 2, NULL, &oss);\ + /* If we aren't using an alternate stack then we have already \ + shown that we are jumping to a frame that doesn't exist so \ + error out. If we are using an alternate stack we must prove \ + that we are jumping *out* of the alternate stack. Note that \ + the check for that is the same as that for _STACK_GROWS_UP \ + as for _STACK_GROWS_DOWN. */ \ + if (!INTERNAL_SYSCALL_ERROR_P (result, err) \ + && ((oss.ss_flags & SS_ONSTACK) == 0 \ + || ((unsigned long) oss.ss_sp + oss.ss_size \ + - (unsigned long) (sp)) < oss.ss_size)) \ + __fortify_fail ("longjmp causes uninitialized stack frame"); \ + } \ + } while (0) + +#include <__longjmp.c>