Module: wine Branch: stable Commit: 8d69049c0dfef130e0897624abbaaf7fbd2ea426 URL: http://source.winehq.org/git/wine.git/?a=commit;h=8d69049c0dfef130e0897624ab...
Author: Piotr Caban piotr@codeweavers.com Date: Mon Mar 21 18:23:34 2016 +0100
msvcrt: Dump exception information in x86_64 __CxxFrameHandler.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org (cherry picked from commit 3350364d8b7f44e328c9e8f564a836ad23b4104f) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
dlls/msvcrt/except_x86_64.c | 157 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcrt/except_x86_64.c b/dlls/msvcrt/except_x86_64.c index 27d0a15..7b62c4d 100644 --- a/dlls/msvcrt/except_x86_64.c +++ b/dlls/msvcrt/except_x86_64.c @@ -61,6 +61,160 @@ typedef struct _DISPATCHER_CONTEXT ULONG ScopeIndex; } DISPATCHER_CONTEXT;
+typedef struct +{ + int prev; + UINT handler; +} unwind_info; + +typedef struct +{ + UINT flags; + UINT type_info; + int offset; + UINT handler; +} catchblock_info; + +typedef struct +{ + int start_level; + int end_level; + int catch_level; + int catchblock_count; + UINT catchblock; +} tryblock_info; + +typedef struct __cxx_function_descr +{ + UINT magic; + UINT unwind_count; + UINT unwind_table; + UINT tryblock_count; + UINT tryblock; + UINT ipmap_count; + UINT ipmap; + UINT unwind_help; + UINT expect_list; + UINT flags; +} cxx_function_descr; + +static inline void* rva_to_ptr(UINT rva, ULONG64 base) +{ + return rva ? (void*)(base+rva) : NULL; +} + +static inline void dump_type(UINT type_rva, ULONG64 base) +{ + const cxx_type_info *type = rva_to_ptr(type_rva, base); + + TRACE("flags %x type %x %s offsets %d,%d,%d size %d copy ctor %x(%p)\n", + type->flags, type->type_info, dbgstr_type_info(rva_to_ptr(type->type_info, base)), + type->offsets.this_offset, type->offsets.vbase_descr, type->offsets.vbase_offset, + type->size, type->copy_ctor, rva_to_ptr(type->copy_ctor, base)); +} + +static void dump_exception_type(const cxx_exception_type *type, ULONG64 base) +{ + const cxx_type_info_table *type_info_table = rva_to_ptr(type->type_info_table, base); + UINT i; + + TRACE("flags %x destr %x(%p) handler %x(%p) type info %x(%p)\n", + type->flags, type->destructor, rva_to_ptr(type->destructor, base), + type->custom_handler, rva_to_ptr(type->custom_handler, base), + type->type_info_table, type_info_table); + for (i = 0; i < type_info_table->count; i++) + { + TRACE(" %d: ", i); + dump_type(type_info_table->info[i], base); + } +} + +static void dump_function_descr(const cxx_function_descr *descr, ULONG64 image_base) +{ + unwind_info *unwind_table = rva_to_ptr(descr->unwind_table, image_base); + tryblock_info *tryblock = rva_to_ptr(descr->tryblock, image_base); + UINT i, j; + + TRACE("magic %x\n", descr->magic); + TRACE("unwind table: %x(%p) %d\n", descr->unwind_table, unwind_table, descr->unwind_count); + for (i=0; i<descr->unwind_count; i++) + { + TRACE(" %d: prev %d func %x(%p)\n", i, unwind_table[i].prev, + unwind_table[i].handler, rva_to_ptr(unwind_table[i].handler, image_base)); + } + TRACE("try table: %x(%p) %d\n", descr->tryblock, tryblock, descr->tryblock_count); + for (i=0; i<descr->tryblock_count; i++) + { + catchblock_info *catchblock = rva_to_ptr(tryblock[i].catchblock, image_base); + + TRACE(" %d: start %d end %d catchlevel %d catch%x(%p) %d\n", i, + tryblock[i].start_level, tryblock[i].end_level, + tryblock[i].catch_level, tryblock[i].catchblock, + catchblock, tryblock[i].catchblock_count); + for (j=0; j<tryblock[i].catchblock_count; j++) + { + TRACE(" %d: flags %x offset %d handler %x(%p) type %x %s\n", + j, catchblock->flags, catchblock->offset, catchblock->handler, + rva_to_ptr(catchblock->handler, image_base), catchblock->type_info, + dbgstr_type_info(rva_to_ptr(catchblock->type_info, image_base))); + } + } + TRACE("unwind_help %d\n", descr->unwind_help); + TRACE("expect list: %x\n", descr->expect_list); + TRACE("flags: %08x\n", descr->flags); +} + +static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame, + CONTEXT *context, DISPATCHER_CONTEXT *dispatch, + const cxx_function_descr *descr) +{ + cxx_exception_type *exc_type; + + if (descr->magic != CXX_FRAME_MAGIC_VC8) + { + FIXME("unhandled frame magic %x\n", descr->magic); + return ExceptionContinueSearch; + } + + if (rec->ExceptionFlags & (EH_UNWINDING|EH_EXIT_UNWIND)) + return ExceptionContinueSearch; + if (!descr->tryblock_count) return ExceptionContinueSearch; + + if (rec->ExceptionCode == CXX_EXCEPTION && + rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) + { + *rec = *msvcrt_get_thread_data()->exc_record; + rec->ExceptionFlags &= ~EH_UNWINDING; + if (TRACE_ON(seh)) { + TRACE("detect rethrow: exception code: %x\n", rec->ExceptionCode); + if (rec->ExceptionCode == CXX_EXCEPTION) + TRACE("re-propage: obj: %lx, type: %lx\n", + rec->ExceptionInformation[1], rec->ExceptionInformation[2]); + } + } + + if (rec->ExceptionCode == CXX_EXCEPTION) + { + exc_type = (cxx_exception_type *)rec->ExceptionInformation[2]; + + if (TRACE_ON(seh)) + { + TRACE("handling C++ exception rec %p frame %lx unwind_help %d descr %p\n", + rec, frame, *((INT*)(frame+descr->unwind_help)), descr); + dump_exception_type(exc_type, rec->ExceptionInformation[3]); + dump_function_descr(descr, dispatch->ImageBase); + } + } + else + { + exc_type = NULL; + TRACE("handling C exception code %x rec %p frame %lx unwind_help %d descr %p\n", + rec->ExceptionCode, rec, frame, *((INT*)(frame+descr->unwind_help)), descr); + } + + return ExceptionContinueSearch; +} + /********************************************************************* * __CxxExceptionFilter (MSVCRT.@) */ @@ -78,7 +232,8 @@ EXCEPTION_DISPOSITION CDECL __CxxFrameHandler( EXCEPTION_RECORD *rec, ULONG64 fr CONTEXT *context, DISPATCHER_CONTEXT *dispatch ) { FIXME( "%p %lx %p %p: not implemented\n", rec, frame, context, dispatch ); - return ExceptionContinueSearch; + return cxx_frame_handler( rec, frame, context, dispatch, + rva_to_ptr(*(UINT*)dispatch->HandlerData, dispatch->ImageBase) ); }