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

📄 gdbstub.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
      ExAcquireFastMutex(&GspLock);
      DPRINT("Thread %p acquired mutex\n", PsGetCurrentThread());

      /* Disable hardware debugging while we are inside the stub */
      Ke386SetDr7(0);
      GspUnloadBreakpoints(TrapFrame);

      /* Make sure we're debugging the current thread. */
      if (NULL != GspDbgThread)
        {
          DPRINT1("Internal error: entering stub with non-NULL GspDbgThread\n");
          ObDereferenceObject(GspDbgThread);
          GspDbgThread = NULL;
        }

      /* ugly hack to avoid attempting to send status at the very
       * beginning, right when GDB is trying to query the stub */
      if (gdb_attached_yet)
        {
          LONG Esp;
  
          stop_reply:
          /* reply to host that an exception has occurred */
          SigVal = GspComputeSignal(ExceptionRecord->ExceptionCode);

          ptr = GspOutBuffer;

          *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
          *ptr++ = HexChars[(SigVal >> 4) & 0xf];
          *ptr++ = HexChars[SigVal & 0xf];

          *ptr++ = HexChars[ESP];
          *ptr++ = ':';
  
          Esp = GspGetEspFromTrapFrame(TrapFrame);      /* SP */
          ptr = GspMem2Hex((PCHAR) &Esp, ptr, 4, 0);
          *ptr++ = ';';
  
          *ptr++ = HexChars[EBP];
          *ptr++ = ':';
          ptr = GspMem2Hex((PCHAR) &TrapFrame->Ebp, ptr, 4, 0);       /* FP */
          *ptr++ = ';';
  
          *ptr++ = HexChars[PC];
          *ptr++ = ':';
          ptr = GspMem2Hex((PCHAR) &TrapFrame->Eip, ptr, 4, 0);        /* PC */
          *ptr++ = ';';

          *ptr = '\0';

          GspPutPacket(&GspOutBuffer[0]);
        }
      else
        {
          gdb_attached_yet = 1;
        }
      
      Stepping = FALSE;

      while (TRUE)
        {
          /* Zero the buffer now so we don't have to worry about the terminating zero character */
          memset(GspOutBuffer, 0, sizeof(GspInBuffer));
          ptr = GspGetPacket();

          switch(*ptr++)
            {
            case '?':
              /* a little hack to send more complete status information */
              goto stop_reply;
              GspOutBuffer[0] = 'S';
              GspOutBuffer[1] = HexChars[SigVal >> 4];
              GspOutBuffer[2] = HexChars[SigVal % 16];
              GspOutBuffer[3] = 0;
              break;
            case 'd':
              GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */
              break;
            case 'g': /* return the value of the CPU Registers */
              GspGetRegisters(GspOutBuffer, TrapFrame);
              break;
            case 'G': /* set the value of the CPU Registers - return OK */
              if (NULL != GspDbgThread)
                {
                  GspSetRegistersInTrapFrame(ptr, Context, GspDbgThread->Tcb.TrapFrame);
                }
              else
                {
                  GspSetRegistersInTrapFrame(ptr, Context, TrapFrame);
                }
              strcpy(GspOutBuffer, "OK");
              break;
            case 'P': /* set the value of a single CPU register - return OK */
              {
                LONG Register;

                if ((GspHex2Long(&ptr, &Register)) && (*ptr++ == '='))
                  {
                    if ((Register >= 0) && (Register < NUMREGS))
                      {
                        if (GspDbgThread)
                          {
                            GspSetSingleRegisterInTrapFrame(ptr, Register,
                                                            Context,
                                                            GspDbgThread->Tcb.TrapFrame);
                          }
                        else
                          {
                            GspSetSingleRegisterInTrapFrame(ptr, Register,
                                                            Context, TrapFrame);
                          }
                        strcpy(GspOutBuffer, "OK");
                        break;
                      }
                  }

                strcpy(GspOutBuffer, "E01");
                break;
              }

            /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
            case 'm':
              /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
              if (GspHex2Long(&ptr, &Address) &&
                  *(ptr++) == ',' &&
                  GspHex2Long(&ptr, &Length))
                {
                  PEPROCESS DbgProcess = NULL;

                  ptr = NULL;
                  if (NULL != GspDbgThread &&
                      PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
                    {
                      DbgProcess = GspDbgThread->ThreadsProcess;
                      KeAttachProcess(&DbgProcess->Pcb);
                    }
                  GspMemoryError = FALSE;
                  GspMem2Hex((PCHAR) Address, GspOutBuffer, Length, 1);
                  if (NULL != DbgProcess)
                    {
                      KeDetachProcess();
                    }
                  if (GspMemoryError)
                    {
                      strcpy(GspOutBuffer, "E03");
                      DPRINT("Fault during memory read\n");
                    }
                }

              if (NULL != ptr)
                {
                  strcpy(GspOutBuffer, "E01");
                }
              break;

            /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
            case 'M':
              /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
              if (GspHex2Long(&ptr, &Address))
                {
                  if (*(ptr++) == ',' &&
                      GspHex2Long(&ptr, &Length) &&
                      *(ptr++) == ':')
                    {
                      PEPROCESS DbgProcess = NULL;

                      if (NULL != GspDbgThread &&
                          PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
                        {
                          DbgProcess = GspDbgThread->ThreadsProcess;
                          KeAttachProcess(&DbgProcess->Pcb);
                        }
                      GspMemoryError = FALSE;
                      GspHex2Mem(ptr, (PCHAR) Address, Length, TRUE);
                      if (NULL != DbgProcess)
                        {
                          KeDetachProcess();
                        }
                      if (GspMemoryError)
                        {
                          strcpy(GspOutBuffer, "E03");
                          DPRINT("Fault during memory write\n");
                        }
                      else
                        {
                          strcpy(GspOutBuffer, "OK");
                        }
                      ptr = NULL;
                    }
                }

              if (NULL != ptr)
                {
                  strcpy(GspOutBuffer, "E02");
                }
              break;

            /* cAA..AA   Continue at address AA..AA(optional) */
            /* sAA..AA   Step one instruction from AA..AA(optional) */
            case 's':
              Stepping = TRUE;
            case 'c':
              {
                ULONG BreakpointNumber;
                ULONG dr6_;

                /* try to read optional parameter, pc unchanged if no parm */
                if (GspHex2Long (&ptr, &Address))
                  {
                    Context->Eip = Address;
                  }

                NewPC = Context->Eip;

                /* clear the trace bit */
                Context->EFlags &= 0xfffffeff;

                /* set the trace bit if we're Stepping */
                if (Stepping)
                  {
                    Context->EFlags |= 0x100;
                  }

#if defined(__GNUC__)
                asm volatile ("movl %%db6, %0\n" : "=r" (dr6_) : );
#elif defined(_MSC_VER)
                __asm mov eax, dr6  __asm mov dr6_, eax;
#else
#error Unknown compiler for inline assembler
#endif
                if (!(dr6_ & 0x4000))
                  {
                    for (BreakpointNumber = 0; BreakpointNumber < 4; ++BreakpointNumber)
                      {
                        if (dr6_ & (1 << BreakpointNumber))
                          {
                            if (GspHwBreakpoints[BreakpointNumber].Type == 0)
                              {
                                /* Set restore flag */
                                Context->EFlags |= 0x10000;
                                break;
                              }
                          }
                      }
                  }
                GspLoadBreakpoints(TrapFrame);
#if defined(__GNUC__)
                asm volatile ("movl %0, %%db6\n" : : "r" (0));
#elif defined(_MSC_VER)
                __asm mov eax, 0  __asm mov dr6, eax;
#else
#error Unknown compiler for inline assembler
#endif

                if (NULL != GspDbgThread)
                  {
                    ObDereferenceObject(GspDbgThread);
                    GspDbgThread = NULL;
                  }

                DPRINT("Thread %p releasing mutex\n", PsGetCurrentThread());
                ExReleaseFastMutex(&GspLock);
                DPRINT("Thread %p leaving stub\n", PsGetCurrentThread());
                return kdContinue;
                break;
              }

            case 'k':  /* kill the program */
              strcpy(GspOutBuffer, "OK");
              break;
              /* kill the program */

            case 'H': /* Set thread */
              GspSetThread(ptr);
              break;

            case 'q': /* Query */
              GspQuery(ptr);
              break;

            case 'T': /* Query thread status */
              GspQueryThreadStatus(ptr);
              break;

            case 'Z':
              {
                LONG Type;
                LONG Address;
                LONG Length;

                GspHex2Long(&ptr, &Type);
                ptr++;
                GspHex2Long(&ptr, &Address);
                ptr++;
                GspHex2Long(&ptr, &Length);
                if (0 == Type)
                  {
                  GspSetSwBreakpoint((ULONG_PTR) Address);
                  }
                else
                  {
                  GspSetHwBreakpoint(Type, (ULONG_PTR) Address, Length);
                  }
                break;
              }

            case 'z':
              {
                LONG Type;
                LONG Address;
                LONG Length;

                GspHex2Long(&ptr, &Type);
                ptr++;
                GspHex2Long(&ptr, &Address);
                ptr++;
                GspHex2Long(&ptr, &Length);
                if (0 == Type)
                  {
                  GspRemoveSwBreakpoint((ULONG_PTR) Address);
                  }
                else
                  {
                  GspRemoveHwBreakpoint(Type, (ULONG_PTR) Address, Length);
                  }
                break;
              }

            default:
              break;
            }

          /* reply to the request */
          GspPutPacket(GspOutBuffer);
        }

      /* not reached */
      ASSERT(0);
    }

  if (NULL != GspDbgThread)
    {
      ObDereferenceObject(GspDbgThread);
      GspDbgThread = NULL;
    }

  return kdContinue;
}


BOOLEAN
STDCALL
GspBreakIn(PKINTERRUPT Interrupt,
  PVOID ServiceContext)
{
  PKTRAP_FRAME TrapFrame;
  BOOLEAN DoBreakIn;
  CONTEXT Context;
  KIRQL OldIrql;
  UCHAR Value;

  DPRINT("Break In\n");

  DoBreakIn = FALSE;
  while (KdPortGetByteEx(&GdbPortInfo, &Value))
    {
      if (Value == 0x03)
        {
          DoBreakIn = TRUE;
        }
    }

  if (!DoBreakIn)
    {
      return TRUE;
    }

  KeRaiseIrql(HIGH_LEVEL, &OldIrql);

  TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;

  KeTrapFrameToContext(TrapFrame, NULL, &Context);

  KdpGdbEnterDebuggerException(NULL, &Context, TrapFrame);

  KeContextToTrapFrame(&Context, NULL, TrapFrame, Context.ContextFlags, KernelMode);

  KeLowerIrql(OldIrql);

  return TRUE;
}

VOID
STDCALL
KdpGdbDebugPrint(PCH Message, ULONG Length)
{
}

/* Initialize the GDB stub */
VOID
STDCALL
KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable,
               ULONG BootPhase)
{
  if (!KdDebuggerEnabled || !KdpDebugMode.Gdb)
    {
      return;
    }

  if (BootPhase == 0)
    {
      ExInitializeFastMutex(&GspLock);

      /* Write out the functions that we support for now */
      WrapperTable->KdpInitRoutine = KdpGdbStubInit;
      WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;
      WrapperTable->KdpExceptionRoutine = KdpGdbEnterDebuggerException;

      /* Initialize the Port */
      KdPortInitializeEx(&GdbPortInfo, 0, 0);

      KdpPort = GdbPortInfo.ComPort;
    }
  else if (BootPhase == 1)
    {
      GspInitialized = TRUE;

      GspRunThread = NULL;
      GspDbgThread = NULL;
      GspEnumThread = NULL;

      HalDisplayString("Waiting for GDB to attach\n");
      DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
    }
  else if (BootPhase == 2)
    {
      HalDisplayString("\n   GDB debugging enabled\n\n");
    }
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -