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

📄 gdbstub.c

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

/* 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 + -