[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