[PATCH 1/5] vcruntime140_1: Support flag 0x2 in unwind table.

Daniel Lehman dlehman25 at gmail.com
Tue Jun 2 20:56:13 CDT 2020


Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---

supercedes https://source.winehq.org/patches/data/185973

with /O2 the unwind table provides a direct frame+offset of the object to unwind
with /Od the unwind table sets flag 0x2 signaling only a frame is passed; the
handler itself adds the offset of the object to unwind

seems safe to pass both; both %rcx and %rdx are volatile and one is ignored

by comparison, FH3 currently always calls: unwind_handler(0, frame)

sample repro:
/* cl /EHs /Od /MD test.cpp */
'#include <stdio.h>

class test {
public:
     test(int d) : id(d) { printf("ctor %x\n", id); }
     ~test() { printf("dtor %x\n", id); }
     int id;
};

int main(void)
{
    try { test t(0x42); throw 1; }
    catch (int i) { printf("catch %d\n", i); }
    return 0;
}

Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---
 dlls/vcruntime140_1/except_x86_64.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/dlls/vcruntime140_1/except_x86_64.c b/dlls/vcruntime140_1/except_x86_64.c
index e1a39c0662..fec133932f 100644
--- a/dlls/vcruntime140_1/except_x86_64.c
+++ b/dlls/vcruntime140_1/except_x86_64.c
@@ -77,6 +77,9 @@ typedef struct
 #define TYPE_FLAG_VOLATILE   2
 #define TYPE_FLAG_REFERENCE  8
 
+#define UNWIND_FLAG_HANDLER   1
+#define UNWIND_FLAG_USE_FRAME 2
+
 typedef struct
 {
     UINT start_level;
@@ -156,7 +159,7 @@ static inline void* rva_to_ptr(UINT rva, ULONG64 base)
     return rva ? (void*)(base+rva) : NULL;
 }
 
-static BOOL read_unwind_info(BYTE **b, unwind_info *ui)
+static void read_unwind_info(BYTE **b, unwind_info *ui)
 {
     BYTE *p = *b;
 
@@ -165,18 +168,12 @@ static BOOL read_unwind_info(BYTE **b, unwind_info *ui)
     ui->prev = p - (ui->flags >> 2);
     ui->flags &= 0x3;
 
-    if (ui->flags & 0x1)
+    if (ui->flags & UNWIND_FLAG_HANDLER)
     {
         ui->handler = read_rva(b);
-        ui->object = decode_uint(b); /* frame offset */
-    }
-
-    if (ui->flags & 0x2)
-    {
-        FIXME("unknown flag: %x\n", ui->flags);
-        return FALSE;
+        if (!(ui->flags & UNWIND_FLAG_USE_FRAME))
+            ui->object = decode_uint(b); /* frame offset */
     }
-    return TRUE;
 }
 
 static void read_tryblock_info(BYTE **b, tryblock_info *ti, ULONG64 image_base)
@@ -268,7 +265,7 @@ static BOOL validate_cxx_function_descr4(const cxx_function_descr *descr, DISPAT
         BYTE *entry = unwind_map;
         unwind_info ui;
 
-        if (!read_unwind_info(&unwind_map, &ui)) return FALSE;
+        read_unwind_info(&unwind_map, &ui);
         if (ui.prev < (BYTE*)rva_to_ptr(descr->unwind_map, image_base)) ui.prev = NULL;
         TRACE("    %d (%p): flags 0x%x prev %p func 0x%x(%p) object 0x%x\n",
                 i, entry, ui.flags, ui.prev, ui.handler,
@@ -403,7 +400,7 @@ static inline void copy_exception(void *object, ULONG64 frame, DISPATCHER_CONTEX
 static void cxx_local_unwind4(ULONG64 frame, DISPATCHER_CONTEXT *dispatch,
         const cxx_function_descr *descr, int trylevel, int last_level)
 {
-    void (__cdecl *handler_dtor)(void *obj);
+    void (__cdecl *handler_dtor)(void *obj, ULONG64 frame);
     BYTE *unwind_data, *last;
     unwind_info ui;
     void *obj;
@@ -442,7 +439,7 @@ static void cxx_local_unwind4(ULONG64 frame, DISPATCHER_CONTEXT *dispatch,
             handler_dtor = rva_to_ptr(ui.handler, dispatch->ImageBase);
             obj = rva_to_ptr(ui.object, frame);
             TRACE("handler: %p object: %p\n", handler_dtor, obj);
-            handler_dtor(obj);
+            handler_dtor(obj, frame);
         }
     }
 }
-- 
2.17.1




More information about the wine-devel mailing list