1/* Copyright (C) 1992-2021 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
4   The GNU C Library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8
9   The GNU C Library is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with the GNU C Library.  If not, see
16   <https://www.gnu.org/licenses/>.  */
17
18#include <sysdep.h>
19#include <jmpbuf-offsets.h>
20
21
22	.section .rodata.str1.1,"aMS",@progbits,1
23	.type   longjmp_msg,@object
24longjmp_msg:
25	.string "longjmp causes uninitialized stack frame"
26	.size   longjmp_msg, .-longjmp_msg
27
28
29/* Jump to the position specified by ENV, causing the
30   setjmp call there to return VAL, or 1 if VAL is 0.
31   void __longjmp (__jmp_buf env, int val).  */
32	.text
33	.align	4
34	.globl	____longjmp_chk
35	.type	____longjmp_chk, @function
36	.usepv	____longjmp_chk, std
37
38	cfi_startproc
39____longjmp_chk:
40	ldgp    gp, 0(pv)
41#ifdef PROF
42	.set noat
43	lda     AT, _mcount
44	jsr     AT, (AT), _mcount
45	.set at
46#endif
47
48	ldq     s2, JB_PC*8(a0)
49	mov	a0, s0
50	ldq     fp, JB_FP*8(a0)
51	mov     a1, s1
52	ldq     s3, JB_SP*8(a0)
53	cmoveq  s1, 1, s1
54
55#ifdef PTR_DEMANGLE
56	PTR_DEMANGLE(s2, t1)
57	PTR_DEMANGLE2(s3, t1)
58	PTR_DEMANGLE2(fp, t1)
59#endif
60	/* ??? While this is a proper test for detecting a longjmp to an
61	   invalid frame within any given stack, the main thread stack is
62	   located *below* almost everything in the address space.  Which
63	   means that the test at Lfail vs the signal stack will almost
64	   certainly never pass.  We ought bounds check top and bottom of
65	   the current thread's stack.  */
66	cmpule	s3, sp, t1
67	bne	t1, $Lfail
68
69	.align	4
70$Lok:
71	mov	s0, a0
72	mov	s1, v0
73	mov	s3, t0
74	mov	s2, ra
75	cfi_remember_state
76	cfi_def_cfa(a0, 0)
77	cfi_register(sp, t0)
78	cfi_offset(s0, JB_S0*8)
79	cfi_offset(s1, JB_S1*8)
80	cfi_offset(s2, JB_S2*8)
81	cfi_offset(s3, JB_S3*8)
82	cfi_offset(s4, JB_S4*8)
83	cfi_offset(s5, JB_S5*8)
84	cfi_offset(s3, JB_S3*8)
85	cfi_offset($f2, JB_F2*8)
86	cfi_offset($f3, JB_F3*8)
87	cfi_offset($f4, JB_F4*8)
88	cfi_offset($f5, JB_F5*8)
89	cfi_offset($f6, JB_F6*8)
90	cfi_offset($f7, JB_F7*8)
91	cfi_offset($f8, JB_F8*8)
92	cfi_offset($f9, JB_F9*8)
93	ldq	s0, JB_S0*8(a0)
94	ldq	s1, JB_S1*8(a0)
95	ldq	s2, JB_S2*8(a0)
96	ldq	s3, JB_S3*8(a0)
97	ldq	s4, JB_S4*8(a0)
98	ldq	s5, JB_S5*8(a0)
99	ldt     $f2, JB_F2*8(a0)
100	ldt     $f3, JB_F3*8(a0)
101	ldt     $f4, JB_F4*8(a0)
102	ldt     $f5, JB_F5*8(a0)
103	ldt     $f6, JB_F6*8(a0)
104	ldt     $f7, JB_F7*8(a0)
105	ldt     $f8, JB_F8*8(a0)
106	ldt     $f9, JB_F9*8(a0)
107	mov     t0, sp
108	ret
109
110	.align	4
111$Lfail:
112	cfi_restore_state
113	lda	v0, __NR_sigaltstack
114	lda	a0, 0
115	lda	a1, -32(sp)
116	lda	sp, -32(sp)
117	cfi_adjust_cfa_offset(32)
118	callsys
119	ldq	t0, 0(sp)	/* ss_sp */
120	ldl	t1, 8(sp)	/* ss_flags */
121	ldq	t2, 16(sp)	/* ss_size */
122	lda	sp, 32(sp)
123	cfi_adjust_cfa_offset(-32)
124
125	/* Without working sigaltstack we cannot perform the test.  */
126	bne	a3, $Lok
127
128	addq	t0, t2, t0	/* t0 = ss_sp + ss_size */
129	subq	t0, s3, t0	/* t0 = (ss_sp + ss_size) - new_sp */
130	cmpule	t2, t0, t0	/* t0 = (t0 >= ss_size) */
131	and	t0, t1, t0	/* t0 = (t0 >= ss_size) & (ss_flags & SS_ONSTACK) */
132	bne	t0, $Lok
133
134	ldah	a0, longjmp_msg(gp)	!gprelhigh
135	lda	a0, longjmp_msg(a0)	!gprellow
136#ifdef PIC
137	jsr	ra, HIDDEN_JUMPTARGET(__fortify_fail)
138#else
139	bsr	ra, HIDDEN_JUMPTARGET(__fortify_fail)	!samegp
140#endif
141	bugchk
142
143	cfi_endproc
144	.size	____longjmp_chk, .-____longjmp_chk
145