📄 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 free
void 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 + -