#include "ntsdp.h" #if defined(TARGET_i386) #include "86reg.h" #endif #include extern ULONG pageSize; #ifdef KERNEL extern PVOID NtsdCurrentEThread; extern DBGKD_GET_VERSION vs; #endif #define SAVE_EBP(f) f.Reserved[0] #define TRAP_TSS(f) f.Reserved[1] #define TRAP_EDITED(f) f.Reserved[1] #define SAVE_TRAP(f) f.Reserved[2] #if defined(TARGET_i386) || defined(CHICAGO) #define MachineType IMAGE_FILE_MACHINE_I386 #elif defined(TARGET_MIPS) #define MachineType IMAGE_FILE_MACHINE_R4000 #elif defined(TARGET_ALPHA) #define MachineType IMAGE_FILE_MACHINE_ALPHA #elif defined(TARGET_PPC) #define MachineType IMAGE_FILE_MACHINE_POWERPC #else #error( "unknown target machine" ); #endif VOID bangReload( IN PUCHAR args ); LPVOID SwFunctionTableAccess( HANDLE hProcess, DWORD AddrBase ) { #if defined(TARGET_i386) || defined(CHICAGO) return (LPVOID)FindFpoDataForModule( AddrBase ); #else static IMAGE_RUNTIME_FUNCTION_ENTRY irfe; PIMAGE_FUNCTION_ENTRY pife = SymFunctionTableAccess( hProcess, AddrBase ); if (pife) { irfe.BeginAddress = pife->StartingAddress; irfe.EndAddress = pife->EndingAddress; irfe.ExceptionHandler = 0; irfe.HandlerData = 0; irfe.PrologEndAddress = pife->EndOfPrologue; return &irfe; } else { return NULL; } #endif } DWORD SwTranslateAddress( HANDLE hProcess, HANDLE hThread, LPADDRESS lpaddress ) { // // don't support 16bit stacks // return 0; } BOOL SwReadMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead ) { #ifdef KERNEL BOOLEAN fSuccess; DWORD BytesRead; NTSTATUS Status; if ((LONG)lpNumberOfBytesRead == -1) { Status = DbgKdReadControlSpace( NtsdCurrentProcessor, (PVOID)lpBaseAddress, lpBuffer, nSize, &BytesRead ); fSuccess = Status == STATUS_SUCCESS; } else { fSuccess = (BOOLEAN)NT_SUCCESS(DbgKdReadVirtualMemory( (PVOID)lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead) ); } return fSuccess; #else ULONG cTotalBytesRead = 0; ULONG cBytesRead; ULONG readcount; PUCHAR pBufSource; BOOLEAN fSuccess; DWORD addr; DWORD bias; pBufSource = (PUCHAR)lpBaseAddress; do { // // do not perform reads across page boundaries. // calculate bytes to read in present page in readcount. // readcount = min(nSize - cTotalBytesRead, pageSize - ((ULONG)pBufSource & (pageSize - 1))); fSuccess = ReadProcessMemory(hProcess, pBufSource, lpBuffer, readcount, &cBytesRead); // update total bytes read and new address for next read if (fSuccess) { cTotalBytesRead += cBytesRead; pBufSource += cBytesRead; (PUCHAR)lpBuffer += cBytesRead; } } while (fSuccess && cTotalBytesRead < nSize); if (lpNumberOfBytesRead) { *lpNumberOfBytesRead = cTotalBytesRead; } return TRUE; #endif } DWORD SwGetModuleBase( HANDLE hProcess, DWORD Address ) { PIMAGE_INFO pImage = pProcessCurrent->pImageHead; while (pImage) { if ((Address >= (DWORD)pImage->lpBaseOfImage) && (Address < (DWORD)((DWORD)pImage->lpBaseOfImage+pImage->dwSizeOfImage))) { return (DWORD)pImage->lpBaseOfImage; } pImage = pImage->pImageNext; } return 0; } #ifdef KERNEL void EnsureModLoadedForAddress( DWORD Address ) { CHAR Buffer[11]; if (!SwGetModuleBase(0, Address)) { sprintf(Buffer, "0x%08x", Address); bangReload(Buffer); } } #endif DWORD StackTrace( ULONG FramePointer, ULONG StackPointer, ULONG InstructionPointer, LPSTACKFRAME StackFrames, ULONG NumFrames, ULONG ExtThread ) { CONTEXT Context; PCONTEXT RegContext; STACKFRAME VirtualFrame; DWORD i; #ifdef KERNEL RegContext = GetRegContext(); #else RegContext = &RegisterContext; #endif Context = *RegContext; // // lets start clean // ZeroMemory( StackFrames, sizeof(STACKFRAME)*NumFrames ); ZeroMemory( &VirtualFrame, sizeof(STACKFRAME) ); #ifdef KERNEL if (vs.KeUserCallbackDispatcher == 0) { // // if debugger was initialized at boot, usermode addresses // were not available. Try it now: // DbgKdGetVersion( &vs ); } VirtualFrame.KdHelp.Thread = ExtThread ? ExtThread : (DWORD)NtsdCurrentEThread; VirtualFrame.KdHelp.KiCallUserMode = vs.KiCallUserMode; VirtualFrame.KdHelp.ThCallbackStack = vs.ThCallbackStack; VirtualFrame.KdHelp.NextCallback = vs.NextCallback; VirtualFrame.KdHelp.KeUserCallbackDispatcher = vs.KeUserCallbackDispatcher; VirtualFrame.KdHelp.FramePointer = vs.FramePointer; #endif // // setup the program counter // #if defined(TARGET_i386) VirtualFrame.AddrPC.Mode = AddrModeFlat; VirtualFrame.AddrPC.Segment = (WORD)X86GetRegValue(REGCS); if (!InstructionPointer) { VirtualFrame.AddrPC.Offset = (ULONG)X86GetRegValue(REGEIP); } else { VirtualFrame.AddrPC.Offset = InstructionPointer; } // // setup the frame pointer // VirtualFrame.AddrFrame.Mode = AddrModeFlat; VirtualFrame.AddrFrame.Segment = (WORD)X86GetRegValue(REGSS); if (!FramePointer) { VirtualFrame.AddrFrame.Offset = (ULONG)X86GetRegValue(REGEBP); } else { VirtualFrame.AddrFrame.Offset = FramePointer; } // // setup the stack pointer // VirtualFrame.AddrStack.Mode = AddrModeFlat; VirtualFrame.AddrStack.Segment = (WORD)X86GetRegValue(REGSS); if (!StackPointer) { VirtualFrame.AddrStack.Offset = (ULONG)X86GetRegValue(REGESP); } else { VirtualFrame.AddrStack.Offset = StackPointer; } #endif #if defined (TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC) if (InstructionPointer) { VirtualFrame.AddrPC.Offset = InstructionPointer; VirtualFrame.AddrPC.Mode = AddrModeFlat; } // // setup the stack pointer // if (StackPointer) { VirtualFrame.AddrStack.Offset = StackPointer; VirtualFrame.AddrStack.Mode = AddrModeFlat; } if (FramePointer) { VirtualFrame.AddrFrame.Offset = FramePointer; VirtualFrame.AddrFrame.Mode = AddrModeFlat; } #endif for (i=0; ihProcess, #ifdef KERNEL (HANDLE)DefaultProcessor, #else pProcessCurrent->pThreadCurrent->hThread, #endif &VirtualFrame, &Context, SwReadMemory, SwFunctionTableAccess, SwGetModuleBase, SwTranslateAddress )) { break; } StackFrames[i] = VirtualFrame; } return i; } VOID DoStackTrace( ULONG FramePointer, ULONG StackPointer, ULONG InstructionPointer, ULONG NumFrames, ULONG TraceType ) { LPSTACKFRAME StackFrames; DWORD FrameCount; DWORD i; DWORD displacement; CHAR symbuf[512]; USHORT StdCallArgs; if (NumFrames == 0) { NumFrames = 20; } StackFrames = malloc( sizeof(STACKFRAME) * NumFrames ); if (!StackFrames) { dprintf( "could not allocate memory for stack trace\n" ); return; } FrameCount = StackTrace( FramePointer, StackPointer, InstructionPointer, StackFrames, NumFrames, 0 ); if (FrameCount == 0) { dprintf( "could not fetch any stack frames\n" ); return; } #if defined(TARGET_i386) dprintf( "ChildEBP RetAddr" ); if (TraceType) { dprintf(" Args to Child"); } dprintf("\n"); #else if (TraceType==1) { dprintf("\nCallee-SP Arguments to Callee Call Site\n\n"); } else { dprintf("\nCallee-SP Return-RA Call Site\n\n"); } #endif for (i=0; i 0) { dprintf( "%08x %08x %08x ", StackFrames[i].Params[0], StackFrames[i].Params[1], StackFrames[i].Params[2] ); } if (*symbuf) { dprintf( "%s", symbuf ); if (displacement) { dprintf("+"); } } if (displacement) { dprintf("0x%x", displacement); } if (TraceType == 2 && !StackFrames[i].FuncTableEntry) { if (StdCallArgs != 0xffff) { dprintf(" [Stdcall: %d]", StdCallArgs); } } else if (TraceType == 2 && StackFrames[i].FuncTableEntry) { PFPO_DATA pFpoData = (PFPO_DATA)StackFrames[i].FuncTableEntry; switch (pFpoData->cbFrame) { case FRAME_FPO: if (pFpoData->fHasSEH) { dprintf("(FPO: [SEH])"); } else { dprintf(" (FPO:"); if (pFpoData->fUseBP) { dprintf(" [EBP 0x%08x]", SAVE_EBP(StackFrames[i])); } dprintf(" [%d,%d,%d])", pFpoData->cdwParams, pFpoData->cdwLocals, pFpoData->cbRegs); } break; case FRAME_NONFPO: dprintf("(FPO: [Non-Fpo]" ); break; #ifdef KERNEL case FRAME_TRAP: dprintf(" (FPO: [%d,%d] TrapFrame%s @ %08lx)", pFpoData->cdwParams, pFpoData->cdwLocals, TRAP_EDITED(StackFrames[i]) ? "" : "-EDITED", SAVE_TRAP(StackFrames[i]) ); break; case FRAME_TSS: dprintf(" (FPO: TaskGate %lx:0)", TRAP_TSS(StackFrames[i])); break; #endif default: dprintf("(UKNOWN FPO TYPE)"); break; } } dprintf( "\n" ); #else if (TraceType == 1) { dprintf( " %08lx : ", StackFrames[i].AddrFrame.Offset ); } else { dprintf( " %08lx %08lx : ", StackFrames[i].AddrFrame.Offset, StackFrames[i].AddrReturn.Offset ); } if (TraceType == 1) { dprintf( "%08lx %08lx %08lx %08lx ", StackFrames[i].Params[0], StackFrames[i].Params[1], StackFrames[i].Params[2], StackFrames[i].Params[3] ); } dprintf( "%s", symbuf ); if (displacement) { dprintf("+0x%lx ", displacement); } dprintf( "\n" ); #endif } free( StackFrames ); return; } #ifdef KERNEL PVOID GetCallbackStackHead( PVOID Thread ) { KTHREAD Tcb; DWORD dwRead; NTSTATUS Status; Status = DbgKdReadVirtualMemory( Thread, &Tcb, sizeof(KTHREAD), &dwRead); if (NT_SUCCESS(Status)) { return Tcb.CallbackStack; } else { return 0; } } #endif