Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

499 lines
12 KiB

#include "ntsdp.h"
#if defined(TARGET_i386)
#include "86reg.h"
#endif
#include <string.h>
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; i<NumFrames; i++) {
if (!StackWalk( MachineType,
pProcessCurrent->hProcess,
#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<FrameCount; i++) {
GetSymbolStdCall( StackFrames[i].AddrPC.Offset,
symbuf,
&displacement,
&StdCallArgs
);
#if defined(TARGET_i386)
dprintf( "%08x %08x ",
StackFrames[i].AddrFrame.Offset,
StackFrames[i].AddrReturn.Offset
);
if (TraceType > 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