Module: wine Branch: master Commit: a672a51cbf06d8e8b9a55fa29ca5f093d4ed8c20 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a672a51cbf06d8e8b9a55fa29c...
Author: Eric Pouech eric.pouech@orange.fr Date: Mon Jan 23 21:37:16 2012 +0100
dbghelp: Allow each CPU backend to save CPU specific memory ranges in minidump.
Used this feature to add x86_64 unwind information.
---
dlls/dbghelp/cpu_arm.c | 7 +++++ dlls/dbghelp/cpu_i386.c | 9 +++++++ dlls/dbghelp/cpu_ppc.c | 7 +++++ dlls/dbghelp/cpu_sparc.c | 7 +++++ dlls/dbghelp/cpu_x86_64.c | 49 ++++++++++++++++++++++++++++++++++++++- dlls/dbghelp/dbghelp_private.h | 1 + dlls/dbghelp/minidump.c | 3 ++ 7 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/dlls/dbghelp/cpu_arm.c b/dlls/dbghelp/cpu_arm.c index 025955e..2712db4 100644 --- a/dlls/dbghelp/cpu_arm.c +++ b/dlls/dbghelp/cpu_arm.c @@ -228,6 +228,12 @@ static BOOL arm_fetch_minidump_thread(struct dump_context* dc, unsigned index, u return FALSE; }
+static BOOL arm_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags) +{ + FIXME("NIY\n"); + return FALSE; +} + DECLSPEC_HIDDEN struct cpu cpu_arm = { IMAGE_FILE_MACHINE_ARMV7, 4, @@ -239,4 +245,5 @@ DECLSPEC_HIDDEN struct cpu cpu_arm = { arm_fetch_context_reg, arm_fetch_regname, arm_fetch_minidump_thread, + arm_fetch_minidump_module, }; diff --git a/dlls/dbghelp/cpu_i386.c b/dlls/dbghelp/cpu_i386.c index b51d3fc..3a66def 100644 --- a/dlls/dbghelp/cpu_i386.c +++ b/dlls/dbghelp/cpu_i386.c @@ -673,6 +673,14 @@ static BOOL i386_fetch_minidump_thread(struct dump_context* dc, unsigned index, return TRUE; }
+static BOOL i386_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags) +{ + /* FIXME: actually, we should probably take care of FPO data, unless it's stored in + * function table minidump stream + */ + return FALSE; +} + DECLSPEC_HIDDEN struct cpu cpu_i386 = { IMAGE_FILE_MACHINE_I386, 4, @@ -684,4 +692,5 @@ DECLSPEC_HIDDEN struct cpu cpu_i386 = { i386_fetch_context_reg, i386_fetch_regname, i386_fetch_minidump_thread, + i386_fetch_minidump_module, }; diff --git a/dlls/dbghelp/cpu_ppc.c b/dlls/dbghelp/cpu_ppc.c index b142e4a..56571c5 100644 --- a/dlls/dbghelp/cpu_ppc.c +++ b/dlls/dbghelp/cpu_ppc.c @@ -78,6 +78,12 @@ static BOOL ppc_fetch_minidump_thread(struct dump_context* dc, unsigned index, u return FALSE; }
+static BOOL ppc_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags) +{ + FIXME("NIY\n"); + return FALSE; +} + DECLSPEC_HIDDEN struct cpu cpu_ppc = { IMAGE_FILE_MACHINE_POWERPC, 4, @@ -89,4 +95,5 @@ DECLSPEC_HIDDEN struct cpu cpu_ppc = { ppc_fetch_context_reg, ppc_fetch_regname, ppc_fetch_minidump_thread, + ppc_fetch_minidump_module, }; diff --git a/dlls/dbghelp/cpu_sparc.c b/dlls/dbghelp/cpu_sparc.c index bae1c22..7f5bfaa 100644 --- a/dlls/dbghelp/cpu_sparc.c +++ b/dlls/dbghelp/cpu_sparc.c @@ -85,6 +85,12 @@ static BOOL sparc_fetch_minidump_thread(struct dump_context* dc, unsigned index, return FALSE; }
+static BOOL sparc_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags) +{ + FIXME("NIY\n"); + return FALSE; +} + DECLSPEC_HIDDEN struct cpu cpu_sparc = { IMAGE_FILE_MACHINE_SPARC, 4, @@ -96,4 +102,5 @@ DECLSPEC_HIDDEN struct cpu cpu_sparc = { sparc_fetch_context_reg, sparc_fetch_regname, sparc_fetch_minidump_thread, + sparc_fetch_minidump_module, }; diff --git a/dlls/dbghelp/cpu_x86_64.c b/dlls/dbghelp/cpu_x86_64.c index 695588e..8de28ef 100644 --- a/dlls/dbghelp/cpu_x86_64.c +++ b/dlls/dbghelp/cpu_x86_64.c @@ -145,7 +145,7 @@ static void dump_unwind_info(struct cpu_stack_walk* csw, ULONG64 base, RUNTIME_F { if (!sw_read_mem(csw, base + function->UnwindData, &snext, sizeof(snext))) { - TRACE("Couldn't unwind RUNTIME_INFO\n"); + TRACE("Couldn't unwind RUNTIME_INFO at %lx\n", base + function->UnwindData); return; } TRACE("unwind info for function %p-%p chained to function %p-%p\n", @@ -159,7 +159,7 @@ static void dump_unwind_info(struct cpu_stack_walk* csw, ULONG64 base, RUNTIME_F !sw_read_mem(csw, addr + FIELD_OFFSET(UNWIND_INFO, UnwindCode), info->UnwindCode, info->CountOfCodes * sizeof(UNWIND_CODE))) { - FIXME("couldn't read memory for UNWIND_INFO\n"); + FIXME("couldn't read memory for UNWIND_INFO at %lx\n", addr); return; } TRACE("unwind info at %p flags %x prolog 0x%x bytes function %p-%p\n", @@ -904,6 +904,50 @@ static BOOL x86_64_fetch_minidump_thread(struct dump_context* dc, unsigned index return TRUE; }
+static BOOL x86_64_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags) +{ + /* FIXME: not sure about the flags... */ + if (1) + { + /* FIXME: crop values across module boundaries, */ +#ifdef __x86_64__ + struct process* pcs; + struct module* module; + const RUNTIME_FUNCTION* rtf; + ULONG size; + + if (!(pcs = process_find_by_handle(dc->hProcess)) || + !(module = module_find_by_addr(pcs, dc->modules[index].base, DMT_UNKNOWN))) + return FALSE; + rtf = (const RUNTIME_FUNCTION*)pe_map_directory(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size); + if (rtf) + { + const RUNTIME_FUNCTION* end = (const RUNTIME_FUNCTION*)((const char*)rtf + size); + UNWIND_INFO ui; + + while (rtf + 1 < end) + { + while (rtf->UnwindData & 1) /* follow chained entry */ + { + FIXME("RunTime_Function outside IMAGE_DIRECTORY_ENTRY_EXCEPTION unimplemented yet!\n"); + return FALSE; + /* we need to read into the other process */ + /* rtf = (RUNTIME_FUNCTION*)(module->module.BaseOfImage + (rtf->UnwindData & ~1)); */ + } + if (ReadProcessMemory(dc->hProcess, + (void*)(dc->modules[index].base + rtf->UnwindData), + &ui, sizeof(ui), NULL)) + minidump_add_memory_block(dc, dc->modules[index].base + rtf->UnwindData, + FIELD_OFFSET(UNWIND_INFO, UnwindCode) + ui.CountOfCodes * sizeof(UNWIND_CODE), 0); + rtf++; + } + } +#endif + } + + return TRUE; +} + DECLSPEC_HIDDEN struct cpu cpu_x86_64 = { IMAGE_FILE_MACHINE_AMD64, 8, @@ -915,4 +959,5 @@ DECLSPEC_HIDDEN struct cpu cpu_x86_64 = { x86_64_fetch_context_reg, x86_64_fetch_regname, x86_64_fetch_minidump_thread, + x86_64_fetch_minidump_module, }; diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 3bee416..f18a0fe 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -538,6 +538,7 @@ struct cpu
/* minidump per CPU extension */ BOOL (*fetch_minidump_thread)(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx); + BOOL (*fetch_minidump_module)(struct dump_context* dc, unsigned index, unsigned flags); };
extern struct cpu* dbghelp_current_cpu DECLSPEC_HIDDEN; diff --git a/dlls/dbghelp/minidump.c b/dlls/dbghelp/minidump.c index fa3cfae..c0882b0 100644 --- a/dlls/dbghelp/minidump.c +++ b/dlls/dbghelp/minidump.c @@ -513,6 +513,9 @@ static unsigned dump_modules(struct dump_context* dc, BOOL dump_elf) } if (flags_out & ModuleWriteModule) { + /* fetch CPU dependant module info (like UNWIND_INFO) */ + dbghelp_current_cpu->fetch_minidump_module(dc, i, flags_out); + mdModule.BaseOfImage = dc->modules[i].base; mdModule.SizeOfImage = dc->modules[i].size; mdModule.CheckSum = dc->modules[i].checksum;