Module: wine Branch: master Commit: ed96e740e9f3d378c0694d93dfd3b6cba3e087e0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=ed96e740e9f3d378c0694d93df...
Author: Eric Pouech eric.pouech@orange.fr Date: Tue Dec 22 14:21:37 2009 +0100
dbghelp: Add a couple of helpers to struct cpu to help adding the stack to minidump.
---
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(-)
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 1dc7dc3..3cddb72 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; } }