⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdbstub.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
              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 + -