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 28ENTRY (__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 91END (__longjmp) 92