1 | /* Copyright (C) 2001-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 | #include <tcb-offsets.h> |
21 | #include <asm-syntax.h> |
22 | |
23 | #include <signal-defines.h> |
24 | /* #include <signal.h> */ |
25 | #define SS_ONSTACK 1 |
26 | |
27 | .text |
28 | ENTRY (__longjmp) |
29 | movl 4(%esp), %eax /* User's jmp_buf in %eax. */ |
30 | |
31 | /* Save the return address now. */ |
32 | movl (JB_PC*4)(%eax), %edx |
33 | /* Get the stack pointer. */ |
34 | movl (JB_SP*4)(%eax), %ecx |
35 | cfi_undefined(%ecx) |
36 | #ifdef PTR_DEMANGLE |
37 | PTR_DEMANGLE (%edx) |
38 | PTR_DEMANGLE (%ecx) |
39 | #endif |
40 | |
41 | movw %ds, %si |
42 | movw %gs, %di |
43 | cmpw %si, %di |
44 | jz .Lok /* TLS not initialized yet */ |
45 | |
46 | movl %gs:SIGSTATE_OFFSET, %edi |
47 | testl %edi, %edi |
48 | jz .Lok /* sigstate not initialized yet */ |
49 | |
50 | testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) |
51 | jz .Lok |
52 | |
53 | /* We were on the alternate stack. */ |
54 | |
55 | cmpl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ecx |
56 | jb .Loks /* We jump below the alternate stack, switch. */ |
57 | |
58 | movl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ebx |
59 | addl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%edi), %ebx |
60 | cmpl %ebx, %ecx |
61 | jb .Lok /* We jump inside the alternate stack, do not switch. */ |
62 | |
63 | /* We jump above the alternate stack, switch. */ |
64 | |
65 | .Loks: /* We jump out of the alternate stack, clear SS_ONSTACK flag. */ |
66 | andl $~(SS_ONSTACK), (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) |
67 | |
68 | .Lok: /* We add unwind information for the target here. */ |
69 | cfi_def_cfa(%eax, 0) |
70 | cfi_register(%eip, %edx) |
71 | cfi_register(%esp, %ecx) |
72 | cfi_offset(%ebx, JB_BX*4) |
73 | cfi_offset(%esi, JB_SI*4) |
74 | cfi_offset(%edi, JB_DI*4) |
75 | cfi_offset(%ebp, JB_BP*4) |
76 | /* Restore registers. */ |
77 | movl (JB_BX*4)(%eax), %ebx |
78 | movl (JB_SI*4)(%eax), %esi |
79 | movl (JB_DI*4)(%eax), %edi |
80 | movl (JB_BP*4)(%eax), %ebp |
81 | cfi_restore(%ebx) |
82 | cfi_restore(%esi) |
83 | cfi_restore(%edi) |
84 | cfi_restore(%ebp) |
85 | |
86 | movl 8(%esp), %eax /* Second argument is return value. */ |
87 | movl %ecx, %esp |
88 | |
89 | /* Jump to saved PC. */ |
90 | jmp *%edx |
91 | END (__longjmp) |
92 | |