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 = \
|
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 @@
|
||||||
|
|
||||||
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:
|
||||||
|
|
||||||
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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
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:
|
||||||
|
|
||||||
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
|
||||||
} 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,
|
||||||
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. */
|
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;
|
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
|
||||||
|
|
||||||
else
|
else
|
||||||
mmd->StartOfMemoryRange = (ctx->Esp - 4);
|
mmd->StartOfMemoryRange = addr.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
|
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;
|
mmd->Memory.DataSize = (ULONG_PTR)tib.StackBase - mmd->StartOfMemoryRange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue