Piotr Caban : msvcrt: Dump exception information in x86_64 __CxxFrameHandler.

Alexandre Julliard julliard at winehq.org
Thu Jun 16 03:45:41 CDT 2016


Module: wine
Branch: stable
Commit: 8d69049c0dfef130e0897624abbaaf7fbd2ea426
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=8d69049c0dfef130e0897624abbaaf7fbd2ea426

Author: Piotr Caban <piotr at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit 3350364d8b7f44e328c9e8f564a836ad23b4104f)
Signed-off-by: Michael Stefaniuc <mstefani at 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) );
 }
 
 




More information about the wine-cvs mailing list