dbghelp: Allow CPU backends to add specific information into a minidump.
Use it to add a 256 byte block around current program counter.
This commit is contained in:
parent
d02295d998
commit
1c5450f91f
|
@ -222,6 +222,12 @@ static const char* arm_fetch_regname(unsigned regno)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL arm_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
|
||||
{
|
||||
FIXME("NIY\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DECLSPEC_HIDDEN struct cpu cpu_arm = {
|
||||
IMAGE_FILE_MACHINE_ARMV7,
|
||||
4,
|
||||
|
@ -232,4 +238,5 @@ DECLSPEC_HIDDEN struct cpu cpu_arm = {
|
|||
arm_map_dwarf_register,
|
||||
arm_fetch_context_reg,
|
||||
arm_fetch_regname,
|
||||
arm_fetch_minidump_thread,
|
||||
};
|
||||
|
|
|
@ -659,6 +659,20 @@ static const char* i386_fetch_regname(unsigned regno)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL i386_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
|
||||
{
|
||||
if (ctx->ContextFlags && (flags & ThreadWriteInstructionWindow))
|
||||
{
|
||||
/* FIXME: crop values across module boundaries, */
|
||||
#ifdef __i386__
|
||||
ULONG base = ctx->Eip <= 0x80 ? 0 : ctx->Eip - 0x80;
|
||||
minidump_add_memory_block(dc, base, ctx->Eip + 0x80 - base, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DECLSPEC_HIDDEN struct cpu cpu_i386 = {
|
||||
IMAGE_FILE_MACHINE_I386,
|
||||
4,
|
||||
|
@ -669,4 +683,5 @@ DECLSPEC_HIDDEN struct cpu cpu_i386 = {
|
|||
i386_map_dwarf_register,
|
||||
i386_fetch_context_reg,
|
||||
i386_fetch_regname,
|
||||
i386_fetch_minidump_thread,
|
||||
};
|
||||
|
|
|
@ -72,6 +72,12 @@ static const char* ppc_fetch_regname(unsigned regno)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL ppc_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
|
||||
{
|
||||
FIXME("NIY\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DECLSPEC_HIDDEN struct cpu cpu_ppc = {
|
||||
IMAGE_FILE_MACHINE_POWERPC,
|
||||
4,
|
||||
|
@ -82,4 +88,5 @@ DECLSPEC_HIDDEN struct cpu cpu_ppc = {
|
|||
ppc_map_dwarf_register,
|
||||
ppc_fetch_context_reg,
|
||||
ppc_fetch_regname,
|
||||
ppc_fetch_minidump_thread,
|
||||
};
|
||||
|
|
|
@ -79,6 +79,12 @@ static const char* sparc_fetch_regname(unsigned regno)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL sparc_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
|
||||
{
|
||||
FIXME("NIY\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DECLSPEC_HIDDEN struct cpu cpu_sparc = {
|
||||
IMAGE_FILE_MACHINE_SPARC,
|
||||
4,
|
||||
|
@ -89,4 +95,5 @@ DECLSPEC_HIDDEN struct cpu cpu_sparc = {
|
|||
sparc_map_dwarf_register,
|
||||
sparc_fetch_context_reg,
|
||||
sparc_fetch_regname,
|
||||
sparc_fetch_minidump_thread,
|
||||
};
|
||||
|
|
|
@ -890,6 +890,20 @@ static const char* x86_64_fetch_regname(unsigned regno)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL x86_64_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
|
||||
{
|
||||
if (ctx->ContextFlags && (flags & ThreadWriteInstructionWindow))
|
||||
{
|
||||
/* FIXME: crop values across module boundaries, */
|
||||
#ifdef __x86_64__
|
||||
ULONG64 base = ctx->Rip <= 0x80 ? 0 : ctx->Rip - 0x80;
|
||||
minidump_add_memory_block(dc, base, ctx->Rip + 0x80 - base, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DECLSPEC_HIDDEN struct cpu cpu_x86_64 = {
|
||||
IMAGE_FILE_MACHINE_AMD64,
|
||||
8,
|
||||
|
@ -900,4 +914,5 @@ DECLSPEC_HIDDEN struct cpu cpu_x86_64 = {
|
|||
x86_64_map_dwarf_register,
|
||||
x86_64_fetch_context_reg,
|
||||
x86_64_fetch_regname,
|
||||
x86_64_fetch_minidump_thread,
|
||||
};
|
||||
|
|
|
@ -463,6 +463,55 @@ struct cpu_stack_walk
|
|||
} u;
|
||||
};
|
||||
|
||||
struct dump_memory
|
||||
{
|
||||
ULONG64 base;
|
||||
ULONG size;
|
||||
ULONG rva;
|
||||
};
|
||||
|
||||
struct dump_module
|
||||
{
|
||||
unsigned is_elf;
|
||||
ULONG64 base;
|
||||
ULONG size;
|
||||
DWORD timestamp;
|
||||
DWORD checksum;
|
||||
WCHAR name[MAX_PATH];
|
||||
};
|
||||
|
||||
struct dump_thread
|
||||
{
|
||||
ULONG tid;
|
||||
ULONG prio_class;
|
||||
ULONG curr_prio;
|
||||
};
|
||||
|
||||
struct dump_context
|
||||
{
|
||||
/* process & thread information */
|
||||
HANDLE hProcess;
|
||||
DWORD pid;
|
||||
unsigned flags_out;
|
||||
/* thread information */
|
||||
struct dump_thread* threads;
|
||||
unsigned num_threads;
|
||||
/* module information */
|
||||
struct dump_module* modules;
|
||||
unsigned num_modules;
|
||||
unsigned alloc_modules;
|
||||
/* exception information */
|
||||
/* output information */
|
||||
MINIDUMP_TYPE type;
|
||||
HANDLE hFile;
|
||||
RVA rva;
|
||||
struct dump_memory* mem;
|
||||
unsigned num_mem;
|
||||
unsigned alloc_mem;
|
||||
/* callback information */
|
||||
MINIDUMP_CALLBACK_INFORMATION* cb;
|
||||
};
|
||||
|
||||
enum cpu_addr {cpu_addr_pc, cpu_addr_stack, cpu_addr_frame};
|
||||
struct cpu
|
||||
{
|
||||
|
@ -486,6 +535,9 @@ struct cpu
|
|||
/* context related manipulation */
|
||||
void* (*fetch_context_reg)(CONTEXT* context, unsigned regno, unsigned* size);
|
||||
const char* (*fetch_regname)(unsigned regno);
|
||||
|
||||
/* minidump per CPU extension */
|
||||
BOOL (*fetch_minidump_thread)(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx);
|
||||
};
|
||||
|
||||
extern struct cpu* dbghelp_current_cpu DECLSPEC_HIDDEN;
|
||||
|
@ -527,6 +579,9 @@ extern struct module*
|
|||
extern BOOL macho_read_wine_loader_dbg_info(struct process* pcs) DECLSPEC_HIDDEN;
|
||||
extern BOOL macho_synchronize_module_list(struct process* pcs) DECLSPEC_HIDDEN;
|
||||
|
||||
/* minidump.c */
|
||||
void minidump_add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva);
|
||||
|
||||
/* module.c */
|
||||
extern const WCHAR S_ElfW[] DECLSPEC_HIDDEN;
|
||||
extern const WCHAR S_WineLoaderW[] DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -32,54 +32,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||
|
||||
struct dump_memory
|
||||
{
|
||||
ULONG64 base;
|
||||
ULONG size;
|
||||
ULONG rva;
|
||||
};
|
||||
|
||||
struct dump_module
|
||||
{
|
||||
unsigned is_elf;
|
||||
ULONG64 base;
|
||||
ULONG size;
|
||||
DWORD timestamp;
|
||||
DWORD checksum;
|
||||
WCHAR name[MAX_PATH];
|
||||
};
|
||||
|
||||
struct dump_thread
|
||||
{
|
||||
ULONG tid;
|
||||
ULONG prio_class;
|
||||
ULONG curr_prio;
|
||||
};
|
||||
|
||||
struct dump_context
|
||||
{
|
||||
/* process & thread information */
|
||||
HANDLE hProcess;
|
||||
DWORD pid;
|
||||
/* thread information */
|
||||
struct dump_thread* threads;
|
||||
unsigned num_threads;
|
||||
/* module information */
|
||||
struct dump_module* modules;
|
||||
unsigned num_modules;
|
||||
unsigned alloc_modules;
|
||||
/* exception information */
|
||||
/* output information */
|
||||
MINIDUMP_TYPE type;
|
||||
HANDLE hFile;
|
||||
RVA rva;
|
||||
struct dump_memory* mem;
|
||||
unsigned num_mem;
|
||||
unsigned alloc_mem;
|
||||
/* callback information */
|
||||
MINIDUMP_CALLBACK_INFORMATION* cb;
|
||||
};
|
||||
|
||||
/******************************************************************
|
||||
* fetch_process_info
|
||||
*
|
||||
|
@ -376,14 +328,14 @@ static void fetch_module_versioninfo(LPCWSTR filename, VS_FIXEDFILEINFO* ffi)
|
|||
}
|
||||
|
||||
/******************************************************************
|
||||
* add_memory_block
|
||||
* minidump_add_memory_block
|
||||
*
|
||||
* Add a memory block to be dumped in a minidump
|
||||
* If rva is non 0, it's the rva in the minidump where has to be stored
|
||||
* also the rva of the memory block when written (this allows to reference
|
||||
* a memory block from outside the list of memory blocks).
|
||||
*/
|
||||
static void add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva)
|
||||
void minidump_add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva)
|
||||
{
|
||||
if (!dc->mem)
|
||||
{
|
||||
|
@ -806,11 +758,11 @@ static unsigned dump_threads(struct dump_context* dc,
|
|||
}
|
||||
if (mdThd.Stack.Memory.DataSize && (flags_out & ThreadWriteStack))
|
||||
{
|
||||
add_memory_block(dc, mdThd.Stack.StartOfMemoryRange,
|
||||
mdThd.Stack.Memory.DataSize,
|
||||
rva_base + sizeof(mdThdList.NumberOfThreads) +
|
||||
mdThdList.NumberOfThreads * sizeof(mdThd) +
|
||||
FIELD_OFFSET(MINIDUMP_THREAD, Stack.Memory.Rva));
|
||||
minidump_add_memory_block(dc, mdThd.Stack.StartOfMemoryRange,
|
||||
mdThd.Stack.Memory.DataSize,
|
||||
rva_base + sizeof(mdThdList.NumberOfThreads) +
|
||||
mdThdList.NumberOfThreads * sizeof(mdThd) +
|
||||
FIELD_OFFSET(MINIDUMP_THREAD, Stack.Memory.Rva));
|
||||
}
|
||||
writeat(dc,
|
||||
rva_base + sizeof(mdThdList.NumberOfThreads) +
|
||||
|
@ -818,14 +770,8 @@ static unsigned dump_threads(struct dump_context* dc,
|
|||
&mdThd, sizeof(mdThd));
|
||||
mdThdList.NumberOfThreads++;
|
||||
}
|
||||
if (ctx.ContextFlags && (flags_out & ThreadWriteInstructionWindow))
|
||||
{
|
||||
/* FIXME: - Native dbghelp also dumps 0x80 bytes around EIP
|
||||
* - also crop values across module boundaries,
|
||||
* - and don't make it i386 dependent
|
||||
*/
|
||||
/* add_memory_block(dc, ctx.Eip - 0x80, ctx.Eip + 0x80, 0); */
|
||||
}
|
||||
/* fetch CPU dependent thread info (like 256 bytes around program counter */
|
||||
dbghelp_current_cpu->fetch_minidump_thread(dc, i, flags_out, &ctx);
|
||||
}
|
||||
writeat(dc, rva_base,
|
||||
&mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads));
|
||||
|
|
Loading…
Reference in New Issue