Commit ed96e740 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

dbghelp: Add a couple of helpers to struct cpu to help adding the stack to minidump.

parent 54766cda
...@@ -11,6 +11,7 @@ DELAYIMPORTS = version ...@@ -11,6 +11,7 @@ DELAYIMPORTS = version
C_SRCS = \ C_SRCS = \
coff.c \ coff.c \
cpu_i386.c \ cpu_i386.c \
cpu_ppc.c \
cpu_x86_64.c \ cpu_x86_64.c \
crc32.c \ crc32.c \
dbghelp.c \ dbghelp.c \
......
...@@ -29,6 +29,64 @@ ...@@ -29,6 +29,64 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); 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}; enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
/* indexes in Reserved array */ /* indexes in Reserved array */
...@@ -344,5 +402,7 @@ done_err: ...@@ -344,5 +402,7 @@ done_err:
struct cpu cpu_i386 = { struct cpu cpu_i386 = {
IMAGE_FILE_MACHINE_I386, IMAGE_FILE_MACHINE_I386,
4,
i386_get_addr,
i386_stack_walk, i386_stack_walk,
}; };
/*
* 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,
};
...@@ -29,6 +29,22 @@ ...@@ -29,6 +29,22 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); 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}; enum st_mode {stm_start, stm_64bit, stm_done};
/* indexes in Reserved array */ /* indexes in Reserved array */
...@@ -111,5 +127,7 @@ done_err: ...@@ -111,5 +127,7 @@ done_err:
struct cpu cpu_x86_64 = { struct cpu cpu_x86_64 = {
IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_AMD64,
8,
x86_64_get_addr,
x86_64_stack_walk, x86_64_stack_walk,
}; };
...@@ -443,9 +443,16 @@ struct cpu_stack_walk ...@@ -443,9 +443,16 @@ struct cpu_stack_walk
} u; } u;
}; };
enum cpu_addr {cpu_addr_pc, cpu_addr_stack, cpu_addr_frame};
struct cpu struct cpu
{ {
DWORD machine; 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); BOOL (*stack_walk)(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame);
}; };
......
...@@ -115,58 +115,25 @@ static void fetch_thread_stack(struct dump_context* dc, const void* teb_addr, ...@@ -115,58 +115,25 @@ static void fetch_thread_stack(struct dump_context* dc, const void* teb_addr,
const CONTEXT* ctx, MINIDUMP_MEMORY_DESCRIPTOR* mmd) const CONTEXT* ctx, MINIDUMP_MEMORY_DESCRIPTOR* mmd)
{ {
NT_TIB tib; 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__ if (addr.Offset)
/* limiting the stack dumping to the size actually used */ {
if (ctx->Esp){ addr.Offset -= dbghelp_current_cpu->word_size;
/* make sure stack pointer is within the established range of the stack. It could have
/* 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
been clobbered by whatever caused the original exception. */ 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; mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
else else
mmd->StartOfMemoryRange = (ctx->Rsp - 8); mmd->StartOfMemoryRange = addr.Offset;
} }
else else
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit; mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
#else
#error unsupported CPU
#endif
mmd->Memory.DataSize = (ULONG_PTR)tib.StackBase - mmd->StartOfMemoryRange; mmd->Memory.DataSize = (ULONG_PTR)tib.StackBase - mmd->StartOfMemoryRange;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment