Piotr Caban : vcruntime140_1: Add support for exception separated code segments.
Alexandre Julliard
julliard at winehq.org
Mon Dec 6 16:07:59 CST 2021
Module: wine
Branch: master
Commit: 9ccd84b945c4935e200becfe08a9a5bdb4799bd5
URL: https://source.winehq.org/git/wine.git/?a=commit;h=9ccd84b945c4935e200becfe08a9a5bdb4799bd5
Author: Piotr Caban <piotr at codeweavers.com>
Date: Sat Dec 4 18:15:06 2021 +0100
vcruntime140_1: Add support for exception separated code segments.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51396
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/vcruntime140_1/except_x86_64.c | 62 ++++++++++++++++++++++++++++++-------
1 file changed, 50 insertions(+), 12 deletions(-)
diff --git a/dlls/vcruntime140_1/except_x86_64.c b/dlls/vcruntime140_1/except_x86_64.c
index f50847d886d..b29a2baa696 100644
--- a/dlls/vcruntime140_1/except_x86_64.c
+++ b/dlls/vcruntime140_1/except_x86_64.c
@@ -74,6 +74,7 @@ typedef struct
#define CATCHBLOCK_FLAGS 0x01
#define CATCHBLOCK_TYPE_INFO 0x02
#define CATCHBLOCK_OFFSET 0x04
+#define CATCHBLOCK_SEPARATED 0x08
#define CATCHBLOCK_RET_ADDR_MASK 0x30
#define CATCHBLOCK_RET_ADDR 0x10
#define CATCHBLOCK_TWO_RET_ADDRS 0x20
@@ -219,13 +220,14 @@ static void read_tryblock_info(BYTE **b, tryblock_info *ti, ULONG64 image_base)
}
}
-static BOOL read_catchblock_info(BYTE **b, catchblock_info *ci)
+static BOOL read_catchblock_info(BYTE **b, catchblock_info *ci, DWORD func_rva)
{
BYTE ret_addr_type;
memset(ci, 0, sizeof(*ci));
ci->header = **b;
(*b)++;
- if (ci->header & ~(CATCHBLOCK_FLAGS | CATCHBLOCK_TYPE_INFO | CATCHBLOCK_OFFSET | CATCHBLOCK_RET_ADDR_MASK))
+ if (ci->header & ~(CATCHBLOCK_FLAGS | CATCHBLOCK_TYPE_INFO | CATCHBLOCK_OFFSET |
+ CATCHBLOCK_SEPARATED | CATCHBLOCK_RET_ADDR_MASK))
{
FIXME("unknown header: %x\n", ci->header);
return FALSE;
@@ -241,10 +243,20 @@ static BOOL read_catchblock_info(BYTE **b, catchblock_info *ci)
if (ci->header & CATCHBLOCK_TYPE_INFO) ci->type_info = read_rva(b);
if (ci->header & CATCHBLOCK_OFFSET) ci->offset = decode_uint(b);
ci->handler = read_rva(b);
- if (ret_addr_type == CATCHBLOCK_RET_ADDR || ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
- ci->ret_addr[0] = decode_uint(b);
- if (ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
- ci->ret_addr[1] = decode_uint(b);
+ if (ci->header & CATCHBLOCK_SEPARATED)
+ {
+ if (ret_addr_type == CATCHBLOCK_RET_ADDR || ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
+ ci->ret_addr[0] = read_rva(b);
+ if (ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
+ ci->ret_addr[1] = read_rva(b);
+ }
+ else
+ {
+ if (ret_addr_type == CATCHBLOCK_RET_ADDR || ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
+ ci->ret_addr[0] = decode_uint(b) + func_rva;
+ if (ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
+ ci->ret_addr[1] = decode_uint(b) + func_rva;
+ }
return TRUE;
}
@@ -320,7 +332,8 @@ static BOOL validate_cxx_function_descr4(const cxx_function_descr *descr, DISPAT
for (j = 0; j < ti.catchblock_count; j++)
{
catchblock_info ci;
- if (!read_catchblock_info(&catchblock, &ci)) return FALSE;
+ if (!read_catchblock_info(&catchblock, &ci,
+ dispatch->FunctionEntry->BeginAddress)) return FALSE;
TRACE(" %d: header 0x%x offset %d handler 0x%x(%p) "
"ret addr[0] %#x ret_addr[1] %#x type %#x %s\n", j, ci.header, ci.offset,
ci.handler, rva_to_ptr(ci.handler, image_base),
@@ -614,7 +627,7 @@ static inline void find_catch_block4(EXCEPTION_RECORD *rec, CONTEXT *context,
{
catchblock_info ci;
- read_catchblock_info(&catchblock, &ci);
+ read_catchblock_info(&catchblock, &ci, dispatch->FunctionEntry->BeginAddress);
if (info)
{
@@ -652,11 +665,15 @@ static inline void find_catch_block4(EXCEPTION_RECORD *rec, CONTEXT *context,
catch_record.ExceptionInformation[6] = (ULONG_PTR)untrans_rec;
catch_record.ExceptionInformation[7] = (ULONG_PTR)context;
if (ci.ret_addr[0])
+ {
catch_record.ExceptionInformation[8] = (ULONG_PTR)rva_to_ptr(
- ci.ret_addr[0] + dispatch->FunctionEntry->BeginAddress, dispatch->ImageBase);
+ ci.ret_addr[0], dispatch->ImageBase);
+ }
if (ci.ret_addr[1])
+ {
catch_record.ExceptionInformation[9] = (ULONG_PTR)rva_to_ptr(
- ci.ret_addr[1] + dispatch->FunctionEntry->BeginAddress, dispatch->ImageBase);
+ ci.ret_addr[1], dispatch->ImageBase);
+ }
RtlUnwindEx((void*)frame, (void*)dispatch->ControlPc, &catch_record, NULL, &ctx, NULL);
}
}
@@ -808,8 +825,9 @@ EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler4(EXCEPTION_RECORD *rec,
rec->ExceptionCode != STATUS_LONGJUMP)
return ExceptionContinueSearch; /* handle only c++ exceptions */
- if (descr.header & ~(FUNC_DESCR_IS_CATCH | FUNC_DESCR_UNWIND_MAP |
- FUNC_DESCR_TRYBLOCK_MAP | FUNC_DESCR_EHS | FUNC_DESCR_NO_EXCEPT))
+ if (descr.header & ~(FUNC_DESCR_IS_CATCH | FUNC_DESCR_IS_SEPARATED |
+ FUNC_DESCR_UNWIND_MAP | FUNC_DESCR_TRYBLOCK_MAP | FUNC_DESCR_EHS |
+ FUNC_DESCR_NO_EXCEPT))
{
FIXME("unsupported flags: %x\n", descr.header);
return ExceptionContinueSearch;
@@ -831,6 +849,26 @@ EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler4(EXCEPTION_RECORD *rec,
descr.tryblock_map += count_end - count;
}
descr.ip_map = read_rva(&p);
+ if (descr.header & FUNC_DESCR_IS_SEPARATED)
+ {
+ UINT i, num, func;
+ BYTE *map;
+
+ map = rva_to_ptr(descr.ip_map, dispatch->ImageBase);
+ num = decode_uint(&map);
+ for (i = 0; i < num; i++)
+ {
+ func = read_rva(&map);
+ descr.ip_map = read_rva(&map);
+ if (func == dispatch->FunctionEntry->BeginAddress)
+ break;
+ }
+ if (i == num)
+ {
+ FIXME("function ip_map not found\n");
+ return ExceptionContinueSearch;
+ }
+ }
count_end = count = rva_to_ptr(descr.ip_map, dispatch->ImageBase);
descr.ip_count = decode_uint(&count_end);
descr.ip_map += count_end - count;
More information about the wine-cvs
mailing list