📄 gdbstub.c
字号:
GspEnumThread = CONTAINING_RECORD(GspEnumThread->ThreadListEntry.Flink,
ETHREAD, ThreadListEntry);
}
else
{
PETHREAD Thread = NULL;
AProcess = Process->ActiveProcessLinks.Flink;
while(AProcess != &PsActiveProcessHead)
{
Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
AThread = Process->ThreadListHead.Flink;
if (AThread != &Process->ThreadListHead)
{
Thread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
ETHREAD, ThreadListEntry);
break;
}
AProcess = AProcess->Flink;
}
GspEnumThread = Thread;
}
if (GspEnumThread != NULL)
{
/* return the ID */
GspOutBuffer[0] = 'm';
Value = (ULONG) GspEnumThread->Cid.UniqueThread;
GspLong2Hex(&ptr, Value);
}
else
{
GspOutBuffer[0] = 'l';
}
}
else
{
GspOutBuffer[0] = 'l';
}
}
else if (strncmp(Request, "ThreadExtraInfo", 15) == 0)
{
PETHREAD ThreadInfo;
/* Get thread information */
if (GspFindThread(Request + 16, &ThreadInfo))
{
char Buffer[64];
PEPROCESS Proc;
Proc = (PEPROCESS) ThreadInfo->ThreadsProcess;
Buffer[0] = '\0';
if (NULL != Proc )
{
sprintf(Buffer, "%s [%d:0x%x], ", Proc->ImageFileName,
(int) Proc->UniqueProcessId,
(int) ThreadInfo->Cid.UniqueThread);
}
strcpy(Buffer + strlen(Buffer),
GspThreadStates[ThreadInfo->Tcb.State]);
ObDereferenceObject(ThreadInfo);
GspMem2Hex(Buffer, &GspOutBuffer[0], strlen(Buffer), FALSE);
}
}
}
VOID
GspQueryThreadStatus(PCHAR Request)
{
PETHREAD ThreadInfo;
PCHAR ptr = &Request[0];
if (GspFindThread(ptr, &ThreadInfo))
{
ObDereferenceObject(ThreadInfo);
GspOutBuffer[0] = 'O';
GspOutBuffer[1] = 'K';
GspOutBuffer[2] = '\0';
}
else
{
GspOutBuffer[0] = 'E';
GspOutBuffer[1] = '\0';
}
}
#define DR7_L0 0x00000001 /* Local breakpoint 0 enable */
#define DR7_G0 0x00000002 /* Global breakpoint 0 enable */
#define DR7_L1 0x00000004 /* Local breakpoint 1 enable */
#define DR7_G1 0x00000008 /* Global breakpoint 1 enable */
#define DR7_L2 0x00000010 /* Local breakpoint 2 enable */
#define DR7_G2 0x00000020 /* Global breakpoint 2 enable */
#define DR7_L3 0x00000040 /* Local breakpoint 3 enable */
#define DR7_G3 0x00000080 /* Global breakpoint 3 enable */
#define DR7_LE 0x00000100 /* Local exact breakpoint enable (old) */
#define DR7_GE 0x00000200 /* Global exact breakpoint enable (old) */
#define DR7_GD 0x00002000 /* General detect enable */
#define DR7_TYPE0_MASK 0x00030000 /* Breakpoint 0 condition */
#define DR7_LEN0_MASK 0x000c0000 /* Breakpoint 0 length */
#define DR7_TYPE1_MASK 0x00300000 /* Breakpoint 1 condition */
#define DR7_LEN1_MASK 0x00c00000 /* Breakpoint 1 length */
#define DR7_TYPE2_MASK 0x03000000 /* Breakpoint 2 condition */
#define DR7_LEN2_MASK 0x0c000000 /* Breakpoint 2 length */
#define DR7_TYPE3_MASK 0x30000000 /* Breakpoint 3 condition */
#define DR7_LEN3_MASK 0xc0000000 /* Breakpoint 3 length */
#define DR7_GLOBAL_ENABLE(Bp) (2 << (2 * (Bp)))
#define DR7_TYPE(Bp, Type) ((Type) << (16 + 4 * (Bp)))
#define DR7_LEN(Bp, Len) ((Len) << (18 + 4 * (Bp)))
#define I386_BP_TYPE_EXECUTE 0
#define I386_BP_TYPE_DATA_WRITE 1
#define I386_BP_TYPE_DATA_READWRITE 3
#define I386_OPCODE_INT3 0xcc
#define GDB_ZTYPE_MEMORY_BREAKPOINT 0
#define GDB_ZTYPE_HARDWARE_BREAKPOINT 1
#define GDB_ZTYPE_WRITE_WATCHPOINT 2
#define GDB_ZTYPE_READ_WATCHPOINT 3
#define GDB_ZTYPE_ACCESS_WATCHPOINT 4
typedef struct _GSPHWBREAKPOINT
{
ULONG Type;
ULONG_PTR Address;
ULONG Length;
} GSPHWBREAKPOINT;
#define MAX_HW_BREAKPOINTS 4
static unsigned GspHwBreakpointCount = 0;
static GSPHWBREAKPOINT GspHwBreakpoints[MAX_HW_BREAKPOINTS];
typedef struct _GSPSWBREAKPOINT
{
ULONG_PTR Address;
CHAR PrevContent;
BOOLEAN Active;
} GSPSWBREAKPOINT;
#define MAX_SW_BREAKPOINTS 64
static unsigned GspSwBreakpointCount = 0;
static GSPSWBREAKPOINT GspSwBreakpoints[MAX_SW_BREAKPOINTS];
static void
GspSetHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
{
DPRINT("GspSetHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address, Length);
if (GDB_ZTYPE_READ_WATCHPOINT == Type)
{
DPRINT1("Read watchpoint not supported\n");
strcpy(GspOutBuffer, "E22");
}
else if (GDB_ZTYPE_HARDWARE_BREAKPOINT == Type && 1 != Length)
{
DPRINT1("Invalid length %lu for hardware breakpoint\n", Length);
strcpy(GspOutBuffer, "E22");
}
else if (1 != Length && 2 != Length && 4 != Length)
{
DPRINT1("Invalid length %lu for GDB Z type %lu\n", Length, Type);
strcpy(GspOutBuffer, "E22");
}
else if (0 != (Address & (Length - 1)))
{
DPRINT1("Invalid alignment for address 0x%p and length %d\n",
Address, Length);
strcpy(GspOutBuffer, "E22");
}
else if (MAX_HW_BREAKPOINTS == GspHwBreakpointCount)
{
DPRINT1("Trying to set too many hardware breakpoints\n");
strcpy(GspOutBuffer, "E22");
}
else
{
DPRINT("Stored at index %u\n", GspHwBreakpointCount);
GspHwBreakpoints[GspHwBreakpointCount].Type = Type;
GspHwBreakpoints[GspHwBreakpointCount].Address = Address;
GspHwBreakpoints[GspHwBreakpointCount].Length = Length;
GspHwBreakpointCount++;
strcpy(GspOutBuffer, "OK");
}
}
static void
GspRemoveHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
{
unsigned Index;
DPRINT("GspRemoveHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address, Length);
for (Index = 0; Index < GspHwBreakpointCount; Index++)
{
if (GspHwBreakpoints[Index].Type == Type &&
GspHwBreakpoints[Index].Address == Address &&
GspHwBreakpoints[Index].Length == Length)
{
DPRINT("Found match at index %u\n", Index);
if (Index + 1 < GspHwBreakpointCount)
{
memmove(GspHwBreakpoints + Index,
GspHwBreakpoints + (Index + 1),
(GspHwBreakpointCount - Index - 1) *
sizeof(GSPHWBREAKPOINT));
}
GspHwBreakpointCount--;
strcpy(GspOutBuffer, "OK");
return;
}
}
DPRINT1("Not found\n");
strcpy(GspOutBuffer, "E22");
}
static void
GspSetSwBreakpoint(ULONG_PTR Address)
{
DPRINT("GspSetSwBreakpoint(0x%p)\n", Address);
if (MAX_SW_BREAKPOINTS == GspSwBreakpointCount)
{
DPRINT1("Trying to set too many software breakpoints\n");
strcpy(GspOutBuffer, "E22");
}
else
{
DPRINT("Stored at index %u\n", GspSwBreakpointCount);
GspSwBreakpoints[GspSwBreakpointCount].Address = Address;
GspSwBreakpoints[GspSwBreakpointCount].Active = FALSE;
GspSwBreakpointCount++;
strcpy(GspOutBuffer, "OK");
}
}
static void
GspRemoveSwBreakpoint(ULONG_PTR Address)
{
unsigned Index;
DPRINT("GspRemoveSwBreakpoint(0x%p)\n", Address);
for (Index = 0; Index < GspSwBreakpointCount; Index++)
{
if (GspSwBreakpoints[Index].Address == Address)
{
DPRINT("Found match at index %u\n", Index);
ASSERT(! GspSwBreakpoints[Index].Active);
if (Index + 1 < GspSwBreakpointCount)
{
memmove(GspSwBreakpoints + Index,
GspSwBreakpoints + (Index + 1),
(GspSwBreakpointCount - Index - 1) *
sizeof(GSPSWBREAKPOINT));
}
GspSwBreakpointCount--;
strcpy(GspOutBuffer, "OK");
return;
}
}
DPRINT1("Not found\n");
strcpy(GspOutBuffer, "E22");
}
static void
GspLoadHwBreakpoint(PKTRAP_FRAME TrapFrame,
unsigned BpIndex,
ULONG_PTR Address,
ULONG Length,
ULONG Type)
{
DPRINT("GspLoadHwBreakpoint(0x%p, %d, 0x%p, %d)\n", TrapFrame, BpIndex,
Address, Type);
/* Set the DR7_Gx bit to globally enable the breakpoint */
TrapFrame->Dr7 |= DR7_GLOBAL_ENABLE(BpIndex) |
DR7_LEN(BpIndex, Length) |
DR7_TYPE(BpIndex, Type);
switch (BpIndex)
{
case 0:
DPRINT("Setting DR0 to 0x%p\n", Address);
TrapFrame->Dr0 = Address;
break;
case 1:
DPRINT("Setting DR1 to 0x%p\n", Address);
TrapFrame->Dr1 = Address;
break;
case 2:
DPRINT("Setting DR2 to 0x%p\n", Address);
TrapFrame->Dr2 = Address;
break;
case 3:
DPRINT("Setting DR3 to 0x%p\n", Address);
TrapFrame->Dr3 = Address;
break;
}
}
static void
GspLoadBreakpoints(PKTRAP_FRAME TrapFrame)
{
unsigned Index;
ULONG i386Type;
DPRINT("GspLoadBreakpoints\n");
DPRINT("DR7 on entry: 0x%08x\n", TrapFrame->Dr7);
/* Remove all breakpoints */
TrapFrame->Dr7 &= ~(DR7_L0 | DR7_L1 | DR7_L2 | DR7_L3 |
DR7_G0 | DR7_G1 | DR7_G2 | DR7_G3 |
DR7_TYPE0_MASK | DR7_LEN0_MASK |
DR7_TYPE1_MASK | DR7_LEN1_MASK |
DR7_TYPE2_MASK | DR7_LEN2_MASK |
DR7_TYPE3_MASK | DR7_LEN3_MASK);
for (Index = 0; Index < GspHwBreakpointCount; Index++)
{
switch(GspHwBreakpoints[Index].Type)
{
case GDB_ZTYPE_HARDWARE_BREAKPOINT:
i386Type = I386_BP_TYPE_EXECUTE;
break;
case GDB_ZTYPE_WRITE_WATCHPOINT:
i386Type = I386_BP_TYPE_DATA_WRITE;
break;
case GDB_ZTYPE_ACCESS_WATCHPOINT:
i386Type = I386_BP_TYPE_DATA_READWRITE;
break;
default:
ASSERT(FALSE);
i386Type = I386_BP_TYPE_EXECUTE;
break;
}
GspLoadHwBreakpoint(TrapFrame, Index, GspHwBreakpoints[Index].Address,
GspHwBreakpoints[Index].Length - 1, i386Type);
}
for (Index = 0; Index < GspSwBreakpointCount; Index++)
{
if (GspHwBreakpointCount + Index < MAX_HW_BREAKPOINTS)
{
DPRINT("Implementing software interrupt using hardware register\n");
GspLoadHwBreakpoint(TrapFrame, GspHwBreakpointCount + Index,
GspSwBreakpoints[Index].Address, 0,
I386_BP_TYPE_EXECUTE);
GspSwBreakpoints[Index].Active = FALSE;
}
else
{
DPRINT("Using real software breakpoint\n");
GspMemoryError = FALSE;
GspSwBreakpoints[Index].PrevContent = GspReadMemSafe((PCHAR) GspSwBreakpoints[Index].Address);
if (! GspMemoryError)
{
GspWriteMemSafe((PCHAR) GspSwBreakpoints[Index].Address, I386_OPCODE_INT3);
}
GspSwBreakpoints[Index].Active = ! GspMemoryError;
if (GspMemoryError)
{
DPRINT1("Failed to set software breakpoint at 0x%p\n",
GspSwBreakpoints[Index].Address);
}
else
{
DPRINT("Successfully set software breakpoint at 0x%p\n",
GspSwBreakpoints[Index].Address);
DPRINT1("Successfully set software breakpoint at 0x%p\n", GspSwBreakpoints[Index].Address);
}
}
}
DPRINT("Final DR7 value 0x%08x\n", TrapFrame->Dr7);
}
static void
GspUnloadBreakpoints(PKTRAP_FRAME TrapFrame)
{
unsigned Index;
DPRINT("GspUnloadHwBreakpoints\n");
for (Index = 0; Index < GspSwBreakpointCount; Index++)
{
if (GspSwBreakpoints[Index].Active)
{
GspMemoryError = FALSE;
GspWriteMemSafe((PCHAR) GspSwBreakpoints[Index].Address,
GspSwBreakpoints[Index].PrevContent);
GspSwBreakpoints[Index].Active = FALSE;
if (GspMemoryError)
{
DPRINT1("Failed to remove software breakpoint from 0x%p\n",
GspSwBreakpoints[Index].Address);
}
else
{
DPRINT("Successfully removed software breakpoint from 0x%p\n",
GspSwBreakpoints[Index].Address);
}
}
}
}
static BOOLEAN gdb_attached_yet = FALSE;
/*
* This function does all command procesing for interfacing to gdb.
*/
KD_CONTINUE_TYPE
STDCALL
KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKTRAP_FRAME TrapFrame)
{
BOOLEAN Stepping;
LONG Address;
LONG Length;
LONG SigVal = 0;
LONG NewPC;
PCHAR ptr;
/* FIXME: Stop on other CPUs too */
if (STATUS_ACCESS_VIOLATION == (NTSTATUS) ExceptionRecord->ExceptionCode &&
NULL != GspAccessLocation &&
(ULONG_PTR) GspAccessLocation ==
(ULONG_PTR) ExceptionRecord->ExceptionInformation[1])
{
GspAccessLocation = NULL;
GspMemoryError = TRUE;
Context->Eip += 3;
}
else
{
DPRINT("Thread %p entering stub\n", PsGetCurrentThread());
/* Can only debug 1 thread at a time... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -