Blame sysdeps/unix/sysv/linux/alpha/____longjmp_chk.S

Packit 6c4009
/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library.  If not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <jmpbuf-offsets.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
	.section .rodata.str1.1,"aMS",@progbits,1
Packit 6c4009
	.type   longjmp_msg,@object
Packit 6c4009
longjmp_msg:
Packit 6c4009
	.string "longjmp causes uninitialized stack frame"
Packit 6c4009
	.size   longjmp_msg, .-longjmp_msg
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Jump to the position specified by ENV, causing the
Packit 6c4009
   setjmp call there to return VAL, or 1 if VAL is 0.
Packit 6c4009
   void __longjmp (__jmp_buf env, int val).  */
Packit 6c4009
	.text
Packit 6c4009
	.align	4
Packit 6c4009
	.globl	____longjmp_chk
Packit 6c4009
	.type	____longjmp_chk, @function
Packit 6c4009
	.usepv	____longjmp_chk, std
Packit 6c4009
Packit 6c4009
	cfi_startproc
Packit 6c4009
____longjmp_chk:
Packit 6c4009
	ldgp    gp, 0(pv)
Packit 6c4009
#ifdef PROF
Packit 6c4009
	.set noat
Packit 6c4009
	lda     AT, _mcount
Packit 6c4009
	jsr     AT, (AT), _mcount
Packit 6c4009
	.set at
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	ldq     s2, JB_PC*8(a0)
Packit 6c4009
	mov	a0, s0
Packit 6c4009
	ldq     fp, JB_FP*8(a0)
Packit 6c4009
	mov     a1, s1
Packit 6c4009
	ldq     s3, JB_SP*8(a0)
Packit 6c4009
	cmoveq  s1, 1, s1
Packit 6c4009
Packit 6c4009
#ifdef PTR_DEMANGLE
Packit 6c4009
	PTR_DEMANGLE(s2, t1)
Packit 6c4009
	PTR_DEMANGLE2(s3, t1)
Packit 6c4009
	PTR_DEMANGLE2(fp, t1)
Packit 6c4009
#endif
Packit 6c4009
	/* ??? While this is a proper test for detecting a longjmp to an
Packit 6c4009
	   invalid frame within any given stack, the main thread stack is
Packit 6c4009
	   located *below* almost everything in the address space.  Which
Packit 6c4009
	   means that the test at Lfail vs the signal stack will almost
Packit 6c4009
	   certainly never pass.  We ought bounds check top and bottom of
Packit 6c4009
	   the current thread's stack.  */
Packit 6c4009
	cmpule	s3, sp, t1
Packit 6c4009
	bne	t1, $Lfail
Packit 6c4009
Packit 6c4009
	.align	4
Packit 6c4009
$Lok:
Packit 6c4009
	mov	s0, a0
Packit 6c4009
	mov	s1, v0
Packit 6c4009
	mov	s3, t0
Packit 6c4009
	mov	s2, ra
Packit 6c4009
	cfi_remember_state
Packit 6c4009
	cfi_def_cfa(a0, 0)
Packit 6c4009
	cfi_register(sp, t0)
Packit 6c4009
	cfi_offset(s0, JB_S0*8)
Packit 6c4009
	cfi_offset(s1, JB_S1*8)
Packit 6c4009
	cfi_offset(s2, JB_S2*8)
Packit 6c4009
	cfi_offset(s3, JB_S3*8)
Packit 6c4009
	cfi_offset(s4, JB_S4*8)
Packit 6c4009
	cfi_offset(s5, JB_S5*8)
Packit 6c4009
	cfi_offset(s3, JB_S3*8)
Packit 6c4009
	cfi_offset($f2, JB_F2*8)
Packit 6c4009
	cfi_offset($f3, JB_F3*8)
Packit 6c4009
	cfi_offset($f4, JB_F4*8)
Packit 6c4009
	cfi_offset($f5, JB_F5*8)
Packit 6c4009
	cfi_offset($f6, JB_F6*8)
Packit 6c4009
	cfi_offset($f7, JB_F7*8)
Packit 6c4009
	cfi_offset($f8, JB_F8*8)
Packit 6c4009
	cfi_offset($f9, JB_F9*8)
Packit 6c4009
	ldq	s0, JB_S0*8(a0)
Packit 6c4009
	ldq	s1, JB_S1*8(a0)
Packit 6c4009
	ldq	s2, JB_S2*8(a0)
Packit 6c4009
	ldq	s3, JB_S3*8(a0)
Packit 6c4009
	ldq	s4, JB_S4*8(a0)
Packit 6c4009
	ldq	s5, JB_S5*8(a0)
Packit 6c4009
	ldt     $f2, JB_F2*8(a0)
Packit 6c4009
	ldt     $f3, JB_F3*8(a0)
Packit 6c4009
	ldt     $f4, JB_F4*8(a0)
Packit 6c4009
	ldt     $f5, JB_F5*8(a0)
Packit 6c4009
	ldt     $f6, JB_F6*8(a0)
Packit 6c4009
	ldt     $f7, JB_F7*8(a0)
Packit 6c4009
	ldt     $f8, JB_F8*8(a0)
Packit 6c4009
	ldt     $f9, JB_F9*8(a0)
Packit 6c4009
	mov     t0, sp
Packit 6c4009
	ret
Packit 6c4009
Packit 6c4009
	.align	4
Packit 6c4009
$Lfail:
Packit 6c4009
	cfi_restore_state
Packit 6c4009
	lda	v0, __NR_sigaltstack
Packit 6c4009
	lda	a0, 0
Packit 6c4009
	lda	a1, -32(sp)
Packit 6c4009
	lda	sp, -32(sp)
Packit 6c4009
	cfi_adjust_cfa_offset(32)
Packit 6c4009
	callsys
Packit 6c4009
	ldq	t0, 0(sp)	/* ss_sp */
Packit 6c4009
	ldl	t1, 8(sp)	/* ss_flags */
Packit 6c4009
	ldq	t2, 16(sp)	/* ss_size */
Packit 6c4009
	lda	sp, 32(sp)
Packit 6c4009
	cfi_adjust_cfa_offset(-32)
Packit 6c4009
Packit 6c4009
	/* Without working sigaltstack we cannot perform the test.  */
Packit 6c4009
	bne	a3, $Lok
Packit 6c4009
Packit 6c4009
	addq	t0, t2, t0	/* t0 = ss_sp + ss_size */
Packit 6c4009
	subq	t0, s3, t0	/* t0 = (ss_sp + ss_size) - new_sp */
Packit 6c4009
	cmpule	t2, t0, t0	/* t0 = (t0 >= ss_size) */
Packit 6c4009
	and	t0, t1, t0	/* t0 = (t0 >= ss_size) & (ss_flags & SS_ONSTACK) */
Packit 6c4009
	bne	t0, $Lok
Packit 6c4009
Packit 6c4009
	ldah	a0, longjmp_msg(gp)	!gprelhigh
Packit 6c4009
	lda	a0, longjmp_msg(a0)	!gprellow
Packit 6c4009
#ifdef PIC
Packit 6c4009
	jsr	ra, HIDDEN_JUMPTARGET(__fortify_fail)
Packit 6c4009
#else
Packit 6c4009
	bsr	ra, HIDDEN_JUMPTARGET(__fortify_fail)	!samegp
Packit 6c4009
#endif
Packit 6c4009
	bugchk
Packit 6c4009
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	____longjmp_chk, .-____longjmp_chk