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 <sysdep.h> |
19 | #include <jmpbuf-offsets.h> |
20 | |
21 | #define ENV(base,reg) [%base + (reg * 4)] |
22 | #define ST_FLUSH_WINDOWS 3 |
23 | |
24 | .section .rodata.str1.1,"aMS" ,@progbits,1 |
25 | .type longjmp_msg,@object |
26 | longjmp_msg: |
27 | .string "longjmp causes uninitialized stack frame" |
28 | .size longjmp_msg, .-longjmp_msg |
29 | |
30 | .text |
31 | ENTRY (____longjmp_chk) |
32 | ld ENV(o0,JB_SP), %g5 |
33 | #ifdef PTR_DEMANGLE |
34 | PTR_DEMANGLE (%g5, %g5, %g4) |
35 | #endif |
36 | |
37 | cmp %sp, %g5 |
38 | bleu .Lok_norestore |
39 | nop |
40 | |
41 | save %sp, -80, %sp |
42 | cfi_remember_state |
43 | cfi_def_cfa_register(%fp) |
44 | cfi_window_save |
45 | cfi_register(%o7, %i7) |
46 | |
47 | clr %o0 |
48 | add %sp, 64, %o1 |
49 | LOADSYSCALL(sigaltstack) |
50 | ta 0x10 |
51 | bcs .Lok |
52 | ld [%sp + 64 + 4], %o2 |
53 | andcc %o2, 0x1, %g0 |
54 | be .Lfail |
55 | ld [%sp + 64 + 0], %o0 |
56 | |
57 | ld [%sp + 64 + 8], %o1 |
58 | add %o0, %o1, %o0 |
59 | sub %o0, %g5, %o0 |
60 | cmp %o0, %o1 |
61 | bgeu .Lok |
62 | nop |
63 | |
64 | .Lfail: |
65 | #ifndef PIC |
66 | sethi %hi(longjmp_msg), %o0 |
67 | or %o0, %lo(longjmp_msg), %o0 |
68 | #else |
69 | SETUP_PIC_REG(l7) |
70 | sethi %gdop_hix22(longjmp_msg), %o0 |
71 | xor %o0, %gdop_lox10(longjmp_msg), %o0 |
72 | ld [%l7 + %o0], %o0, %gdop(longjmp_msg) |
73 | #endif |
74 | call HIDDEN_JUMPTARGET(__fortify_fail) |
75 | nop |
76 | |
77 | .Lok: |
78 | restore |
79 | cfi_restore_state |
80 | |
81 | .Lok_norestore: |
82 | ld ENV(o0,JB_FP), %g3 /* Cache target FP in register %g3. */ |
83 | #ifdef PTR_DEMANGLE |
84 | PTR_DEMANGLE2 (%g3, %g3, %g4) |
85 | #endif |
86 | |
87 | mov %o0, %g1 /* ENV in %g1 */ |
88 | orcc %o1, %g0, %g2 /* VAL in %g2 */ |
89 | be,a 0f /* Branch if zero; else skip delay slot. */ |
90 | mov 1, %g2 /* Delay slot only hit if zero: VAL = 1. */ |
91 | 0: |
92 | |
93 | save %sp, -96, %sp |
94 | /* |
95 | * Do a "flush register windows trap". The trap handler in the |
96 | * kernel writes all the register windows to their stack slots, and |
97 | * marks them all as invalid (needing to be sucked up from the |
98 | * stack when used). This ensures that all information needed to |
99 | * unwind to these callers is in memory, not in the register |
100 | * windows. |
101 | */ |
102 | ta ST_FLUSH_WINDOWS |
103 | #ifdef PTR_DEMANGLE |
104 | ld ENV(g1,JB_PC), %g1 /* Set return PC. */ |
105 | PTR_DEMANGLE2 (%i7, %g1, %g4) |
106 | #else |
107 | ld ENV(g1,JB_PC), %i7 /* Set return PC. */ |
108 | #endif |
109 | mov %g5, %fp |
110 | jmp %i7 + 8 |
111 | restore %g2, 0, %o0 /* Restore values from above register frame. */ |
112 | |
113 | END(____longjmp_chk) |
114 | |