windows-nt/Source/XPSP1/NT/base/crts/crtw32/misc/amd64/longjmp.asm
2020-09-26 16:20:57 +08:00

149 lines
4.9 KiB
NASM

title "Long Jump"
;++
;
; Copyright (c) 2000 Microsoft Corporation
;
; Module Name:
;
; longjmp.asm
;
; Abstract:
;
; This module implements the AMD64 specific routine to perform a long
; jump.
;
; N.B. This routine conditionally provides unsafe handling of long jump if
; structured exception handling is not being used. The determination
; is made based on the contents of the jump buffer.
;
; Author:
;
; David N. Cutler (davec) 4-Jul-2000
;
; Environment:
;
; Any mode.
;
;--
include ksamd64.inc
extern RtlUnwindEx:proc
subttl "Long Jump"
;++
;
; VOID
; longjmp (
; IN jmp_buf Jumpbuffer
; IN int ReturnValue
; )
;
; Routine Description:
;
; This function performs a long jump to the context specified by the
; jump buffer.
;
; Arguments:
;
; JumpBuffer (rcx) - Supplies the address of a jump buffer.
;
; ReturnValue (edx) - Supplies the value that is to be returned to the
; caller of set jump.
;
; Return Value:
;
; None.
;
;--
LjFrame struct
P1Home dq ? ; target frame home address
P2Home dq ? ; target IP home address
P3Home dq ? ; exception record address home address
P4Home dq ? ; return value home address
P5Home dq ? ; context record address parameter
P6Home dq ? ; history table address
Excode dd ? ; exception code
Flags dd ? ; exception flags
Associate dq ? ; associated exception record
Address dq ? ; exception address
Number dd ? ; number of parameters
Fill1 dd ? ; fill to qword boundary
Jmpbuf dq ? ; address of jump buffer
Fill2 dq ? ; align to 0 mod 16
Context db CONTEXT_FRAME_LENGTH dup (?) ; context record
Fill3 dq ? ; align to 8 mod 16
LjFrame ends
NESTED_ENTRY longjmp, _TEXT$00
alloc_stack (sizeof LjFrame) ; allocate stack frame
END_PROLOGUE
test rdx, rdx ; test if return value nonzero
jnz short LJ10 ; if nz, return value not zero
inc rdx ; set nonzero return value
LJ10: xor r10, r10 ; generate zero value
cmp JbFrame[rcx], r10 ; check for safe/unsafe long jump
jne LJ20 ; if ne, safe long jump
;
; Provide unsafe handling of long jump.
;
mov rax, rdx ; set return value
mov rbx, JbRbx[rcx] ; restore nonvolatile integer registers
mov rsi, JbRsi[rcx] ;
mov rdi, JbRdi[rcx] ;
mov r12, JbR12[rcx] ;
mov r13, JbR13[rcx] ;
mov r14, JbR14[rcx] ;
mov r15, JbR15[rcx] ;
movdqa xmm6, JbXmm6[rcx] ; save nonvolatile floating registers
movdqa xmm7, JbXmm7[rcx] ;
movdqa xmm8, JbXmm8[rcx] ;
movdqa xmm9, JbXmm9[rcx] ;
movdqa xmm10, JbXmm10[rcx] ;
movdqa xmm11, JbXmm11[rcx] ;
movdqa xmm12, JbXmm12[rcx] ;
movdqa xmm13, JbXmm13[rcx] ;
movdqa xmm14, JbXmm14[rcx] ;
movdqa xmm15, JbXmm15[rcx] ;
mov rdx, JbRip[rcx] ; get return address
mov rbp, JbRbp[rcx] ; set frame pointer
mov rsp, JbRsp[rcx] ; set stack pointer
jmp rdx ; jump back to set jump site
;
; Provide safe handling of long jump.
;
; An exception record is constructed that contains a long jump status
; code and the first exception information parameter is a pointer to
; the jump buffer.
;
LJ20: mov LjFrame.Excode[rsp], STATUS_LONGJUMP ; set exception code
mov LjFrame.Flags[rsp], r10d ; zero exception flags
mov LjFrame.Associate[rsp], r10 ; zero associated record address
mov LjFrame.Address[rsp], r10 ; zero exception address
mov LjFrame.P6Home[rsp], r10 ; set address of history table
inc r10d ; set number of parameters
mov LjFrame.Number[rsp], r10d ;
mov LjFrame.Jmpbuf[rsp], rcx ; set jump buffer address
lea rax, LjFrame.Context[rsp] ; set address of context record
mov LjFrame.P5Home[rsp], rax ;
mov r9, rdx ; set return value
lea r8, LjFrame.Excode[rsp] ; set address of exception record
mov rdx, JbRip[rcx] ; set target IP
mov rcx, JbFrame[rcx] ; set target frame
call RtlUnwindEx ; unwind to set jump target
jmp short LJ20 ;
NESTED_END longjmp, _TEXT$00
end