From 34cd4c3dd5245be2a0e0e510312e73c6a7e1a641 Mon Sep 17 00:00:00 2001 From: Daniel Lehman Date: Tue, 2 Aug 2016 17:16:52 -0700 Subject: [PATCH] msvcrt: Call unwind handlers on intermediate frames during virtual unwind during the virtual unwind, cxx_frame_handler isn't calling the unwind handler for a frame that it is 'passing' on the way to the target. the frames that are passed should have all the destructors called from where control left the frame to the end of scope (from ip_map[ControlPc] to -1). the original frame and end level are still needed on the target class klass; void throw_int() { klass k; <- ~klass() isn't called during unwind throw (int)0x42; } int main(int argc, char **argv) { try { throw_it(); } catch(int i) { } } Signed-off-by: Daniel Lehman --- dlls/msvcrt/except_x86_64.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dlls/msvcrt/except_x86_64.c b/dlls/msvcrt/except_x86_64.c index 3a90a66..80780ae 100644 --- a/dlls/msvcrt/except_x86_64.c +++ b/dlls/msvcrt/except_x86_64.c @@ -470,14 +470,20 @@ static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame, if (rec->ExceptionCode==STATUS_UNWIND_CONSOLIDATE && rec->NumberParameters==6 && rec->ExceptionInformation[0]==(ULONG_PTR)call_catch_block) { - ULONG64 orig_frame = rec->ExceptionInformation[1]; - const cxx_function_descr *descr = (void*)rec->ExceptionInformation[2]; - int end_level = rec->ExceptionInformation[3]; EXCEPTION_RECORD *new_rec = (void*)rec->ExceptionInformation[4]; thread_data_t *data = msvcrt_get_thread_data(); frame_info *cur; - cxx_local_unwind(orig_frame, dispatch, descr, end_level); + if (rec->ExceptionFlags & EH_TARGET_UNWIND) + { + ULONG64 orig_frame = rec->ExceptionInformation[1]; + const cxx_function_descr *orig_descr = (void*)rec->ExceptionInformation[2]; + int end_level = rec->ExceptionInformation[3]; + + cxx_local_unwind(orig_frame, dispatch, orig_descr, end_level); + } + else + cxx_local_unwind(frame, dispatch, descr, -1); /* FIXME: we should only unregister frames registered by call_catch_block here */ for (cur = data->frame_info_head; cur; cur = cur->next) -- 1.9.5