📄 gdbstub.c
字号:
/* Convert the hex array pointed to by Buffer into binary to be placed at Address */
/* Return a pointer to the character AFTER the last byte read from Buffer */
static PCHAR
GspHex2Mem(PCHAR Buffer,
PCHAR Address,
ULONG Count,
BOOLEAN MayFault)
{
Count = GspWriteMem(Address, Count, MayFault, GspHex2MemGetContent, Buffer);
return Buffer + 2 * Count;
}
static CHAR
GspWriteMemSafeGetContent(PVOID Context, ULONG Offset)
{
ASSERT(0 == Offset);
return *((PCHAR) Context);
}
static void
GspWriteMemSafe(PCHAR Address,
CHAR Ch)
{
GspWriteMem(Address, 1, TRUE, GspWriteMemSafeGetContent, &Ch);
}
/* This function takes the 386 exception vector and attempts to
translate this number into a unix compatible signal value */
ULONG
GspComputeSignal(NTSTATUS ExceptionCode)
{
ULONG SigVal;
switch (ExceptionCode)
{
case STATUS_INTEGER_DIVIDE_BY_ZERO:
SigVal = 8; /* divide by zero */
break;
case STATUS_SINGLE_STEP:
case STATUS_BREAKPOINT:
SigVal = 5; /* breakpoint */
break;
case STATUS_INTEGER_OVERFLOW:
case STATUS_ARRAY_BOUNDS_EXCEEDED:
SigVal = 16; /* bound instruction */
break;
case STATUS_ILLEGAL_INSTRUCTION:
SigVal = 4; /* Invalid opcode */
break;
case STATUS_STACK_OVERFLOW:
case STATUS_DATATYPE_MISALIGNMENT:
case STATUS_ACCESS_VIOLATION:
SigVal = 11; /* access violation */
break;
default:
SigVal = 7; /* "software generated" */
}
return SigVal;
}
/**********************************************/
/* WHILE WE FIND NICE HEX CHARS, BUILD A LONG */
/* RETURN NUMBER OF CHARS PROCESSED */
/**********************************************/
LONG
GspHex2Long(PCHAR *Address,
PLONG Value)
{
LONG NumChars = 0;
LONG Hex;
*Value = 0;
while (**Address)
{
Hex = HexValue(**Address);
if (Hex >= 0)
{
*Value = (*Value << 4) | Hex;
NumChars++;
}
else
{
break;
}
(*Address)++;
}
return NumChars;
}
VOID
GspLong2Hex(PCHAR *Address,
LONG Value)
{
LONG Save;
Save = (((Value >> 0) & 0xff) << 24) |
(((Value >> 8) & 0xff) << 16) |
(((Value >> 16) & 0xff) << 8) |
(((Value >> 24) & 0xff) << 0);
*Address = GspMem2Hex((PCHAR) &Save, *Address, 4, FALSE);
}
/*
* When coming from kernel mode, Esp is not stored in the trap frame.
* Instead, it was pointing to the location of the TrapFrame Esp member
* when the exception occured. When coming from user mode, Esp is just
* stored in the TrapFrame Esp member.
*/
static LONG
GspGetEspFromTrapFrame(PKTRAP_FRAME TrapFrame)
{
return KeGetPreviousMode() == KernelMode
? (LONG) &TrapFrame->HardwareEsp : (LONG)TrapFrame->HardwareEsp;
}
static VOID
GspGetRegisters(PCHAR Address,
PKTRAP_FRAME TrapFrame)
{
ULONG_PTR Value;
PULONG p;
ULONG i;
PETHREAD Thread;
ULONG_PTR *KernelStack;
if (NULL == GspDbgThread)
{
Thread = PsGetCurrentThread();
}
else
{
TrapFrame = GspDbgThread->Tcb.TrapFrame;
Thread = GspDbgThread;
}
if (Waiting == Thread->Tcb.State)
{
KernelStack = Thread->Tcb.KernelStack;
for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
{
switch(i)
{
case EBP:
Value = KernelStack[3];
break;
case EDI:
Value = KernelStack[4];
break;
case ESI:
Value = KernelStack[5];
break;
case EBX:
Value = KernelStack[6];
break;
case PC:
Value = KernelStack[7];
break;
case ESP:
Value = (ULONG_PTR) (KernelStack + 8);
break;
case CS:
Value = KGDT_R0_CODE;
break;
case DS:
Value = KGDT_R0_DATA;
break;
default:
Value = 0;
break;
}
Address = GspMem2Hex((PCHAR) &Value, Address, GspRegisters[i].Size,
FALSE);
}
}
else
{
for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
{
if (TrapFrame)
{
if (ESP == i)
{
Value = GspGetEspFromTrapFrame(TrapFrame);
}
else
{
p = (PULONG)((ULONG_PTR) TrapFrame +
GspRegisters[i].OffsetInTF);
Value = *p;
}
}
else if (i == PC)
{
/*
* This thread has not been sheduled yet so assume it
* is still in PsBeginThreadWithContextInternal().
*/
Value = (ULONG)KiThreadStartup;
}
else
{
Value = 0;
}
Address = GspMem2Hex((PCHAR) &Value, Address,
GspRegisters[i].Size, FALSE);
}
}
}
VOID
GspSetRegistersInTrapFrame(PCHAR Address,
PCONTEXT Context,
PKTRAP_FRAME TrapFrame)
{
ULONG Value;
PCHAR Buffer;
PULONG p;
ULONG i;
if (!TrapFrame)
{
return;
}
Buffer = Address;
for (i = 0; i < NUMREGS; i++)
{
if (GspRegisters[i].SetInContext)
{
p = (PULONG) ((ULONG_PTR) Context + GspRegisters[i].OffsetInContext);
}
else
{
p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
}
Value = 0;
Buffer = GspHex2Mem(Buffer, (PCHAR) &Value, GspRegisters[i].Size, FALSE);
*p = Value;
}
}
VOID
GspSetSingleRegisterInTrapFrame(PCHAR Address,
LONG Number,
PCONTEXT Context,
PKTRAP_FRAME TrapFrame)
{
ULONG Value;
PULONG p;
if (!TrapFrame)
{
return;
}
if (GspRegisters[Number].SetInContext)
{
p = (PULONG) ((ULONG_PTR) Context + GspRegisters[Number].OffsetInContext);
}
else
{
p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF);
}
Value = 0;
GspHex2Mem(Address, (PCHAR) &Value, GspRegisters[Number].Size, FALSE);
*p = Value;
}
BOOLEAN
GspFindThread(PCHAR Data,
PETHREAD *Thread)
{
PETHREAD ThreadInfo = NULL;
if (strcmp (Data, "-1") == 0)
{
/* All threads */
ThreadInfo = NULL;
}
else
{
ULONG uThreadId;
HANDLE ThreadId;
PCHAR ptr = &Data[0];
GspHex2Long(&ptr, (PLONG) &uThreadId);
ThreadId = (HANDLE)uThreadId;
if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &ThreadInfo)))
{
*Thread = NULL;
return FALSE;
}
}
*Thread = ThreadInfo;
return TRUE;
}
VOID
GspSetThread(PCHAR Request)
{
PETHREAD ThreadInfo;
PCHAR ptr = &Request[1];
switch (Request[0])
{
case 'c': /* Run thread */
if (GspFindThread(ptr, &ThreadInfo))
{
GspOutBuffer[0] = 'O';
GspOutBuffer[1] = 'K';
if (NULL != GspRunThread)
{
ObDereferenceObject(GspRunThread);
}
GspRunThread = ThreadInfo;
if (NULL != GspRunThread)
{
ObReferenceObject(GspRunThread);
}
}
else
{
GspOutBuffer[0] = 'E';
}
break;
case 'g': /* Debug thread */
if (GspFindThread(ptr, &ThreadInfo))
{
GspOutBuffer[0] = 'O';
GspOutBuffer[1] = 'K';
if (NULL != GspDbgThread)
{
ObDereferenceObject(GspDbgThread);
}
if (ThreadInfo == PsGetCurrentThread())
{
GspDbgThread = NULL;
ObDereferenceObject(ThreadInfo);
}
else
{
GspDbgThread = ThreadInfo;
}
}
else
{
GspOutBuffer[0] = 'E';
}
break;
default:
break;
}
}
VOID
GspQuery(PCHAR Request)
{
ULONG Value;
if (strncmp(Request, "C", 1) == 0)
{
PCHAR ptr = &GspOutBuffer[2];
/* Get current thread id */
GspOutBuffer[0] = 'Q';
GspOutBuffer[1] = 'C';
if (NULL != GspDbgThread)
{
Value = (ULONG) GspDbgThread->Cid.UniqueThread;
}
else
{
Value = (ULONG) PsGetCurrentThread()->Cid.UniqueThread;
}
GspLong2Hex(&ptr, Value);
}
else if (strncmp(Request, "fThreadInfo", 11) == 0)
{
PEPROCESS Process;
PLIST_ENTRY AThread, AProcess;
PCHAR ptr = &GspOutBuffer[1];
/* Get first thread id */
GspEnumThread = NULL;
AProcess = PsActiveProcessHead.Flink;
while(AProcess != &PsActiveProcessHead)
{
Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
AThread = Process->ThreadListHead.Flink;
if (AThread != &Process->ThreadListHead)
{
GspEnumThread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
ETHREAD, ThreadListEntry);
break;
}
AProcess = AProcess->Flink;
}
if(GspEnumThread != NULL)
{
GspOutBuffer[0] = 'm';
Value = (ULONG) GspEnumThread->Cid.UniqueThread;
GspLong2Hex(&ptr, Value);
}
else
{
/* FIXME - what to do here? This case should never happen though, there
should always be at least one thread on the system... */
/* GspOutBuffer[0] = 'l'; */
}
}
else if (strncmp(Request, "sThreadInfo", 11) == 0)
{
PEPROCESS Process;
PLIST_ENTRY AThread, AProcess;
PCHAR ptr = &GspOutBuffer[1];
/* Get next thread id */
if (GspEnumThread != NULL)
{
/* find the next thread */
Process = GspEnumThread->ThreadsProcess;
if(GspEnumThread->ThreadListEntry.Flink != &Process->ThreadListHead)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -