https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0eea78648ce3235fb2506f561c0345f29fc241ee

commit 0eea78648ce3235fb2506f561c0345f29fc241ee
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Wed Apr 14 13:36:17 2021 +0200
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Wed Apr 28 13:10:23 2021 +0200

    [KDGDB] Adapt to amd64
---
 drivers/base/kdgdb/CMakeLists.txt |   4 +-
 drivers/base/kdgdb/amd64_sup.c    | 263 ++++++++++++++++++++++++++++++++++++++
 drivers/base/kdgdb/gdb_input.c    |  18 +--
 drivers/base/kdgdb/kdgdb.h        |  13 +-
 4 files changed, 284 insertions(+), 14 deletions(-)

diff --git a/drivers/base/kdgdb/CMakeLists.txt 
b/drivers/base/kdgdb/CMakeLists.txt
index d783b3851da..05c2f8f6e2e 100644
--- a/drivers/base/kdgdb/CMakeLists.txt
+++ b/drivers/base/kdgdb/CMakeLists.txt
@@ -10,9 +10,11 @@ list(APPEND SOURCE
     utils.c
     kdgdb.h)
 
-# TODO: AMD64, ARM...
+# TODO: ARM...
 if(ARCH STREQUAL "i386")
     list(APPEND SOURCE i386_sup.c)
+elseif(ARCH STREQUAL "amd64")
+    list(APPEND SOURCE amd64_sup.c)
 endif()
 
 add_library(kdcom MODULE
diff --git a/drivers/base/kdgdb/amd64_sup.c b/drivers/base/kdgdb/amd64_sup.c
new file mode 100644
index 00000000000..b497581a797
--- /dev/null
+++ b/drivers/base/kdgdb/amd64_sup.c
@@ -0,0 +1,263 @@
+/*
+ * PROJECT:     ReactOS KD dll - GDB stub
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Base functions for the kernel debugger
+ * COPYRIGHT:   Copyright 2021 Jérôme Gardou
+ */
+
+#include "kdgdb.h"
+
+enum reg_name
+{
+    RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP,
+    R8, R9, R10, R11, R12, R13, R14, R15,
+    RIP,
+    EFLAGS,
+    CS, SS, DS, ES, FS, GS,
+    ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7,
+    FCTRL, FSTAT, FTAG, FISEG, FIOFF, FOSEG, FOOFF, FOP
+};
+
+static const unsigned char reg_size[] =
+{
+    8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8,
+    8,
+    4,
+    4, 4, 4, 4, 4, 4,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    8, 8, 8, 8, 8, 8, 8, 8
+};
+
+static
+void*
+ctx_to_reg(CONTEXT* ctx, enum reg_name name)
+{
+    switch (name)
+    {
+        case RAX: return &ctx->Rax;
+        case RBX: return &ctx->Rbx;
+        case RCX: return &ctx->Rcx;
+        case RDX: return &ctx->Rdx;
+        case RSP: return &ctx->Rsp;
+        case RBP: return &ctx->Rbp;
+        case RSI: return &ctx->Rsi;
+        case RDI: return &ctx->Rdi;
+        case RIP: return &ctx->Rip;
+        case R8: return &ctx->R8;
+        case R9: return &ctx->R9;
+        case R10: return &ctx->R10;
+        case R11: return &ctx->R11;
+        case R12: return &ctx->R12;
+        case R13: return &ctx->R13;
+        case R14: return &ctx->R14;
+        case R15: return &ctx->R15;
+        case EFLAGS: return &ctx->EFlags;
+        case CS: return &ctx->SegCs;
+        case DS: return &ctx->SegSs;
+        case ES: return &ctx->SegEs;
+        case FS: return &ctx->SegFs;
+        case GS: return &ctx->SegGs;
+        case SS: return &ctx->SegSs;
+    }
+#undef return_reg
+    return 0;
+}
+
+static
+void*
+thread_to_reg(PETHREAD Thread, enum reg_name reg_name)
+{
+    static const void* NullValue = NULL;
+
+#if 0
+    if (Thread->Tcb.TrapFrame)
+    {
+        PKTRAP_FRAME TrapFrame = Thread->Tcb.TrapFrame;
+
+        switch (reg_name)
+        {
+            case RAX: return &TrapFrame->Rax;
+            case RBX: return &TrapFrame->Rbx;
+            case RCX: return &TrapFrame->Rcx;
+            case RDX: return &TrapFrame->Rdx;
+            case RSP: return &TrapFrame->Rsp;
+            case RBP: return &TrapFrame->Rbp;
+            case RSI: return &TrapFrame->Rsi;
+            case RDI: return &TrapFrame->Rdi;
+            case RIP: return &TrapFrame->Rip;
+            case R8: return &TrapFrame->R8;
+            case R9: return &TrapFrame->R9;
+            case R10: return &TrapFrame->R10;
+            case R11: return &TrapFrame->R11;
+            case EFLAGS: return &TrapFrame->EFlags;
+            case CS: return &TrapFrame->SegCs;
+            case DS: return &TrapFrame->SegSs;
+            case ES: return &TrapFrame->SegEs;
+            case FS: return &TrapFrame->SegFs;
+            case GS: return &TrapFrame->SegGs;
+            case SS: return &TrapFrame->SegSs;
+            default:
+                KDDBGPRINT("Unhandled regname: %d.\n", reg_name);
+        }
+    }
+    else
+#endif
+    if (!Thread->Tcb.InitialStack)
+    {
+        /* Terminated thread ? */
+        switch (reg_name)
+        {
+            case RSP:
+            case RBP:
+            case RIP:
+                KDDBGPRINT("Returning NULL for register %d.\n", reg_name);
+                return &NullValue;
+            default:
+                return NULL;
+        }
+    }
+    else
+    {
+        switch(reg_name)
+        {
+            case RSP: return &Thread->Tcb.KernelStack;
+            case RIP:
+            {
+                PULONG_PTR Rsp = Thread->Tcb.KernelStack;
+                return &Rsp[3];
+            }
+            case RBP:
+            {
+                PULONG_PTR Rsp = Thread->Tcb.KernelStack;
+                return &Rsp[4];
+            }
+            default:
+                return NULL;
+        }
+    }
+
+    return NULL;
+}
+
+KDSTATUS
+gdb_send_registers(void)
+{
+    CHAR RegisterStr[17];
+    UCHAR* RegisterPtr;
+    unsigned short i;
+    unsigned short size;
+
+    start_gdb_packet();
+
+    KDDBGPRINT("Sending registers of thread %" PRIxPTR ".\n", gdb_dbg_tid);
+    KDDBGPRINT("Current thread_id: %p.\n", 
PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
+    if (((gdb_dbg_pid == 0) && (gdb_dbg_tid == 0)) ||
+            gdb_tid_to_handle(gdb_dbg_tid) == 
PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))
+    {
+        for (i = 0; i < 24; i++)
+        {
+            RegisterPtr = ctx_to_reg(&CurrentContext, i);
+            size = reg_size[i] * 2;
+            RegisterStr[size] = 0;
+            while (size)
+            {
+                size--;
+                RegisterStr[size] = hex_chars[RegisterPtr[size/2] & 0xF];
+                size--;
+                RegisterStr[size] = hex_chars[RegisterPtr[size/2] >> 4];
+            }
+
+            send_gdb_partial_packet(RegisterStr);
+        }
+    }
+    else
+    {
+        PETHREAD DbgThread;
+
+        DbgThread = find_thread(gdb_dbg_pid, gdb_dbg_tid);
+
+        if (DbgThread == NULL)
+        {
+            /* Thread is dead */
+            send_gdb_partial_packet("E03");
+            return finish_gdb_packet();
+        }
+
+        for (i = 0; i < 24; i++)
+        {
+            RegisterPtr = thread_to_reg(DbgThread, i);
+            size = reg_size[i] * 2;
+            RegisterStr[size] = 0;
+
+            while (size)
+            {
+                if (RegisterPtr)
+                {
+                    size--;
+                    RegisterStr[size] = hex_chars[RegisterPtr[size/2] & 0xF];
+                    size--;
+                    RegisterStr[size] = hex_chars[RegisterPtr[size/2] >> 4];
+                }
+                else
+                {
+                    size--;
+                    RegisterStr[size] = 'x';
+                    size--;
+                    RegisterStr[size] = 'x';
+                }
+            }
+
+            send_gdb_partial_packet(RegisterStr);
+        }
+    }
+
+    return finish_gdb_packet();
+}
+
+KDSTATUS
+gdb_send_register(void)
+{
+    enum reg_name reg_name;
+    void *ptr;
+
+    /* Get the GDB register name (gdb_input = "pXX") */
+    reg_name = (hex_value(gdb_input[1]) << 4) | hex_value(gdb_input[2]);
+
+    if (((gdb_dbg_pid == 0) && (gdb_dbg_tid == 0)) ||
+            gdb_tid_to_handle(gdb_dbg_tid) == 
PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))
+    {
+        /* We can get it from the context of the current exception */
+        ptr = ctx_to_reg(&CurrentContext, reg_name);
+    }
+    else
+    {
+        PETHREAD DbgThread;
+
+        DbgThread = find_thread(gdb_dbg_pid, gdb_dbg_tid);
+
+        if (DbgThread == NULL)
+        {
+            /* Thread is dead */
+            return send_gdb_packet("E03");
+        }
+
+        ptr = thread_to_reg(DbgThread, reg_name);
+    }
+
+    if (!ptr)
+    {
+        unsigned char size = reg_size[reg_name];
+        start_gdb_packet();
+        while (size--)
+            send_gdb_partial_packet("xx");
+        return finish_gdb_packet();
+    }
+    else
+    {
+        KDDBGPRINT("KDDBG : Sending registers as memory.\n");
+        return send_gdb_memory(ptr, reg_size[reg_name]);
+    }
+}
+
+
diff --git a/drivers/base/kdgdb/gdb_input.c b/drivers/base/kdgdb/gdb_input.c
index 3b898c46829..23f030686d4 100644
--- a/drivers/base/kdgdb/gdb_input.c
+++ b/drivers/base/kdgdb/gdb_input.c
@@ -301,12 +301,6 @@ handle_gdb_query(void)
         return gdb_send_debug_io(&String, FALSE);
     }
 
-    if (strncmp(gdb_input, "qOffsets", 8) == 0)
-    {
-        /* We load ntoskrnl at 0x80800000 while compiling it at 0x00800000 
base address */
-        return send_gdb_packet("TextSeg=80000000");
-    }
-
     if (strcmp(gdb_input, "qTStatus") == 0)
     {
         /* No tracepoint support */
@@ -323,7 +317,7 @@ handle_gdb_query(void)
     {
         static LIST_ENTRY* CurrentEntry = NULL;
         char str_helper[256];
-        char name_helper[64];        
+        char name_helper[64];
         ULONG_PTR Offset = hex_to_address(&gdb_input[22]);
         ULONG_PTR ToSend = hex_to_address(strstr(&gdb_input[22], ",") + 1);
         ULONG Sent = 0;
@@ -381,7 +375,7 @@ handle_gdb_query(void)
 
             /* GDB doesn't load the file if you don't prefix it with a drive 
letter... */
             mem_length = _snprintf(str_helper, 256, "<library 
name=\"C:\\%s\"><segment address=\"0x%p\"/></library>", &name_helper, DllBase);
-            
+
             /* DLL name must be too long. */
             if (mem_length < 0)
             {
@@ -639,7 +633,7 @@ handle_gdb_write_mem(
         /* Nothing to do */
         return LOOP_IF_SUCCESS(send_gdb_packet("OK"));
     }
-    
+
     State->u.WriteMemory.TransferCount = BufferLength;
     MessageData->Length = BufferLength;
     MessageData->Buffer = (CHAR*)OutBuffer;
@@ -794,7 +788,7 @@ RestoreBreakPointSendHandler(
         KDDBGPRINT("Wrong API number (%lu) after DbgKdRestoreBreakPointApi 
request.\n", State->ApiNumber);
     }
 
-    /* We ignore failure here. If DbgKdRestoreBreakPointApi fails, 
+    /* We ignore failure here. If DbgKdRestoreBreakPointApi fails,
      * this means that the breakpoint was already invalid for KD. So clean it 
up on our side. */
     for (i = 0; i < (sizeof(BreakPointHandles) / 
sizeof(BreakPointHandles[0])); i++)
     {
@@ -879,7 +873,7 @@ handle_gdb_c(
     Status = send_gdb_packet("OK");
     if (Status != KdPacketReceived)
         return Status;
-        
+
 
     if (CurrentStateChange.NewState == DbgKdExceptionStateChange)
     {
@@ -967,7 +961,7 @@ handle_gdb_v(
 
         if (strncmp(gdb_input, "vCont;s", 7) == 0)
         {
-            
+
             return handle_gdb_s(State, MessageData, MessageLength, KdContext);
         }
     }
diff --git a/drivers/base/kdgdb/kdgdb.h b/drivers/base/kdgdb/kdgdb.h
index d09ef74593b..a260e570319 100644
--- a/drivers/base/kdgdb/kdgdb.h
+++ b/drivers/base/kdgdb/kdgdb.h
@@ -19,7 +19,7 @@
 
 #include <pstypes.h>
 
-// #define KDDEBUG /* uncomment to enable debugging this dll */
+#define KDDEBUG /* uncomment to enable debugging this dll */
 
 /* To undefine once https://sourceware.org/bugzilla/show_bug.cgi?id=17397 is 
resolved */
 #define MONOPROCESS 1
@@ -132,6 +132,17 @@ extern KDSTATUS gdb_send_registers(void);
 #  define KD_BREAKPOINT_SIZE        sizeof(UCHAR)
 #  define KD_BREAKPOINT_VALUE       0xCC
 /* Single step mode */
+#  define KdpSetSingleStep(Context) \
+    ((Context)->EFlags |= EFLAGS_TF)
+#elif defined(_M_AMD64)
+#  define KdpGetContextPc(Context) \
+    ((Context)->Rip)
+#  define KdpSetContextPc(Context, ProgramCounter) \
+    ((Context)->Rip = (ProgramCounter))
+#  define KD_BREAKPOINT_TYPE        UCHAR
+#  define KD_BREAKPOINT_SIZE        sizeof(UCHAR)
+#  define KD_BREAKPOINT_VALUE       0xCC
+/* Single step mode */
 #  define KdpSetSingleStep(Context) \
     ((Context)->EFlags |= EFLAGS_TF)
 #else

Reply via email to