📄 trap.s
字号:
/* Get the faulting opcode */
mov esi, [ecx+FP_DATA_OFFSET]
CheckError:
/* Mask exceptions */
and eax, 0x3F
not eax
and eax, edx
/* Check if what's left is invalid */
test al, 1
jz ValidNpxOpcode
/* Check if it was a stack fault */
test al, 64
jnz InvalidStack
/* Raise exception */
mov eax, STATUS_FLOAT_INVALID_OPERATION
jmp _DispatchOneParam
InvalidStack:
/* Raise exception */
mov eax, STATUS_FLOAT_STACK_CHECK
jmp _DispatchTwoParam
ValidNpxOpcode:
/* Check for divide by 0 */
test al, 4
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_DIVIDE_BY_ZERO
jmp _DispatchOneParam
1:
/* Check for denormal */
test al, 2
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_INVALID_OPERATION
jmp _DispatchOneParam
1:
/* Check for overflow */
test al, 8
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_OVERFLOW
jmp _DispatchOneParam
1:
/* Check for underflow */
test al, 16
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_UNDERFLOW
jmp _DispatchOneParam
1:
/* Check for precision fault */
test al, 32
jz UnexpectedNpx
/* Raise exception */
mov eax, STATUS_FLOAT_INEXACT_RESULT
jmp _DispatchOneParam
UnexpectedNpx:
/* Strange result, bugcheck the OS */
sti
push ebp
push 0
push 0
push eax
push 1
push TRAP_CAUSE_UNKNOWN
call _KeBugCheckWithTf@24
V86Npx:
/* Check if this is a VDM */
mov eax, PCR[KPCR_CURRENT_THREAD]
mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz HandleUserNpx
/* V86 NPX not handled */
UNHANDLED_PATH
EmulationEnabled:
/* Did this come from kernel-mode? */
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
jz CheckState
/* It came from user-mode, so this would only be valid inside a VDM */
/* Since we don't actually have VDMs in ROS, bugcheck. */
jmp UnexpectedNpx
TsSetOnLoadedState:
/* TS shouldn't be set, unless this we don't have a Math Processor */
test bl, CR0_MP
jnz BogusTrap
/* Strange that we got a trap at all, but ignore and continue */
clts
jmp _Kei386EoiHelper@0
BogusTrap:
/* Cause a bugcheck */
push 0
push 0
push ebx
push 2
push TRAP_CAUSE_UNKNOWN
call _KeBugCheckEx@20
.endfunc
.globl _KiTrap8
.func KiTrap8
_KiTrap8:
/* Can't really do too much */
mov eax, 8
jmp _KiSystemFatalException
.endfunc
.func KiTrap9
TRAP_FIXUPS kit9_a, kit9_t, DoFixupV86, DoNotFixupAbios
_KiTrap9:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG kit9_a, kit9_t
/* Enable interrupts and bugcheck */
sti
mov eax, 9
jmp _KiSystemFatalException
.endfunc
.func KiTrap10
TRAP_FIXUPS kita_a, kita_t, DoFixupV86, DoNotFixupAbios
_KiTrap10:
/* Enter trap */
TRAP_PROLOG kita_a, kita_t
/* Check for V86 */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz V86IntA
/* Check if the frame was from kernelmode */
test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz Fatal
V86IntA:
/* Check if OF was set during iretd */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAG_ZERO
sti
jz Fatal
/* It was, just mask it out */
and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAG_ZERO
jmp _Kei386EoiHelper@0
Fatal:
/* TSS failure for some other reason: crash */
mov eax, 10
jmp _KiSystemFatalException
.endfunc
.func KiTrap11
TRAP_FIXUPS kitb_a, kitb_t, DoFixupV86, DoNotFixupAbios
_KiTrap11:
/* Enter trap */
TRAP_PROLOG kitb_a, kitb_t
/* FIXME: ROS Doesn't handle segment faults yet */
mov eax, 11
jmp _KiSystemFatalException
.endfunc
.func KiTrap12
TRAP_FIXUPS kitc_a, kitc_t, DoFixupV86, DoNotFixupAbios
_KiTrap12:
/* Enter trap */
TRAP_PROLOG kitc_a, kitc_t
/* FIXME: ROS Doesn't handle stack faults yet */
mov eax, 12
jmp _KiSystemFatalException
.endfunc
.func KiTrapExceptHandler
_KiTrapExceptHandler:
/* Setup SEH handler frame */
mov esp, [esp+8]
pop PCR[KPCR_EXCEPTION_LIST]
add esp, 4
pop ebp
/* Check if the fault came from user mode */
test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jnz SetException
/* Kernel fault, bugcheck */
push ebp
push 0
push 0
push 0
push 0
push KMODE_EXCEPTION_NOT_HANDLED
call _KeBugCheckWithTf@24
.endfunc
.func KiTrap13
TRAP_FIXUPS kitd_a, kitd_t, DoFixupV86, DoNotFixupAbios
_KiTrap13:
/* It this a V86 GPF? */
test dword ptr [esp+12], EFLAGS_V86_MASK
jz NotV86
/* Enter V86 Trap */
V86_TRAP_PROLOG kitd_a, kitd_v
/* Make sure that this is a V86 process */
mov ecx, PCR[KPCR_CURRENT_THREAD]
mov ecx, [ecx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0
jnz RaiseIrql
/* Otherwise, something is very wrong, raise an exception */
sti
mov ebx, [ebp+KTRAP_FRAME_EIP]
mov esi, -1
mov eax, STATUS_ACCESS_VIOLATION
jmp _DispatchTwoParam
RaiseIrql:
/* Go to APC level */
mov ecx, APC_LEVEL
call @KfRaiseIrql@4
/* Save old IRQL and enable interrupts */
push eax
sti
/* Handle the opcode */
call _Ki386HandleOpcodeV86@0
/* Check if this was VDM */
test al, 0xFF
jnz NoReflect
/* FIXME: TODO */
UNHANDLED_PATH
NoReflect:
/* Lower IRQL and disable interrupts */
pop ecx
call @KfLowerIrql@4
cli
/* Check if this was a V86 trap */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jz NotV86Trap
/* Exit the V86 Trap */
V86_TRAP_EPILOG
NotV86Trap:
/* Either this wasn't V86, or it was, but an APC interrupted us */
jmp _Kei386EoiHelper@0
NotV86:
/* Enter trap */
TRAP_PROLOG kitd_a, kitd_t
/* Check if this was from kernel-mode */
test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jnz UserModeGpf
/* Check if we have a VDM alert */
cmp dword ptr PCR[KPCR_VDM_ALERT], 0
jnz VdmAlertGpf
/* Check for GPF during GPF */
mov eax, [ebp+KTRAP_FRAME_EIP]
cmp eax, offset CheckPrivilegedInstruction
jbe KmodeGpf
cmp eax, offset CheckPrivilegedInstruction2
/* FIXME: TODO */
UNHANDLED_PATH
/* Get the opcode and trap frame */
KmodeGpf:
mov eax, [ebp+KTRAP_FRAME_EIP]
mov eax, [eax]
mov edx, [ebp+KTRAP_FRAME_EBP]
/* We want to check if this was POP [DS/ES/FS/GS] */
add edx, KTRAP_FRAME_DS
cmp al, 0x1F
jz SegPopGpf
add edx, KTRAP_FRAME_ES - KTRAP_FRAME_DS
cmp al, 7
jz SegPopGpf
add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
cmp ax, 0xA10F
jz SegPopGpf
add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
cmp ax, 0xA90F
jz SegPopGpf
/* It isn't, was it IRETD? */
cmp al, 0xCF
jne NotIretGpf
/* Get error code */
lea edx, [ebp+KTRAP_FRAME_ESP]
mov ax, [ebp+KTRAP_FRAME_ERROR_CODE]
and ax, ~RPL_MASK
/* Get CS */
mov cx, word ptr [edx+4]
and cx, ~RPL_MASK
cmp cx, ax
jnz NotCsGpf
/* This should be a Ki386CallBios return */
mov eax, offset _Ki386BiosCallReturnAddress
cmp eax, [edx]
jne NotBiosGpf
mov eax, [edx+4]
cmp ax, KGDT_R0_CODE + RPL_MASK
jne NotBiosGpf
/* Jump to return address */
jmp _Ki386BiosCallReturnAddress
NotBiosGpf:
/* Check if the thread was in kernel mode */
mov ebx, PCR[KPCR_CURRENT_THREAD]
test byte ptr [ebx+KTHREAD_PREVIOUS_MODE], 0xFF
jz UserModeGpf
/* Set RPL_MASK for check below */
or word ptr [edx+4], RPL_MASK
NotCsGpf:
/* Check if the IRET goes to user-mode */
test dword ptr [edx+4], RPL_MASK
jz UserModeGpf
/* Setup trap frame to copy */
mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4
lea edx, [ebp+KTRAP_FRAME_ERROR_CODE]
TrapCopy:
/* Copy each field */
mov eax, [edx]
mov [edx+12], eax
sub edx, 4
loop TrapCopy
/* Enable interrupts and adjust stack */
sti
add esp, 12
add ebp, 12
/* Setup exception record */
mov ebx, [ebp+KTRAP_FRAME_EIP]
mov esi, [ebp+KTRAP_FRAME_ERROR_CODE]
and esi, 0xFFFF
mov eax, STATUS_ACCESS_VIOLATION
jmp _DispatchTwoParam
MsrCheck:
/* FIXME: Handle RDMSR/WRMSR */
UNHANDLED_PATH
NotIretGpf:
/* Check if this was an MSR opcode */
cmp al, 0xF
jz MsrCheck
/* Check if DS is Ring 3 */
cmp word ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
jz CheckEs
/* Otherwise, fix it up */
mov dword ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
jmp ExitGpfTrap
CheckEs:
/* Check if ES is Ring 3 */
cmp word ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
jz UserModeGpf
/* Otherwise, fix it up */
mov dword ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
jmp ExitGpfTrap
SegPopGpf:
/* Sanity check */
lea eax, [ebp+KTRAP_FRAME_ESP]
cmp edx, eax
jz HandleSegPop
int 3
/* Handle segment POP fault by setting it to 0 */
HandleSegPop:
xor eax, eax
mov dword ptr [edx], eax
ExitGpfTrap:
/* Do a trap exit */
TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoNotRestoreSegments, DoRestoreVolatiles, DoRestoreEverything
UserModeGpf:
/* If the previous mode was kernel, raise a fatal exception */
mov eax, 13
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz _KiSystemFatalException
/* Get the process and check which CS this came from */
mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jz CheckVdmGpf
/* Check if this is a VDM */
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jnz DispatchV86Gpf
/* Enable interrupts and check if we have an error code */
sti
cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
jnz SetException
jmp CheckPrivilegedInstruction
HandleSegPop2:
/* Update EIP (will be updated below again) */
add dword ptr [ebp+KTRAP_FRAME_EIP], 1
HandleEsPop:
/* Clear the segment, update EIP and ESP */
mov dword ptr [edx], 0
add dword ptr [ebp+KTRAP_FRAME_EIP], 1
add dword ptr [ebp+KTRAP_FRAME_ESP], 4
jmp _Kei386EoiHelper@0
CheckVdmGpf:
/* Check if this is a VDM */
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz CheckPrivilegedInstruction
/* Bring interrupts back */
sti
/* Check what kind of instruction this is */
mov eax, [ebp+KTRAP_FRAME_EIP]
mov eax, [eax]
/* FIXME: Check for BOP4 */
/* Check if this is POP ES */
mov edx, ebp
add edx, KTRAP_FRAME_ES
cmp al, 0x07
jz HandleEsPop
/* Check if this is POP FS */
add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
cmp ax, 0xA10F
jz HandleSegPop2
/* Check if this is POP GS */
add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
cmp ax, 0xA90F
jz HandleSegPop2
CheckPrivilegedInstruction:
/* Bring interrupts back */
sti
/* Setup a SEH handler */
push ebp
push offset _KiTrapExceptHandler
push PCR[KPCR_EXCEPTION_LIST]
mov PCR[KPCR_EXCEPTION_LIST], esp
/* Get EIP */
mov esi, [ebp+KTRAP_FRAME_EIP]
/* Setup loop count */
mov ecx, 15
InstLoop:
/* Save loop count */
push ecx
/* Get the instruction */
lods byte ptr [esi]
/* Now lookup in the prefix table */
mov ecx, 11
mov edi, offset _KiTrapPrefixTable
repnz scasb
/* Restore loop count */
pop ecx
/* If it's not a prefix byte, check other instructions */
jnz NotPrefixByte
/* FIXME */
UNHANDLED_PATH
NotPrefixByte:
/* FIXME: Check if it's a HLT */
/* Check if the instruction has two bytes */
cmp al, 0xF
jne CheckRing3Io
/* FIXME */
UNHANDLED_PATH
CheckRing3Io:
/* Get EFLAGS and IOPL */
mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
and ebx, 0x3000
shr ebx, 12
/* Check the CS's RPL mask */
mov ecx, [ebp+KTRAP_FRAME_CS]
and ecx, RPL_MASK
cmp ebx, ecx
jge NotIoViolation
CheckPrivilegedInstruction2:
/* Check if this is a CLI or STI */
cmp al, 0xFA
je IsPrivInstruction
cmp al, 0xFB
je IsPrivInstruction
/* Setup I/O table lookup */
mov ecx, 13
mov edi, offset _KiTrapIoTable
/* Loopup in the table */
repnz scasb
jnz NotIoViolation
/* FIXME: Check IOPM!!! */
IsPrivInstruction:
/* Cleanup the SEH frame */
pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8
/* Setup the exception */
mov ebx, [ebp+KTRAP_FRAME_EIP]
mov eax, STATUS_PRIVILEGED_INSTRUCTION
jmp _DispatchNoParam
NotIoViolation:
/* Cleanup the SEH frame */
pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8
SetException:
/* Setup the exception */
mov ebx, [ebp+KTRAP_FRAME_EIP]
mov esi, -1
mov eax, STATUS_ACCESS_VIOLATION
jmp _DispatchTwoParam
DispatchV86Gpf:
/* FIXME */
UNHANDLED_PATH
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -