diff options
Diffstat (limited to 'sysdeps/mach/hurd/i386/____longjmp_chk.S')
-rw-r--r-- | sysdeps/mach/hurd/i386/____longjmp_chk.S | 70 |
1 files changed, 38 insertions, 32 deletions
diff --git a/sysdeps/mach/hurd/i386/____longjmp_chk.S b/sysdeps/mach/hurd/i386/____longjmp_chk.S index 819e5dc875..4d3a331728 100644 --- a/sysdeps/mach/hurd/i386/____longjmp_chk.S +++ b/sysdeps/mach/hurd/i386/____longjmp_chk.S @@ -17,6 +17,7 @@ #include <sysdep.h> #include <jmpbuf-offsets.h> +#include <tcb-offsets.h> #include <asm-syntax.h> #include <signal-defines.h> @@ -47,65 +48,70 @@ longjmp_msg: .text ENTRY (____longjmp_chk) - movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */ + movl 4(%esp), %eax /* User's jmp_buf in %eax. */ /* Save the return address now. */ - movl (JB_PC*4)(%ecx), %edx + movl (JB_PC*4)(%eax), %edx /* Get the stack pointer. */ - movl (JB_SP*4)(%ecx), %edi - cfi_undefined(%edi) + movl (JB_SP*4)(%eax), %ecx + cfi_undefined(%ecx) #ifdef PTR_DEMANGLE PTR_DEMANGLE (%edx) - PTR_DEMANGLE (%edi) + PTR_DEMANGLE (%ecx) #endif - cmpl %edi, %esp + movl %gs:SIGSTATE_OFFSET,%edi + + testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) + jnz .Lonstack + + /* We were on the main stack */ + + cmpl %ecx, %esp /* Jumping to a higher-address frame is always allowed. */ jbe .Lok - /* Passing here, we're either about to do something invalid, or we're - executing on an alternative signal stack. */ + /* Otherwise it's not allowed. */ + CALL_FAIL - /* TODO: need locking? */ - /* struct hurd_sigstate * _hurd_self_sigstate (void) */ - call HIDDEN_JUMPTARGET(_hurd_self_sigstate) - /* TODO: %eax and %eax->sigaltstack are always valid? */ +.Lonstack: + /* We were on the alternate stack, can't really easily check anything + since longjmp may get us out of the alternate stack. */ - testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%eax) - /* Fail if SS_ONSTACK is not set. */ - jz .Lfail + cmpl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ecx + jb .Loks /* We jump below the alternate stack, switch. */ - movl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%eax), %ebx - addl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%eax), %ebx - subl %edi, %ebx - cmpl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%eax), %ebx - /* TODO: comment this calculation. */ - jae .Lok + movl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ebx + addl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%edi), %ebx + cmpl %ebx, %ecx + jb .Lok /* We jump inside the alternate stack, do not switch. */ -.Lfail: CALL_FAIL + /* We jump above the alternate stack, switch. */ + +.Loks: /* We jump out of the alternate stack, clear SS_ONSTACK flag. */ + andl $~(SS_ONSTACK), (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) .Lok: /* We add unwind information for the target here. */ - cfi_def_cfa(%ecx, 0) + cfi_def_cfa(%eax, 0) cfi_register(%eip, %edx) - cfi_register(%esp, %edi) + cfi_register(%esp, %ecx) cfi_offset(%ebx, JB_BX*4) cfi_offset(%esi, JB_SI*4) cfi_offset(%edi, JB_DI*4) cfi_offset(%ebp, JB_BP*4) - - movl 8(%esp), %eax /* Second argument is return value. */ - movl %edi, %esp - /* Restore registers. */ - movl (JB_BX*4)(%ecx), %ebx - movl (JB_SI*4)(%ecx), %esi - movl (JB_DI*4)(%ecx), %edi - movl (JB_BP*4)(%ecx), %ebp + movl (JB_BX*4)(%eax), %ebx + movl (JB_SI*4)(%eax), %esi + movl (JB_DI*4)(%eax), %edi + movl (JB_BP*4)(%eax), %ebp cfi_restore(%ebx) cfi_restore(%esi) cfi_restore(%edi) cfi_restore(%ebp) + movl 8(%esp), %eax /* Second argument is return value. */ + movl %ecx, %esp + /* Jump to saved PC. */ jmp *%edx END (____longjmp_chk) |