[PATCH 8/8] [DbgHelp]: add a couple of helpers to struct cpu to help adding the stack to minidump

Eric Pouech eric.pouech at orange.fr
Tue Dec 22 07:21:37 CST 2009




A+
---

 dlls/dbghelp/Makefile.in       |    1 +
 dlls/dbghelp/cpu_i386.c        |   60 ++++++++++++++++++++++++++++++++++++++
 dlls/dbghelp/cpu_ppc.c         |   63 ++++++++++++++++++++++++++++++++++++++++
 dlls/dbghelp/cpu_x86_64.c      |   18 +++++++++++
 dlls/dbghelp/dbghelp_private.h |    7 ++++
 dlls/dbghelp/minidump.c        |   53 ++++++----------------------------
 6 files changed, 159 insertions(+), 43 deletions(-)
 create mode 100644 dlls/dbghelp/cpu_ppc.c


diff --git a/dlls/dbghelp/Makefile.in b/dlls/dbghelp/Makefile.in
index d3a72a2..a3b1553 100644
--- a/dlls/dbghelp/Makefile.in
+++ b/dlls/dbghelp/Makefile.in
@@ -11,6 +11,7 @@ DELAYIMPORTS = version
 C_SRCS = \
 	coff.c \
 	cpu_i386.c \
+	cpu_ppc.c \
 	cpu_x86_64.c \
 	crc32.c \
 	dbghelp.c \
diff --git a/dlls/dbghelp/cpu_i386.c b/dlls/dbghelp/cpu_i386.c
index a3649ba..a83f0fa 100644
--- a/dlls/dbghelp/cpu_i386.c
+++ b/dlls/dbghelp/cpu_i386.c
@@ -29,6 +29,64 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
 
+#define STEP_FLAG 0x00000100 /* single step flag */
+#define V86_FLAG  0x00020000
+
+#define IS_VM86_MODE(ctx) (ctx->EFlags & V86_FLAG)
+
+#ifdef __i386__
+static ADDRESS_MODE get_selector_type(HANDLE hThread, const CONTEXT* ctx, WORD sel)
+{
+    LDT_ENTRY	le;
+
+    if (IS_VM86_MODE(ctx)) return AddrModeReal;
+    /* null or system selector */
+    if (!(sel & 4) || ((sel >> 3) < 17)) return AddrModeFlat;
+    if (hThread && GetThreadSelectorEntry(hThread, sel, &le))
+        return le.HighWord.Bits.Default_Big ? AddrMode1632 : AddrMode1616;
+    /* selector doesn't exist */
+    return -1;
+}
+
+static unsigned i386_build_addr(HANDLE hThread, const CONTEXT* ctx, ADDRESS64* addr,
+                                unsigned seg, unsigned long offset)
+{
+    addr->Mode    = AddrModeFlat;
+    addr->Segment = seg;
+    addr->Offset  = offset;
+    if (seg)
+    {
+        switch (addr->Mode = get_selector_type(hThread, ctx, seg))
+        {
+        case AddrModeReal:
+        case AddrMode1616:
+            addr->Offset &= 0xffff;
+            break;
+        case AddrModeFlat:
+        case AddrMode1632:
+            break;
+        default:
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+#endif
+
+static unsigned i386_get_addr(HANDLE hThread, const CONTEXT* ctx,
+                              enum cpu_addr ca, ADDRESS64* addr)
+{
+#ifdef __i386__
+    switch (ca)
+    {
+    case cpu_addr_pc:    return i386_build_addr(hThread, ctx, addr, ctx->SegCs, ctx->Eip);
+    case cpu_addr_stack: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Esp);
+    case cpu_addr_frame: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Ebp);
+    }
+#endif
+    return FALSE;
+}
+
 enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
 
 /* indexes in Reserved array */
@@ -344,5 +402,7 @@ done_err:
 
 struct cpu cpu_i386 = {
     IMAGE_FILE_MACHINE_I386,
+    4,
+    i386_get_addr,
     i386_stack_walk,
 };
diff --git a/dlls/dbghelp/cpu_ppc.c b/dlls/dbghelp/cpu_ppc.c
new file mode 100644
index 0000000..da440f8
--- /dev/null
+++ b/dlls/dbghelp/cpu_ppc.c
@@ -0,0 +1,63 @@
+/*
+ * File cpu_ppc.c
+ *
+ * Copyright (C) 2009-2009, Eric Pouech.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <assert.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "dbghelp_private.h"
+#include "wine/winbase16.h"
+#include "winternl.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
+
+static unsigned ppc_get_addr(HANDLE hThread, const CONTEXT* ctx,
+                             enum cpu_addr ca, ADDRESS64* addr)
+{
+   switch (ca)
+    {
+#if defined(__powerpc__)
+    case cpu_addr_pc:
+        addr->Mode    = AddrModeFlat;
+        addr->Segment = 0; /* don't need segment */
+        addr->Offset  = ctx->Iar;
+        return TRUE;
+#endif
+    default:
+    case cpu_addr_stack:
+    case cpu_addr_frame:
+        FIXME("not done\n");
+    }
+    return FALSE;
+}
+
+static BOOL ppc_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
+{
+    FIXME("not done\n");
+    return FALSE;
+}
+
+struct cpu cpu_ppc = {
+    IMAGE_FILE_MACHINE_POWERPC,
+    4,
+    ppc_get_addr,
+    ppc_stack_walk,
+};
diff --git a/dlls/dbghelp/cpu_x86_64.c b/dlls/dbghelp/cpu_x86_64.c
index 5678678..d7fb138 100644
--- a/dlls/dbghelp/cpu_x86_64.c
+++ b/dlls/dbghelp/cpu_x86_64.c
@@ -29,6 +29,22 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
 
+static unsigned x86_64_get_addr(HANDLE hThread, const CONTEXT* ctx,
+                                enum cpu_addr ca, ADDRESS64* addr)
+{
+    addr->Mode = AddrModeFlat;
+    switch (ca)
+    {
+#ifdef __x86_64__
+    case cpu_addr_pc:    addr->Segment = ctx->SegCs; addr->Offset = ctx->Rip; return TRUE;
+    case cpu_addr_stack: addr->Segment = ctx->SegSs; addr->Offset = ctx->Rsp; return TRUE;
+    case cpu_addr_frame: addr->Segment = ctx->SegSs; addr->Offset = ctx->Rbp; return TRUE;
+#endif
+    default: addr->Mode = -1;
+        return FALSE;
+    }
+}
+
 enum st_mode {stm_start, stm_64bit, stm_done};
 
 /* indexes in Reserved array */
@@ -111,5 +127,7 @@ done_err:
 
 struct cpu cpu_x86_64 = {
     IMAGE_FILE_MACHINE_AMD64,
+    8,
+    x86_64_get_addr,
     x86_64_stack_walk,
 };
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index 69150e1..d2e2f1b 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -443,9 +443,16 @@ struct cpu_stack_walk
     } u;
 };
 
+enum cpu_addr {cpu_addr_pc, cpu_addr_stack, cpu_addr_frame};
 struct cpu
 {
     DWORD       machine;
+    DWORD       word_size;
+    /* address manipulation */
+    unsigned    (*get_addr)(HANDLE hThread, const CONTEXT* ctx,
+                            enum cpu_addr, ADDRESS64* addr);
+
+    /* stack manipulation */
     BOOL        (*stack_walk)(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame);
 };
 
diff --git a/dlls/dbghelp/minidump.c b/dlls/dbghelp/minidump.c
index b026d32..7248cea 100644
--- a/dlls/dbghelp/minidump.c
+++ b/dlls/dbghelp/minidump.c
@@ -115,58 +115,25 @@ static void fetch_thread_stack(struct dump_context* dc, const void* teb_addr,
                                const CONTEXT* ctx, MINIDUMP_MEMORY_DESCRIPTOR* mmd)
 {
     NT_TIB      tib;
+    ADDRESS64   addr;
 
-    if (ReadProcessMemory(dc->hProcess, teb_addr, &tib, sizeof(tib), NULL))
+    if (ReadProcessMemory(dc->hProcess, teb_addr, &tib, sizeof(tib), NULL) &&
+        dbghelp_current_cpu &&
+        dbghelp_current_cpu->get_addr(NULL /* FIXME */, ctx, cpu_addr_stack, &addr) && addr.Mode == AddrModeFlat)
     {
-#ifdef __i386__
-        /* limiting the stack dumping to the size actually used */
-        if (ctx->Esp){
-
-            /* make sure ESP is within the established range of the stack.  It could have
-               been clobbered by whatever caused the original exception. */
-            if (ctx->Esp - 4 < (ULONG_PTR)tib.StackLimit || ctx->Esp - 4 > (ULONG_PTR)tib.StackBase)
-                mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
-            else
-                mmd->StartOfMemoryRange = (ctx->Esp - 4);
-        }
-
-        else
-            mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
-#elif defined(__powerpc__)
-        if (ctx->Iar){
-
-            /* make sure IAR is within the established range of the stack.  It could have
-               been clobbered by whatever caused the original exception. */
-            if (ctx->Iar - 4 < (ULONG_PTR)tib.StackLimit || ctx->Iar - 4 > (ULONG_PTR)tib.StackBase)
-                mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
-            else
-                mmd->StartOfMemoryRange = (ctx->Iar - 4);
-        }
-
-        else
-            mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
-#elif defined(__x86_64__)
-        if (ctx->Rsp){
-
-            /* make sure RSP is within the established range of the stack.  It could have
+        if (addr.Offset)
+        {
+            addr.Offset -= dbghelp_current_cpu->word_size;
+            /* make sure stack pointer is within the established range of the stack.  It could have
                been clobbered by whatever caused the original exception. */
-            if (ctx->Rsp - 8 < (ULONG_PTR)tib.StackLimit || ctx->Rsp - 8 > (ULONG_PTR)tib.StackBase)
+            if (addr.Offset < (ULONG_PTR)tib.StackLimit || addr.Offset > (ULONG_PTR)tib.StackBase)
                 mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
 
             else
-                mmd->StartOfMemoryRange = (ctx->Rsp - 8);
+                mmd->StartOfMemoryRange = addr.Offset;
         }
-
         else
             mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
-#else
-#error unsupported CPU
-#endif
         mmd->Memory.DataSize = (ULONG_PTR)tib.StackBase - mmd->StartOfMemoryRange;
     }
 }






More information about the wine-patches mailing list