dbghelp: Add a couple of helpers to struct cpu to help adding the stack to minidump.
This commit is contained in:
parent
54766cdac0
commit
ed96e740e9
|
@ -11,6 +11,7 @@ DELAYIMPORTS = version
|
|||
C_SRCS = \
|
||||
coff.c \
|
||||
cpu_i386.c \
|
||||
cpu_ppc.c \
|
||||
cpu_x86_64.c \
|
||||
crc32.c \
|
||||
dbghelp.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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
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->Esp - 4 < (ULONG_PTR)tib.StackLimit || ctx->Esp - 4 > (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->Esp - 4);
|
||||
mmd->StartOfMemoryRange = addr.Offset;
|
||||
}
|
||||
|
||||
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. */
|
||||
if (ctx->Rsp - 8 < (ULONG_PTR)tib.StackLimit || ctx->Rsp - 8 > (ULONG_PTR)tib.StackBase)
|
||||
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
|
||||
|
||||
else
|
||||
mmd->StartOfMemoryRange = (ctx->Rsp - 8);
|
||||
}
|
||||
|
||||
else
|
||||
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
|
||||
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
mmd->Memory.DataSize = (ULONG_PTR)tib.StackBase - mmd->StartOfMemoryRange;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue