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@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d4cfb0c30c
commit
9ccd84b945
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue