⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trap.s

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 S
📖 第 1 页 / 共 4 页
字号:
    lea ebx, [esp+SIZEOF_EXCEPTION_RECORD]
    mov [ebx], edx
    mov [ebx+4], esi
    mov [ebx+8], edi

NoParams:

    /* Set the record in ECX and check if this was V86 */
    mov ecx, esp
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jz SetPreviousMode

    /* Set V86 mode */
    mov eax, 0xFFFF
    jmp MaskMode

SetPreviousMode:

    /* Get the caller's CS */
    mov eax, [ebp+KTRAP_FRAME_CS]

MaskMode:
    /* Check if it was user-mode or kernel-mode */
    and eax, MODE_MASK

    /* Dispatch the exception */
    push 1
    push eax
    push ebp
    push 0
    push ecx
    call _KiDispatchException@20

    /* End the trap */
    mov esp, ebp
    jmp _Kei386EoiHelper@0
.endfunc

.func DispatchNoParam
_DispatchNoParam:
    /* Call the common dispatcher */
    xor ecx, ecx
    call _CommonDispatchException
.endfunc

.func DispatchOneParam
_DispatchOneParam:
    /* Call the common dispatcher */
    xor edx, edx
    mov ecx, 1
    call _CommonDispatchException
.endfunc

.func DispatchTwoParam
_DispatchTwoParam:
    /* Call the common dispatcher */
    xor edx, edx
    mov ecx, 2
    call _CommonDispatchException
.endfunc

/* HARDWARE TRAP HANDLERS ****************************************************/

.func KiFixupFrame
_KiFixupFrame:

    /* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */
    UNHANDLED_PATH
.endfunc

.func KiTrap0
TRAP_FIXUPS kit0_a, kit0_t, DoFixupV86, DoNotFixupAbios
_KiTrap0:
    /* Push error code */
    push 0

    /* Enter trap */
    TRAP_PROLOG kit0_a, kit0_t

    /* Check for V86 */
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86Int0

    /* Check if the frame was from kernelmode */
    test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
    jz SendException

    /* Check the old mode */
    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
    jne VdmCheck

SendException:
    /* Re-enable interrupts for user-mode and send the exception */
    sti
    mov eax, STATUS_INTEGER_DIVIDE_BY_ZERO
    mov ebx, [ebp+KTRAP_FRAME_EIP]
    jmp _DispatchNoParam

VdmCheck:
    /* Check if this is a VDM process */
    mov ebx, PCR[KPCR_CURRENT_THREAD]
    mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
    jz SendException

    /* We don't support this yet! */
V86Int0:
    /* FIXME: TODO */
    UNHANDLED_PATH
.endfunc

.func KiTrap1
TRAP_FIXUPS kit1_a, kit1_t, DoFixupV86, DoNotFixupAbios
_KiTrap1:
    /* Push error code */
    push 0

    /* Enter trap */
    TRAP_PROLOG kit1_a, kit1_t

    /* Check for V86 */
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86Int1

    /* Check if the frame was from kernelmode */
    test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
    jz PrepInt1

    /* Check the old mode */
    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
    jne V86Int1

EnableInterrupts:
    /* Enable interrupts for user-mode */
    sti

PrepInt1:
    /* Prepare the exception */
    and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAGS_TF
    mov ebx, [ebp+KTRAP_FRAME_EIP]
    mov eax, STATUS_SINGLE_STEP
    jmp _DispatchNoParam

V86Int1:
    /* Check if this is a VDM process */
    mov ebx, PCR[KPCR_CURRENT_THREAD]
    mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
    jz EnableInterrupts

    /* We don't support VDM! */
    UNHANDLED_PATH
.endfunc

.globl _KiTrap2
.func KiTrap2
_KiTrap2:

    /* FIXME: This is an NMI, nothing like a normal exception */
    mov eax, 2
    jmp _KiSystemFatalException
.endfunc

.func KiTrap3
TRAP_FIXUPS kit3_a, kit3_t, DoFixupV86, DoNotFixupAbios
_KiTrap3:
    /* Push error code */
    push 0

    /* Enter trap */
    TRAP_PROLOG kit3_a, kit3_t

    /* Set status code */
    mov eax, 0 //STATUS_SUCCESS

    /* Check for V86 */
PrepareInt3:
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86Int3

    /* Check if the frame was from kernelmode */
    test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
    jz PrepInt3

    /* Check the old mode */
    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
    jne V86Int3

EnableInterrupts3:
    /* Enable interrupts for user-mode */
    sti

PrepInt3:

    /* Prepare the exception */
    mov esi, ecx
    mov edi, edx
    mov edx, eax

    /* Setup EIP, NTSTATUS and parameter count, then dispatch */
    mov ebx, [ebp+KTRAP_FRAME_EIP]
    dec ebx
    mov ecx, 3
    mov eax, STATUS_BREAKPOINT
    call _CommonDispatchException

V86Int3:
    /* Check if this is a VDM process */
    mov ebx, PCR[KPCR_CURRENT_THREAD]
    mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
    jz EnableInterrupts3

    /* We don't support VDM! */
    UNHANDLED_PATH
.endfunc

.func KiTrap4
TRAP_FIXUPS kit4_a, kit4_t, DoFixupV86, DoNotFixupAbios
_KiTrap4:
    /* Push error code */
    push 0

    /* Enter trap */
    TRAP_PROLOG kit4_a, kit4_t

    /* Check for V86 */
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86Int4

    /* Check if the frame was from kernelmode */
    test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
    jz SendException4

    /* Check the old mode */
    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
    jne VdmCheck4

SendException4:
    /* Re-enable interrupts for user-mode and send the exception */
    sti
    mov eax, STATUS_INTEGER_OVERFLOW
    mov ebx, [ebp+KTRAP_FRAME_EIP]
    dec ebx
    jmp _DispatchNoParam

VdmCheck4:
    /* Check if this is a VDM process */
    mov ebx, PCR[KPCR_CURRENT_THREAD]
    mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
    jz SendException4

    /* We don't support this yet! */
V86Int4:
    UNHANDLED_PATH
.endfunc

.func KiTrap5
TRAP_FIXUPS kit5_a, kit5_t, DoFixupV86, DoNotFixupAbios
_KiTrap5:
    /* Push error code */
    push 0

    /* Enter trap */
    TRAP_PROLOG kit5_a, kit5_t

    /* Check for V86 */
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86Int5

    /* Check if the frame was from kernelmode */
    test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
    jnz CheckMode

    /* It did, and this should never happen */
    mov eax, 5
    jmp _KiSystemFatalException

    /* Check the old mode */
CheckMode:
    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
    jne VdmCheck5

    /* Re-enable interrupts for user-mode and send the exception */
SendException5:
    sti
    mov eax, STATUS_ARRAY_BOUNDS_EXCEEDED
    mov ebx, [ebp+KTRAP_FRAME_EIP]
    jmp _DispatchNoParam

VdmCheck5:
    /* Check if this is a VDM process */
    mov ebx, PCR[KPCR_CURRENT_THREAD]
    mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
    jz SendException5

    /* We don't support this yet! */
V86Int5:
    UNHANDLED_PATH
.endfunc

.func KiTrap6
TRAP_FIXUPS kit6_a, kit6_t, DoFixupV86, DoNotFixupAbios
_KiTrap6:

    /* It this a V86 GPF? */
    test dword ptr [esp+8], EFLAGS_V86_MASK
    jz NotV86UD

    /* Enter V86 Trap */
    V86_TRAP_PROLOG kit6_a, kit6_v

    /* Not yet supported (Invalid OPCODE from V86) */
    UNHANDLED_PATH

NotV86UD:
    /* Push error code */
    push 0

    /* Enter trap */
    TRAP_PROLOG kit6_a, kit6_t

    /* Check if this happened in kernel mode */
    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
    jz KmodeOpcode

    /* Check for VDM */
    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
    jz UmodeOpcode

    /* Check if the process is vDM */
    mov ebx, PCR[KPCR_CURRENT_THREAD]
    mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
    jnz IsVdmOpcode

UmodeOpcode:
    /* Get EIP and enable interrupts at this point */
    mov esi, [ebp+KTRAP_FRAME_EIP]
    sti

    /* Set intruction prefix length */
    mov ecx, 4

    /* Setup a SEH frame */
    push ebp
    push OpcodeSEH
    push PCR[KPCR_EXCEPTION_LIST]
    mov PCR[KPCR_EXCEPTION_LIST], esp

OpcodeLoop:
    /* Get the instruction and check if it's LOCK */
    mov al, [esi]
    cmp al, 0xF0
    jz LockCrash

    /* Keep moving */
    add esi, 1
    loop OpcodeLoop

    /* Undo SEH frame */
    pop PCR[KPCR_EXCEPTION_LIST]
    add esp, 8

KmodeOpcode:

    /* Re-enable interrupts */
    sti

    /* Setup illegal instruction exception and dispatch it */
    mov ebx, [ebp+KTRAP_FRAME_EIP]
    mov eax, STATUS_ILLEGAL_INSTRUCTION
    jmp _DispatchNoParam

LockCrash:

    /* Undo SEH Frame */
    pop PCR[KPCR_EXCEPTION_LIST]
    add esp, 8

    /* Setup invalid lock exception and dispatch it */
    mov ebx, [ebp+KTRAP_FRAME_EIP]
    mov eax, STATUS_INVALID_LOCK_SEQUENCE
    jmp _DispatchNoParam

IsVdmOpcode:

    /* Unhandled yet */
    UNHANDLED_PATH

    /* Return to caller */
    jmp _Kei386EoiHelper@0

OpcodeSEH:

    /* Get SEH frame */
    mov esp, [esp+8]
    pop PCR[KPCR_EXCEPTION_LIST]
    add esp, 4
    pop ebp

    /* Check if this was user mode */
    test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
    jnz KmodeOpcode

    /* Do a bugcheck */
    push ebp
    push 0
    push 0
    push 0
    push 0
    push KMODE_EXCEPTION_NOT_HANDLED
    call _KeBugCheckWithTf@24
.endfunc

.func KiTrap7
TRAP_FIXUPS kit7_a, kit7_t, DoFixupV86, DoNotFixupAbios
_KiTrap7:
    /* Push error code */
    push 0

    /* Enter trap */
    TRAP_PROLOG kit7_a, kit7_t

    /* Get the current thread and stack */
StartTrapHandle:
    mov eax, PCR[KPCR_CURRENT_THREAD]
    mov ecx, [eax+KTHREAD_INITIAL_STACK]
    sub ecx, NPX_FRAME_LENGTH

    /* Check if emulation is enabled */
    test dword ptr [ecx+FN_CR0_NPX_STATE], CR0_EM
    jnz EmulationEnabled

CheckState:
    /* Check if the NPX state is loaded */
    cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
    mov ebx, cr0
    jz IsLoaded

    /* Remove flags */
    and ebx, ~(CR0_MP + CR0_TS + CR0_EM)
    mov cr0, ebx

    /* Check the NPX thread */
    mov edx, PCR[KPCR_NPX_THREAD]
    or edx, edx
    jz NoNpxThread

    /* Get the NPX Stack */
    mov esi, [edx+KTHREAD_INITIAL_STACK]
    sub esi, NPX_FRAME_LENGTH

    /* Check if we have FXSR and check which operand to use */
    test byte ptr _KeI386FxsrPresent, 1
    jz FnSave
    fxsave [esi]
    jmp AfterSave

FnSave:
    fnsave [esi]

AfterSave:
    /* Set the thread's state to dirty */
    mov byte ptr [edx+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED

NoNpxThread:
    /* Check if we have FXSR and choose which operand to use */
    test byte ptr _KeI386FxsrPresent, 1
    jz FrRestore
    fxrstor [ecx]
    jmp AfterRestore

FrRestore:
    frstor [ecx]

AfterRestore:
    /* Set state loaded */
    mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
    mov PCR[KPCR_NPX_THREAD], eax

    /* Enable interrupts to happen now */
    sti
    nop

    /* Check if CR0 needs to be reloaded due to a context switch */
    cmp dword ptr [ecx+FN_CR0_NPX_STATE], 0
    jz _Kei386EoiHelper@0

    /* We have to reload CR0... disable interrupts */
    cli

    /* Get CR0 and update it */
    mov ebx, cr0
    or ebx, [ecx+FN_CR0_NPX_STATE]
    mov cr0, ebx

    /* Restore interrupts and check if TS is back on */
    sti
    test bl, CR0_TS
    jz _Kei386EoiHelper@0

    /* Clear TS, and loop handling again */
    clts
    cli
    jmp StartTrapHandle

KernelNpx:

    /* Set delayed error */
    or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS

    /* Check if this happened during restore */
    cmp dword ptr [ebp+KTRAP_FRAME_EIP], offset FrRestore
    jnz UserNpx

    /* Skip instruction and dispatch the exception */
    add dword ptr [ebp+KTRAP_FRAME_EIP], 3
    jmp _Kei386EoiHelper@0

IsLoaded:
    /* Check if TS is set */
    test bl, CR0_TS
    jnz TsSetOnLoadedState

HandleNpxFault:
    /* Check if the trap came from V86 mode */
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86Npx

    /* Check if it came from kernel mode */
    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
    jz KernelNpx

    /* Check if it came from a VDM */
    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
    jne V86Npx

UserNpx:
    /* Get the current thread */
    mov eax, PCR[KPCR_CURRENT_THREAD]

    /* Check NPX state */
    cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED

    /* Get the NPX save area */
    mov ecx, [eax+KTHREAD_INITIAL_STACK]
    lea ecx, [ecx-NPX_FRAME_LENGTH]
    jz NoSaveRestore

HandleUserNpx:

    /* Set new CR0 */
    mov ebx, cr0
    and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
    mov cr0, ebx

    /* Check if we have FX support */
    test byte ptr _KeI386FxsrPresent, 1
    jz FnSave2

    /* Save the state */
    fxsave [ecx]
    jmp MakeCr0Dirty
FnSave2:
    fnsave [ecx]
    wait

MakeCr0Dirty:
    /* Make CR0 state not loaded */
    or ebx, NPX_STATE_NOT_LOADED
    or ebx, [ecx+FN_CR0_NPX_STATE]
    mov cr0, ebx

    /* Update NPX state */
    mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
    mov dword ptr PCR[KPCR_NPX_THREAD], 0

NoSaveRestore:
    /* Clear the TS bit and re-enable interrupts */
    and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
    sti

    /* Check if we have FX support */
    test byte ptr _KeI386FxsrPresent, 1
    jz FnError

    /* Get error offset, control and status words */
    mov ebx, [ecx+FX_ERROR_OFFSET]
    movzx eax, word ptr [ecx+FX_CONTROL_WORD]
    movzx edx, word ptr [ecx+FX_STATUS_WORD]

    /* Get the faulting opcode */
    mov esi, [ecx+FX_DATA_OFFSET]
    jmp CheckError

FnError:
    /* Get error offset, control and status words */
    mov ebx, [ecx+FP_ERROR_OFFSET]
    movzx eax, word ptr [ecx+FP_CONTROL_WORD]
    movzx edx, word ptr [ecx+FP_STATUS_WORD]

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -