1/* Copyright (C) 2009-2022 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 <sigaltstack-offsets.h>
19
20 .section .rodata.str1.8,"aMS",@progbits,1
21 .align 8
22.LC0:
23 .string "longjmp causes uninitialized stack frame"
24
25 .section .sdata,"aws",@progbits
26 .align 8
27 .type longjmp_msg,@object
28longjmp_msg:
29 data8 .LC0
30 .size longjmp_msg, .-longjmp_msg
31
32#define __longjmp ____longjmp_chk
33
34/* We use 32 bytes (rather than sizeof(stack_t)) so that we keep the stack
35 properly aligned. But we still want a sanity check to make sure 32 is
36 actually enough. */
37#define STACK_SPACE ((sizeSS + 31) & -32)
38
39/* Check the stack pointer held in the jumpbuf. Make sure it's in either the
40 current stack (r12) or in the signal stack. */
41#define CHECK_RSP \
42 ld8 loc0 = [in0]; \
43 ;; \
44 /* First see if target stack is within current one. */ \
45 cmp.ltu p0, p8 = loc0, r12; \
46(p8) br.cond.dptk.many .Lok; \
47 \
48 /* Check if it's an alternative signal stack. */ \
49 mov out0 = r0; \
50 add out1 = -STACK_SPACE, r12; \
51 ;; \
52 mov r12 = out1; \
53 DO_CALL_VIA_BREAK (SYS_ify (sigaltstack)); \
54 ;; \
55 /* If the syscall failed, then assume it's OK. */ \
56 cmp.eq p8, p0 = -1, r10; \
57(p8) br.cond.spnt .Lok; \
58 /* Move stack_t into regs. */ \
59 add r14 = oSS_FLAGS, r12; /* ss_flags */ \
60 add r15 = oSS_SIZE, r12; /* ss_size */ \
61 ld8 r16 = [r12]; /* ss_sp */ \
62 ;; \
63 ld4 r17 = [r14]; /* ss_flags */ \
64 ld8 r18 = [r15]; /* ss_size */ \
65 ;; \
66 sub r19 = r16, r18; /* sp - size */ \
67 /* See if we're currently on the altstack. */ \
68 tbit.nz p0, p8 = r17, 0; /* SS_ONSTACK */ \
69(p8) br.cond.spnt .Lfail; \
70 /* Verify target is within alternative stack. */ \
71 cmp.gtu p7, p0 = loc0, r16; \
72(p7) br.cond.spnt .Lfail; \
73 ;; \
74 cmp.ltu p0, p8 = loc0, r19; \
75(p8) br.cond.sptk.many .Lok; \
76 ;; \
77 \
78 /* Still here? Abort! */ \
79.Lfail: \
80 add r12 = STACK_SPACE, r12; \
81 addl loc0 = @ltoffx(longjmp_msg#), r1;; \
82 ld8.mov loc0 = [loc0], longjmp_msg#;; \
83 ld8 out0 = [loc0]; \
84 br.call.sptk.many b0 = HIDDEN_JUMPTARGET(__fortify_fail)#;; \
85.Lok: \
86 add r12 = STACK_SPACE, r12;
87
88#include "__longjmp.S"
89

source code of glibc/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S