📄 fault.c
字号:
jne short rsd20 jmp RunThread // redispatch the same thread// Switch to a new thread's process context.// Switching to a new thread. Update current process and address space// information. Edit the ring0 stack pointer in the TSS to point to the// new thread's register save area.//// (eax) = ptr to thread structurersd20: mov edi, eax // Save thread pointer mov esi, (THREAD)[eax].hTh // (esi) = thread handle push edi call SetCPUASID // Sets hCurProc for us! pop ecx // Clean up stack mov hCurThd, esi // set the current thread handle mov PtrCurThd, edi // and the current thread pointer mov ecx, [edi].tlsPtr // (ecx) = thread local storage ptr mov [KData].lpvTls, ecx // set TLS pointer cmp edi, g_CurFPUOwner jne SetTSBit clts jmp MuckWithFSBaseSetTSBit: mov eax, CR0 test eax, TS_MASK jnz MuckWithFSBase or eax, TS_MASK mov CR0, eaxMuckWithFSBase: mov edx, offset g_aGlobalDescriptorTable+KGDT_PCR sub ecx, FS_LIMIT+1 // (ecx) = ptr to NK_PCR base mov word ptr [edx+2], cx // set low word of FS base shr ecx, 16 mov byte ptr [edx+4], cl // set third byte of FS base mov byte ptr [edx+7], ch // set high byte of FS base lea ecx, [edi].ctx.TcxSs+4 // (ecx) = ptr to end of context save area mov [MainTSS].Esp0, ecx jmp RunThread // Run thread pointed to by edi// No threads ready to run. Call OEMIdle to shutdown the cpu.rsd50: cli cmp ticksleft, 0 je short skip_force_reched mov byte ptr ([KData].bResched), 1skip_force_reched: cmp word ptr ([KData].bResched), 1 je short DoReschedule call OEMIdle mov byte ptr ([KData].bResched), 1 jmp RescheduleDoReschedule: sti jmp Reschedule }}Naked CommonIntDispatch(){ _asm { cld mov eax, KGDT_R3_DATA mov ds, ax mov es, ax dec [KData].cNest jnz short cid20 // nested fault mov esp, offset KData-4 mov edi, PtrCurThdcid10:#ifdef CELOG push esi // save ESI mov eax, 80000000h // mark as ISR entry push eax // Arg 0, cNest + SYSINTR_xxx call CeLogInterrupt pop eax // cleanup the stack from the call pop esi // restore ESI#endif sti call esi cli#ifdef CELOG push eax // Save original SYSINTR return value. bswap eax // Reverse endian mov ah, [KData].cNest // Nesting level (0 = no nesting, -1 = nested once) neg ah // Nesting level (0 = no nesting, 1 = nested once) bswap eax // Reverse endian push eax // Arg 0, cNest + SYSINTR_xxx call CeLogInterrupt pop eax // cleanup the stack from the call pop eax // restore original SYSINTR value#endif test eax, eax jz short cid17 // SYSINTR_NOP: nothing more to do#ifdef NKPROF cmp eax, SYSINTR_PROFILE jne short cid13 call ProfilerHit jmp cid17 // Continue on our merry way...cid13:#endif cmp eax, SYSINTR_RESCHED je short cid15 lea ecx, [eax-SYSINTR_DEVICES] cmp ecx, SYSINTR_MAX_DEVICES jae short cid15 // force a reschedule for good measure// A device interrupt has been signaled. Set the appropriate bit in the pending// events mask and set the reschedule flag. The device event will be signaled// by the scheduler. mov eax, 1 shl eax, cl or [KData].aInfo[KINX_PENDEVENTS*4], eaxcid15: or [KData].bResched, 1 // must reschedulecid17: jmp RunThread// Nested exception. Create a fake thread structure on the stackcid20: push ds push es push fs push gs sub esp, THREAD_CONTEXT_OFFSET mov edi, esp // (edi) = ptr to fake thread struct jmp short cid10 }}// Continue thread execution.//// (edi) = ptr to Thread structureNaked RunThread(){ _asm { cli cmp word ptr ([KData].bResched), 1 jne short NotReschedule jmp RescheduleNotReschedule: inc [KData].cNest lea esp, [edi].ctx.TcxGs pop gs pop fs pop es pop ds popad add esp, 4 iretd cli hlt }}Naked PageFault(){ _asm { pushad mov ebx, OFFSET KData mov edi, cr2 test edi, edi js short pf50 // Address > 2GB, get out now dec [ebx].cNest // count kernel reentrancy level mov esi, esp // (esi) = original stack pointer jnz short pf10 lea esp, [ebx-4] // switch to kernel stack (&KData-4)// Process a page fault for the "user" address space (0 to 0x7FFFFFFF)//// (edi) = Faulting address// (ebx) = ptr to KData// (esi) = Original ESPpf10: cld // Need to do this since the page fault could have come from anywhere! cmp dword ptr ([KData].dwInDebugger), 0 // see if debugger active jne short pf20 // if so, skip turning on of interrupts sti // enable interruptspf20: push [esi+32] push edi call LowAddrSpacePageFault cli test eax, eax jz short pf40 // page not found in the Virtual memory tree cmp word ptr ([KData].bResched), 1 je short pf60 // must reschedule now inc [ebx].cNest // back out of kernel one level mov esp, esi // restore stack pointer popad add esp, 4 iretd// This one was not a good one! Jump to common fault handler//// (edi) = faulting addresspf40: inc [ebx].cNest // back out of kernel one level mov esp, esi // restore stack pointerpf50: mov ecx, edi // (ecx) = fault effective address mov esi, 0Eh jmp CommonFault// The reschedule flag was set and we are at the first nest level into the kernel// so we must reschedule now.pf60: mov edi, PtrCurThd // (edi) = ptr to current THREAD jmp Reschedule }}Naked GeneralFault(){ _asm { pushad xor ecx, ecx // (ecx) = 0 (fault effective address) mov esi, 13 jmp CommonFault }}Naked InvalidOpcode(void){ __asm { push eax pushad mov esi, 6 xor ecx, ecx // (ecx) = 0 (fault effective address) jmp CommonFault }}Naked ZeroDivide(void){ __asm { push eax pushad xor esi, esi // (esi) = 0 (divide by zero fault) xor ecx, ecx // (ecx) = 0 (fault effective address) jmp CommonFault }}const BYTE PosTable[256] = { 0,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1, 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1, 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1, 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1, 8,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1, 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1, 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1, 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1};void __declspec(naked) GetHighPos(DWORD foo) { _asm { mov ecx, dword ptr [esp + 4] push ebx lea ebx, PosTable mov dl, 0xff xor eax, eax mov al, cl xlatb test al, al jne res shr ecx, 8 add dl, 8 mov al, cl xlatb test al, al jne res shr ecx, 8 add dl, 8 mov al, cl xlatb test al, al jne res shr ecx, 8 add dl, 8 mov al, cl xlatb test al, al jne res mov al, 9res: add al, dl pop ebx ret }}Naked Int1Fault(void){ __asm { push eax // Save orig EAX as fake error code cmp word ptr [esp + 6], 0FFFFh // Is it an API call fault? je skip_debug // Yes - handle page fault first mov eax, [esp + 4] // (eax) = faulting EIP and dword ptr [esp + 12], not 0100h // Clear TF if set test byte ptr [esp + 8], 3 // Are we trying to SS ring 0? jz skip_debug // Yes - get out quick mov eax, dword ptr [esp] // Restore original EAX pushad mov esi, 1 xor ecx, ecx // (ecx) = 0 (fault effective address) jmp CommonFaultskip_debug: pop eax iretd }}Naked Int2Fault(void){ __asm { push eax // Fake error code pushad mov esi, 2 xor ecx, ecx // (ecx) = 0 (fault effective address) jmp CommonFault }}Naked Int3Fault(void){ __asm { dec dword ptr [esp] // Back up EIP push eax // Fake error code pushad mov esi, 3 xor ecx, ecx // (ecx) = 0 (fault effective address) jmp CommonFault }}PPAGETABLE LowAddrSpacePageFault(LPVOID pvAddr, DWORD flags){ PSECTION pscn; MEMBLOCK *pmb; ULONG entry; ACCESSKEY ReqKey; DWORD OldPTE = 0; DWORD OldPDE = 0; if (((pscn = SectionTable[(ulong)pvAddr >> VA_SECTION]) != 0) && ((pmb = (*pscn)[((ulong)pvAddr >> VA_BLOCK)&BLOCK_MASK]) != 0) && (pmb != RESERVED_BLOCK && (ReqKey = TestAccess(&pmb->alk, &CurAKey)) != 0) && ((entry = pmb->aPages[((ulong)pvAddr >> VA_PAGE) & PAGE_MASK]) & PG_VALID_MASK) && (!(flags&2) || (entry & (PG_WRITE_MASK | PG_WRITE_THRU_MASK)))) { PPAGETABLE pPageTable; ULONG ulDirFaultIdx; PDIRTYRANGE pDirtyRange; ULONG ulBlockIndex; PDWORD pDirEntry; // // ulDirFaultIdx is the index of the page directory corresponding to // the address which faulted. // ulDirFaultIdx = (ULONG)pvAddr / (ARRAY_SIZE(g_PageDir.PTE) * PAGE_SIZE); OldPDE = g_PageDir.PTE[ulDirFaultIdx]; if (ulDirFaultIdx < PDES_PER_SLOT) { // The fault occurred in the alias area, update the index to the // appropriate "real" entry. ulDirFaultIdx += PID_TO_PT_INDEX(pCurProc->procnum); } else { if (g_PageDir.PTE[ulDirFaultIdx] == 0 && g_ShadowPageDir.PTE[ulDirFaultIdx] != 0) g_PageDir.PTE[ulDirFaultIdx] = g_ShadowPageDir.PTE[ulDirFaultIdx];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -