📄 mdarm.c
字号:
// Check for RaiseException call versus a CPU detected exception. // RaiseException just becomes a call to CaptureContext as a KPSL. // HandleExcepion sets the LSB of the callstack linkage but ObjectCall // does not. if (!(pexi->linkage & 1)) { DEBUGMSG(ZONE_SEH, (TEXT("Raising exception %x flags=%x args=%d pexi=%8.8lx\r\n"), pctx->R0, pctx->R1, pctx->R2, pexi)); er.ExceptionCode = pctx->R0; er.ExceptionFlags = pctx->R1; if (pctx->R3 && pctx->R2) { if (pctx->R2 > EXCEPTION_MAXIMUM_PARAMETERS) { er.ExceptionCode = STATUS_INVALID_PARAMETER; er.ExceptionFlags = EXCEPTION_NONCONTINUABLE; } else { memcpy(er.ExceptionInformation, (void*)pctx->R3, pctx->R2*sizeof(DWORD)); er.NumberParameters = pctx->R2; } } id = -1; } else { // CPU detected exception. Extract some additional information about // the cause of the exception from the EXCINFO (CALLSTACK) structure. // // The exception handling code uses bit 0 to indicate Thumb vs. ARM // execution. This bit is not set by the hardware on exceptions. Set // the bit here: // if ( ThumbMode ){ pctx->Pc |= 0x01; } addr = pexi->addr; id = pexi->id; pctx->Sp += pexi->lowSpBits + sizeof(CALLSTACK); fsr = pexi->fsr; if (((id == ID_DATA_ABORT) && ((fsr & FSR_STATUS) == FSR_TRANSLATION)) && AutoCommit(addr)) { pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1); goto continueExecution; } switch (id) { case ID_UNDEF_INSTR: er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION; if ( ThumbMode ){ FaultAddr = pctx->Pc & ~0x01; if ( *(PUSHORT)FaultAddr == THM_BREAKPOINT ){ er.ExceptionCode = STATUS_BREAKPOINT; er.ExceptionInformation[0] = *(PUSHORT)FaultAddr; } } else if ( (*(PULONG)pctx->Pc & 0x0fffffff) == BREAKPOINT ){ er.ExceptionCode = STATUS_BREAKPOINT; er.ExceptionInformation[0] = *(PULONG)pctx->Pc; } break; case ID_SWI_INSTR: er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION; break; case ID_DATA_ABORT: // Data page fault // // Determine load vs. store depending on whether ARM or Thumb // mode: if ( ThumbMode ){ ULONG Instr; FaultAddr = pctx->Pc & ~0x01; // Clear Thumb bit Instr = *(PUSHORT)FaultAddr; if ((Instr & 0xFE00) == 0x5600){ // Discontinuity in the Thumb instruction set: // LDRSB instruction does not have bit 11 set. er.ExceptionInformation[0] = 0; } else { // All other load instructions have bit 11 set. The // corresponding store instructions have bit 11 clear er.ExceptionInformation[0] = !(Instr & (1<<11)); } } else { FaultAddr = pctx->Pc; er.ExceptionInformation[0] = !((*(PULONG)FaultAddr) & (1<<20)); } switch(fsr & FSR_STATUS) { case FSR_TRANSLATION: case FSR_DOMAIN_ERROR: case FSR_PERMISSION: DEBUGMSG(ZONE_PAGING, (L"ExD: ID_DATA_ABORT\r\n")); goto doPageFault; case FSR_ALIGNMENT: er.ExceptionCode = STATUS_DATATYPE_MISALIGNMENT; break; default: er.ExceptionCode = 0xdfff0123; break; } break; case ID_PREFETCH_ABORT: // Code page fault addr = pctx->Pc; DEBUGMSG(ZONE_PAGING, (L"ExD: ID_PREFETCH_ABORT\r\n")); doPageFault: DEBUGMSG(ZONE_PAGING, (L"ExD: addr = %8.8lx\r\n",addr)); if (ProcessPageFault(er.ExceptionInformation[0], addr)) { pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1); DEBUGMSG(ZONE_PAGING, (L"ExD: continuing. lr = %8.8lx\r\n", pctx->Lr)); goto continueExecution; } er.ExceptionCode = STATUS_ACCESS_VIOLATION; er.ExceptionInformation[1] = addr; er.NumberParameters = 2; break; case ID_STACK_FAULT: // Stack overflow er.ExceptionCode = STATUS_STACK_OVERFLOW; er.ExceptionFlags = EXCEPTION_NONCONTINUABLE; break; } } if (er.ExceptionCode != STATUS_BREAKPOINT) { NKDbgPrintfW(L"%a: Thread=%8.8lx Proc=%8.8lx '%s'\r\n",IdStrings[id+1], pth, pCurProc, pCurProc->lpszProcName ? pCurProc->lpszProcName : L""); NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx RA=%8.8lx BVA=%8.8lx\r\n", pCurThread->aky, pctx->Pc, pctx->Lr, addr); if (UTlsPtr()[TLSSLOT_KERNEL] & TLSKERN_NOFAULT) { NKDbgPrintfW(L"TLSKERN_NOFAULT set... bypassing kernel debugger.\r\n"); } } // Unlink the EXCINFO structure from the threads call stack chain. pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1); // Invoke the kernel debugger to attempt to debug the exception before // letting the program resolve the condition via SEH. if (!UserDbgTrap(&er,pctx,FALSE) && ((UTlsPtr()[TLSSLOT_KERNEL] & TLSKERN_NOFAULT) || !KDTrap(&er, pctx, FALSE))) { if (er.ExceptionCode == STATUS_BREAKPOINT) { RETAILMSG(1, (TEXT("DEBUG_BREAK @%8.8lx MD=%2x Ignored.\r\n"), pctx->Pc, pctx->Psr & 0xFF)); pctx->Pc += ThumbMode ? 2 : 4; // skip over the BREAK instruction } else { bHandled = NKDispatchException(pth, &er, pctx); if (!bHandled) { if (!UserDbgTrap(&er, pctx, TRUE) && !KDTrap(&er, pctx, TRUE)) { // Terminate the process. RETAILMSG(1, (TEXT("\r\nUnhandled exception %8.8lx:\r\n"), er.ExceptionCode)); DumpFrame(pth, (PCPUCONTEXT)&pctx->Psr, id, addr, 0); if (InSysCall()) { OutputDebugStringW(L"Halting system\r\n"); for (;;) ; } else { if (!GET_DEAD(pth)) { SET_DEAD(pth); pctx->Pc = (ULONG)pExitThread; pctx->R0 = 0; RETAILMSG(1, (TEXT("Terminating thread %8.8lx\r\n"), pth)); } else { RETAILMSG(1, (TEXT("Can't terminate thread %8.8lx, sleeping forever\r\n"), pth)); SurrenderCritSecs(); Sleep(INFINITE); DEBUGCHK(0); // should never get here } } } }#if defined(THUMBSUPPORT) // // Update PSR based on ARM/Thumb continuation: // if ( pctx->Pc & 0x01 ){ pctx->Psr |= THUMB_STATE; } else { pctx->Psr &= ~THUMB_STATE; }#endif } } if ((id == ID_DATA_ABORT) || (id == ID_PREFETCH_ABORT)) GuardCommit(addr);continueExecution: // If returning from handling a stack overflow, reset the thread's stack overflow // flag. It would be good to free the tail of the stack at this time // so that the thread will stack fault again if the stack gets too big. But we // are currently using that stack page. if (id == ID_STACK_FAULT) CLEAR_STACKFAULT(pth); if (GET_DYING(pth) && !GET_DEAD(pth) && (pCurProc == pth->pOwnerProc)) { SET_DEAD(pth); CLEAR_USERBLOCK(pth); CLEAR_DEBUGWAIT(pth); pctx->Pc = (ULONG)pExitThread; pctx->R0 = 0;#if defined(THUMBSUPPORT) // // Update PSR based on ARM/Thumb continuation: // if ( pctx->Pc & 0x01 ){ pctx->Psr |= THUMB_STATE; } else { pctx->Psr &= ~THUMB_STATE; }#endif } }//// Page Table Entry from OEMAddressTable//typedef struct { DWORD dwVA; DWORD dwPA; DWORD dwSize;} PTE, *PPTE;//// The Physical to Virtual mapping table is supplied by OEM.//extern PTE OEMAddressTable[];PVOID Phys2Virt(DWORD pfn) { int i = 0; DWORD va; // Virtual Base Address of section DWORD pa; // Physical Base Address of section DWORD pau; // Physical Address Upper Bound of section DWORD pfnmb; // PFN rounded down to 1MB // // The end of the table is marked by an entry with a ZERO size. // while(OEMAddressTable[i].dwSize) { va = OEMAddressTable[i].dwVA & 0x1FF00000; pa = OEMAddressTable[i].dwPA & 0xFFF00000; pau = pa + (OEMAddressTable[i].dwSize << 20) - 1; pfnmb = pfn & 0xfff00000; if ((pfnmb >= pa) && (pfnmb <= pau)) return ((PVOID) ((pfn - pa) + va + 0x80000000)); i++; } DEBUGMSG(ZONE_PHYSMEM, (TEXT("Phys2Virt() : PFN (0x%08X) not found!\r\n"), pfn)); return NULL;}LPVOID VerifyAccess(LPVOID pvAddr, DWORD dwFlags, ACCESSKEY aky) { PSECTION pscn; MEMBLOCK *pmb; ulong entry; int i=0; if ((long)pvAddr >= 0) { if ((pscn = SectionTable[(ulong)pvAddr>>VA_SECTION]) && (pmb = (*pscn)[((ulong)pvAddr>>VA_BLOCK)&BLOCK_MASK]) && (pmb != RESERVED_BLOCK) && (pmb->alk & aky) && ((entry = pmb->aPages[((ulong)pvAddr>>VA_PAGE)&PAGE_MASK]) & PG_VALID_MASK) && (!(dwFlags & VERIFY_WRITE_FLAG) || ((entry&PG_PROTECTION) == PG_PROT_WRITE))) return Phys2Virt(PFNfromEntry(entry) | ((ulong)pvAddr & (PAGE_SIZE-1))); } else { // Kernel mode only address. If the "kernel mode OK" flag is set or if the // thread is running in kernel mode, allow the access. if (((dwFlags & VERIFY_KERNEL_OK) || (GetThreadMode(pCurThread) == KERNEL_MODE)) && (((ulong)pvAddr < 0xC0000000) || ((ulong)pvAddr >= 0xFFFD0000))) { // kernel data and page table territory... if(((ulong)pvAddr >= 0xFFFD0000) && ((ulong)pvAddr < 0xFFFD8000)) return pvAddr; if(((ulong)pvAddr >= 0xFFFF0000) && ((ulong)pvAddr < 0xFFFF1000)) return pvAddr; if(((ulong)pvAddr >= 0xFFFF2000) && ((ulong)pvAddr < 0xFFFF3000)) return pvAddr; if(((ulong)pvAddr >= 0xFFFF4000) && ((ulong)pvAddr < 0xFFFF5000)) return pvAddr; if(((ulong)pvAddr >= 0xFFFFC000) && ((ulong)pvAddr < 0xFFFFD000)) return pvAddr; // Need to check the OEM address map to see if the address we've been // handed is indeed mapped... while(OEMAddressTable[i].dwSize != 0) { if((OEMAddressTable[i].dwVA < (ulong)pvAddr) && ((ulong)pvAddr < (OEMAddressTable[i].dwVA + (OEMAddressTable[i].dwSize * 0x00100000)))) { return pvAddr; } i++; } } } return 0;}/* Machine dependent thread creation */#define STKALIGN 8#define STKMSK (STKALIGN-1)// normal thread stack: from top, TLS then args then freevoid MDCreateThread(PTHREAD pTh, LPVOID lpStack, DWORD cbStack, LPVOID lpBase, LPVOID lpStart, DWORD dwVMBase, BOOL kmode, ulong param) { PDWORD pTLS; if (!((ulong)lpStack>>VA_SECTION)) lpStack = (LPVOID)((ulong)lpStack + dwVMBase); pTh->dwStackBase = (DWORD)lpStack; // Leave room for arguments and TLS on the stack pTLS = (PDWORD)((PBYTE)lpStack + cbStack - TLS_MINIMUM_AVAILABLE*4); pTh->ctx.Sp = (ulong)pTLS; pTh->dwStackBound = pTh->ctx.Sp & ~(PAGE_SIZE-1); pTh->tlsPtr = pTLS; pTh->ctx.R0 = (ulong)lpStart; pTh->ctx.R1 = param; pTh->ctx.Lr = 4; pTh->ctx.Pc = (ULONG)lpBase; pTh->ctx.Psr = (kmode || bAllKMode) ? KERNEL_MODE : USER_MODE;#if defined(THUMBSUPPORT) if ( (pTh->ctx.Pc & 0x01) != 0 ){ pTh->ctx.Psr |= THUMB_STATE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -