Commit 9ccd84b9 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

vcruntime140_1: Add support for exception separated code segments.

parent d4cfb0c3
...@@ -74,6 +74,7 @@ typedef struct ...@@ -74,6 +74,7 @@ typedef struct
#define CATCHBLOCK_FLAGS 0x01 #define CATCHBLOCK_FLAGS 0x01
#define CATCHBLOCK_TYPE_INFO 0x02 #define CATCHBLOCK_TYPE_INFO 0x02
#define CATCHBLOCK_OFFSET 0x04 #define CATCHBLOCK_OFFSET 0x04
#define CATCHBLOCK_SEPARATED 0x08
#define CATCHBLOCK_RET_ADDR_MASK 0x30 #define CATCHBLOCK_RET_ADDR_MASK 0x30
#define CATCHBLOCK_RET_ADDR 0x10 #define CATCHBLOCK_RET_ADDR 0x10
#define CATCHBLOCK_TWO_RET_ADDRS 0x20 #define CATCHBLOCK_TWO_RET_ADDRS 0x20
...@@ -219,13 +220,14 @@ static void read_tryblock_info(BYTE **b, tryblock_info *ti, ULONG64 image_base) ...@@ -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; BYTE ret_addr_type;
memset(ci, 0, sizeof(*ci)); memset(ci, 0, sizeof(*ci));
ci->header = **b; ci->header = **b;
(*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); FIXME("unknown header: %x\n", ci->header);
return FALSE; return FALSE;
...@@ -241,10 +243,20 @@ static BOOL read_catchblock_info(BYTE **b, catchblock_info *ci) ...@@ -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_TYPE_INFO) ci->type_info = read_rva(b);
if (ci->header & CATCHBLOCK_OFFSET) ci->offset = decode_uint(b); if (ci->header & CATCHBLOCK_OFFSET) ci->offset = decode_uint(b);
ci->handler = read_rva(b); ci->handler = read_rva(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) if (ret_addr_type == CATCHBLOCK_RET_ADDR || ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
ci->ret_addr[0] = decode_uint(b); ci->ret_addr[0] = decode_uint(b) + func_rva;
if (ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS) if (ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
ci->ret_addr[1] = decode_uint(b); ci->ret_addr[1] = decode_uint(b) + func_rva;
}
return TRUE; return TRUE;
} }
...@@ -320,7 +332,8 @@ static BOOL validate_cxx_function_descr4(const cxx_function_descr *descr, DISPAT ...@@ -320,7 +332,8 @@ static BOOL validate_cxx_function_descr4(const cxx_function_descr *descr, DISPAT
for (j = 0; j < ti.catchblock_count; j++) for (j = 0; j < ti.catchblock_count; j++)
{ {
catchblock_info ci; 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) " 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, "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), ci.handler, rva_to_ptr(ci.handler, image_base),
...@@ -614,7 +627,7 @@ static inline void find_catch_block4(EXCEPTION_RECORD *rec, CONTEXT *context, ...@@ -614,7 +627,7 @@ static inline void find_catch_block4(EXCEPTION_RECORD *rec, CONTEXT *context,
{ {
catchblock_info ci; catchblock_info ci;
read_catchblock_info(&catchblock, &ci); read_catchblock_info(&catchblock, &ci, dispatch->FunctionEntry->BeginAddress);
if (info) if (info)
{ {
...@@ -652,11 +665,15 @@ static inline void find_catch_block4(EXCEPTION_RECORD *rec, CONTEXT *context, ...@@ -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[6] = (ULONG_PTR)untrans_rec;
catch_record.ExceptionInformation[7] = (ULONG_PTR)context; catch_record.ExceptionInformation[7] = (ULONG_PTR)context;
if (ci.ret_addr[0]) if (ci.ret_addr[0])
{
catch_record.ExceptionInformation[8] = (ULONG_PTR)rva_to_ptr( 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]) if (ci.ret_addr[1])
{
catch_record.ExceptionInformation[9] = (ULONG_PTR)rva_to_ptr( 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); RtlUnwindEx((void*)frame, (void*)dispatch->ControlPc, &catch_record, NULL, &ctx, NULL);
} }
} }
...@@ -808,8 +825,9 @@ EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler4(EXCEPTION_RECORD *rec, ...@@ -808,8 +825,9 @@ EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler4(EXCEPTION_RECORD *rec,
rec->ExceptionCode != STATUS_LONGJUMP) rec->ExceptionCode != STATUS_LONGJUMP)
return ExceptionContinueSearch; /* handle only c++ exceptions */ return ExceptionContinueSearch; /* handle only c++ exceptions */
if (descr.header & ~(FUNC_DESCR_IS_CATCH | FUNC_DESCR_UNWIND_MAP | if (descr.header & ~(FUNC_DESCR_IS_CATCH | FUNC_DESCR_IS_SEPARATED |
FUNC_DESCR_TRYBLOCK_MAP | FUNC_DESCR_EHS | FUNC_DESCR_NO_EXCEPT)) FUNC_DESCR_UNWIND_MAP | FUNC_DESCR_TRYBLOCK_MAP | FUNC_DESCR_EHS |
FUNC_DESCR_NO_EXCEPT))
{ {
FIXME("unsupported flags: %x\n", descr.header); FIXME("unsupported flags: %x\n", descr.header);
return ExceptionContinueSearch; return ExceptionContinueSearch;
...@@ -831,6 +849,26 @@ EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler4(EXCEPTION_RECORD *rec, ...@@ -831,6 +849,26 @@ EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler4(EXCEPTION_RECORD *rec,
descr.tryblock_map += count_end - count; descr.tryblock_map += count_end - count;
} }
descr.ip_map = read_rva(&p); 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); count_end = count = rva_to_ptr(descr.ip_map, dispatch->ImageBase);
descr.ip_count = decode_uint(&count_end); descr.ip_count = decode_uint(&count_end);
descr.ip_map += count_end - count; descr.ip_map += count_end - count;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment