[PATCH 3/7] [WineDbg]: frame handling

Eric Pouech eric.pouech at wanadoo.fr
Sat Dec 2 10:43:08 CST 2006


- added some black magic to still handle register values
  on non current frame for some of the registers we know of
  (frame pointer, stack pointer)

A+
---

 programs/winedbg/be_alpha.c  |    7 +++++++
 programs/winedbg/be_cpu.h    |    4 ++++
 programs/winedbg/be_i386.c   |   12 ++++++++++++
 programs/winedbg/be_ppc.c    |    7 +++++++
 programs/winedbg/be_x86_64.c |   13 +++++++++++++
 programs/winedbg/debugger.h  |    5 +++++
 programs/winedbg/memory.c    |   18 ++++++++++++------
 programs/winedbg/stack.c     |   35 +++++++++++++++++++++++++++++++----
 8 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/programs/winedbg/be_alpha.c b/programs/winedbg/be_alpha.c
index 6bc9cd8..e3072ae 100644
--- a/programs/winedbg/be_alpha.c
+++ b/programs/winedbg/be_alpha.c
@@ -29,6 +29,12 @@ static unsigned be_alpha_get_addr(HANDLE
     return FALSE;
 }
 
+static unsigned be_alpha_get_register_info(int regno, enum be_cpu_addr* kind)
+{
+    dbg_printf("not done\n");
+    return FALSE;
+}
+
 static void be_alpha_single_step(CONTEXT* ctx, unsigned enable)
 {
     dbg_printf("not done\n");
@@ -148,6 +154,7 @@ struct backend_cpu be_alpha =
     be_cpu_linearize,
     be_cpu_build_addr,
     be_alpha_get_addr,
+    be_alpha_get_register_info,
     be_alpha_single_step,
     be_alpha_print_context,
     be_alpha_print_segment_info,
diff --git a/programs/winedbg/be_cpu.h b/programs/winedbg/be_cpu.h
index 4111dff..db3e0cd 100644
--- a/programs/winedbg/be_cpu.h
+++ b/programs/winedbg/be_cpu.h
@@ -43,6 +43,10 @@ struct backend_cpu
      */
     unsigned            (*get_addr)(HANDLE hThread, const CONTEXT* ctx, 
                                     enum be_cpu_addr, ADDRESS64* addr);
+
+    /* returns which kind of information a given register number refers to */
+    unsigned            (*get_register_info)(int regno, enum be_cpu_addr* kind);
+
     /* -------------------------------------------------------------------------------
      * context manipulation 
      * ------------------------------------------------------------------------------- */
diff --git a/programs/winedbg/be_i386.c b/programs/winedbg/be_i386.c
index dc8f824..f15121d 100644
--- a/programs/winedbg/be_i386.c
+++ b/programs/winedbg/be_i386.c
@@ -111,6 +111,17 @@ static unsigned be_i386_get_addr(HANDLE 
     return FALSE;
 }
 
+static unsigned be_i386_get_register_info(int regno, enum be_cpu_addr* kind)
+{
+    switch (regno)
+    {
+    case CV_REG_EIP: *kind = be_cpu_addr_pc; return TRUE;
+    case CV_REG_EBP: *kind = be_cpu_addr_frame; return TRUE;
+    case CV_REG_ESP: *kind = be_cpu_addr_stack; return TRUE;
+    }
+    return FALSE;
+}
+
 static void be_i386_single_step(CONTEXT* ctx, unsigned enable)
 {
     if (enable) ctx->EFlags |= STEP_FLAG;
@@ -739,6 +750,7 @@ struct backend_cpu be_i386 =
     be_i386_linearize,
     be_i386_build_addr,
     be_i386_get_addr,
+    be_i386_get_register_info,
     be_i386_single_step,
     be_i386_print_context,
     be_i386_print_segment_info,
diff --git a/programs/winedbg/be_ppc.c b/programs/winedbg/be_ppc.c
index 24e75e5..2e8826e 100644
--- a/programs/winedbg/be_ppc.c
+++ b/programs/winedbg/be_ppc.c
@@ -38,6 +38,12 @@ static unsigned be_ppc_get_addr(HANDLE h
     return FALSE;
 }
 
+static unsigned be_ppc_get_register_info(int regno, enum be_cpu_addr* kind)
+{
+    dbg_printf("not done\n");
+    return FALSE;
+}
+
 static void be_ppc_single_step(CONTEXT* ctx, unsigned enable)
 {
 #ifndef MSR_SE
@@ -172,6 +178,7 @@ struct backend_cpu be_ppc =
     be_cpu_linearize,
     be_cpu_build_addr,
     be_ppc_get_addr,
+    be_ppc_get_register_info,
     be_ppc_single_step,
     be_ppc_print_context,
     be_ppc_print_segment_info,
diff --git a/programs/winedbg/be_x86_64.c b/programs/winedbg/be_x86_64.c
index 9a40a8c..3400f72 100644
--- a/programs/winedbg/be_x86_64.c
+++ b/programs/winedbg/be_x86_64.c
@@ -46,6 +46,18 @@ static unsigned be_x86_64_get_addr(HANDL
     }
 }
 
+static unsigned be_x86_64_get_register_info(int regno, enum be_cpu_addr* kind)
+{
+    /* this is true when running in 32bit mode... and wrong in 64 :-/ */
+    switch (regno)
+    {
+    case CV_AMD64_EIP: *kind = be_cpu_addr_pc; return TRUE;
+    case CV_AMD64_EBP: *kind = be_cpu_addr_frame; return TRUE;
+    case CV_AMD64_ESP: *kind = be_cpu_addr_stack; return TRUE;
+    }
+    return FALSE;
+}
+
 static void be_x86_64_single_step(CONTEXT* ctx, unsigned enable)
 {
     dbg_printf("not done single_step\n");
@@ -210,6 +222,7 @@ struct backend_cpu be_x86_64 =
     be_cpu_linearize,
     be_cpu_build_addr,
     be_x86_64_get_addr,
+    be_x86_64_get_register_info,
     be_x86_64_single_step,
     be_x86_64_print_context,
     be_x86_64_print_segment_info,
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index 67b84ba..43abb60 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -176,6 +176,10 @@ struct dbg_thread
     {
         ADDRESS64               addr_pc;
         ADDRESS64               addr_frame;
+        ADDRESS64               addr_stack;
+        DWORD                   linear_pc;
+        DWORD                   linear_frame;
+        DWORD                   linear_stack;
     }*                          frames;
     int                         num_frames;
     int                         curr_frame;
@@ -361,6 +365,7 @@ extern void             stack_info(void)
 extern void             stack_backtrace(DWORD threadID);
 extern BOOL             stack_set_frame(int newframe);
 extern BOOL             stack_get_current_frame(IMAGEHLP_STACK_FRAME* ihsf);
+extern BOOL             stack_get_register_current_frame(unsigned regno, DWORD** pval);
 extern unsigned         stack_fetch_frames(void);
 extern BOOL             stack_get_current_symbol(SYMBOL_INFO* sym);
 
diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c
index d4fb7c3..01d3da0 100644
--- a/programs/winedbg/memory.c
+++ b/programs/winedbg/memory.c
@@ -636,16 +636,22 @@ BOOL memory_get_register(DWORD regno, DW
         if (buffer) snprintf(buffer, len, "<couldn't read memory>");
         return FALSE;
     }
-    if (dbg_curr_thread->curr_frame != 0)
-    {
-        if (buffer) snprintf(buffer, len, "<register not in topmost frame>");
-        return FALSE;
-    }
+
     for (div = dbg_context_vars; div->name; div++)
     {
         if (div->val == regno)
         {
-            *value = div->pval;
+            if (dbg_curr_thread->curr_frame != 0)
+            {
+                if (!stack_get_register_current_frame(regno, value))
+                {
+                    if (buffer) snprintf(buffer, len, "<register %s not in topmost frame>", div->name);
+                    return FALSE;
+                }
+            }
+            else
+                *value = div->pval;
+
             snprintf(buffer, len, div->name);
             return TRUE;
         }
diff --git a/programs/winedbg/stack.c b/programs/winedbg/stack.c
index 527ed03..c279014 100644
--- a/programs/winedbg/stack.c
+++ b/programs/winedbg/stack.c
@@ -82,8 +82,8 @@ static BOOL stack_set_frame_internal(int
 static BOOL stack_get_frame(int nf, IMAGEHLP_STACK_FRAME* ihsf)
 {
     memset(ihsf, 0, sizeof(*ihsf));
-    ihsf->InstructionOffset = (unsigned long)memory_to_linear_addr(&dbg_curr_thread->frames[nf].addr_pc);
-    ihsf->FrameOffset = (unsigned long)memory_to_linear_addr(&dbg_curr_thread->frames[nf].addr_frame);
+    ihsf->InstructionOffset = dbg_curr_thread->frames[nf].linear_pc;
+    ihsf->FrameOffset = dbg_curr_thread->frames[nf].linear_frame;
     return TRUE;
 }
 
@@ -96,6 +96,29 @@ BOOL stack_get_current_frame(IMAGEHLP_ST
     return stack_get_frame(dbg_curr_thread->curr_frame, ihsf);
 }
 
+BOOL stack_get_register_current_frame(unsigned regno, DWORD** pval)
+{
+    enum be_cpu_addr            kind;
+
+    if (dbg_curr_thread->frames == NULL) return FALSE;
+
+    if (!be_cpu->get_register_info(regno, &kind)) return FALSE;
+
+    switch (kind)
+    {
+    case be_cpu_addr_pc:
+        *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_pc;
+        break;
+    case be_cpu_addr_stack:
+        *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_stack;
+        break;
+    case be_cpu_addr_frame:
+        *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_frame;
+        break;
+    }
+    return TRUE;
+}
+
 BOOL stack_set_frame(int newframe)
 {
     ADDRESS64   addr;
@@ -170,8 +193,12 @@ unsigned stack_fetch_frames(void)
         dbg_curr_thread->frames = dbg_heap_realloc(dbg_curr_thread->frames, 
                                                    (nf + 1) * sizeof(dbg_curr_thread->frames[0]));
 
-        dbg_curr_thread->frames[nf].addr_pc = sf.AddrPC;
-        dbg_curr_thread->frames[nf].addr_frame = sf.AddrFrame;
+        dbg_curr_thread->frames[nf].addr_pc      = sf.AddrPC;
+        dbg_curr_thread->frames[nf].linear_pc    = (DWORD)memory_to_linear_addr(&sf.AddrPC);
+        dbg_curr_thread->frames[nf].addr_frame   = sf.AddrFrame;
+        dbg_curr_thread->frames[nf].linear_frame = (DWORD)memory_to_linear_addr(&sf.AddrFrame);
+        dbg_curr_thread->frames[nf].addr_stack   = sf.AddrStack;
+        dbg_curr_thread->frames[nf].linear_stack = (DWORD)memory_to_linear_addr(&sf.AddrStack);
         nf++;
         /* we've probably gotten ourselves into an infinite loop so bail */
         if (nf > 200) break;



More information about the wine-patches mailing list