diff options
Diffstat (limited to 'ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S')
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S b/ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S index f4ce5d3a3c..6025bf609c 100644 --- a/ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S +++ b/ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2013 Free Software Foundation, Inc. +/* Copyright (C) 2009-2014 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 @@ -15,6 +15,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <sigaltstack-offsets.h> + .section .rodata.str1.8,"aMS",@progbits,1 .align 8 .LC0: @@ -29,13 +31,58 @@ longjmp_msg: #define __longjmp ____longjmp_chk -#define CHECK_RSP(reg) \ - cmp.ltu p0, p8 = reg, r12; \ -(p8) br.cond.dpnt .Lok;; \ - addl r28 = @ltoffx(longjmp_msg#), r1;; \ - ld8.mov r28 = [r28], longjmp_msg#;; \ - ld8 out0 = [r28]; \ +/* We use 32 bytes (rather than sizeof(stack_t)) so that we keep the stack + properly aligned. But we still want a sanity check to make sure 32 is + actually enough. */ +#define STACK_SPACE ((sizeSS + 31) & -32) + +/* Check the stack pointer held in the jumpbuf. Make sure it's in either the + current stack (r12) or in the signal stack. */ +#define CHECK_RSP \ + ld8 loc0 = [in0]; \ + ;; \ + /* First see if target stack is within current one. */ \ + cmp.ltu p0, p8 = loc0, r12; \ +(p8) br.cond.dptk.many .Lok; \ + \ + /* Check if it's an alternative signal stack. */ \ + mov out0 = r0; \ + add out1 = -STACK_SPACE, r12; \ + ;; \ + mov r12 = out1; \ + DO_CALL_VIA_BREAK (SYS_ify (sigaltstack)); \ + ;; \ + /* If the syscall failed, then assume it's OK. */ \ + cmp.eq p8, p0 = -1, r10; \ +(p8) br.cond.spnt .Lok; \ + /* Move stack_t into regs. */ \ + add r14 = oSS_FLAGS, r12; /* ss_flags */ \ + add r15 = oSS_SIZE, r12; /* ss_size */ \ + ld8 r16 = [r12]; /* ss_sp */ \ + ;; \ + ld4 r17 = [r14]; /* ss_flags */ \ + ld8 r18 = [r15]; /* ss_size */ \ + ;; \ + sub r19 = r16, r18; /* sp - size */ \ + /* See if we're currently on the altstack. */ \ + tbit.nz p0, p8 = r17, 0; /* SS_ONSTACK */ \ +(p8) br.cond.spnt .Lfail; \ + /* Verify target is within alternative stack. */ \ + cmp.gtu p7, p0 = loc0, r16; \ +(p7) br.cond.spnt .Lfail; \ + ;; \ + cmp.ltu p0, p8 = loc0, r19; \ +(p8) br.cond.sptk.many .Lok; \ + ;; \ + \ + /* Still here? Abort! */ \ +.Lfail: \ + add r12 = STACK_SPACE, r12; \ + addl loc0 = @ltoffx(longjmp_msg#), r1;; \ + ld8.mov loc0 = [loc0], longjmp_msg#;; \ + ld8 out0 = [loc0]; \ br.call.sptk.many b0 = HIDDEN_JUMPTARGET(__fortify_fail)#;; \ -.Lok: +.Lok: \ + add r12 = STACK_SPACE, r12; #include "__longjmp.S" |