149 lines
4.9 KiB
NASM
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
|