From a41c5557e2da79f03873a232189cb1a569424394 Mon Sep 17 00:00:00 2001 From: anonymous Date: Thu, 6 Jan 2011 05:36:17 +0600 Subject: Fix for COMPILER-8909 --- src/dwarf_eh.h | 28 ++++++++++++++++++++-------- src/exception.cc | 23 ++++++++++++++++++++--- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/dwarf_eh.h b/src/dwarf_eh.h index 8acc2a1..6d2e504 100644 --- a/src/dwarf_eh.h +++ b/src/dwarf_eh.h @@ -269,11 +269,15 @@ struct dwarf_eh_action /** * Look up the landing pad that corresponds to the current invoke. + * Returns true if record exists. */ -static struct dwarf_eh_action - dwarf_eh_find_callsite(struct _Unwind_Context *context, struct dwarf_eh_lsda *lsda) +static bool + dwarf_eh_find_callsite(struct _Unwind_Context *context, + struct dwarf_eh_lsda *lsda, + struct dwarf_eh_action *result) { - struct dwarf_eh_action result = { 0, 0}; + result->action_record = 0; + result->landing_pad = 0; uint64_t ip = _Unwind_GetIP(context) - _Unwind_GetRegionStart(context); unsigned char *callsite_table = (unsigned char*)lsda->call_site_table; while (callsite_table <= lsda->action_table) @@ -289,22 +293,30 @@ static struct dwarf_eh_action landing_pad = read_value(lsda->callsite_encoding, &callsite_table); action = read_uleb128(&callsite_table); - if (call_site_start <= ip && ip <= call_site_start + call_site_size) + // we shold not include call_site_start (begin of the region) + // address in ip range. For each call site + // + // address1: call proc + // address2: next instruction + // + // call stack contains address2 and not address1. + // address1 can be at the end of another EH region. + if (call_site_start < ip && ip <= call_site_start + call_site_size) { if (action) { // Action records are 1-biased so both no-record and zeroth // record can be stored. - result.action_record = lsda->action_table + action - 1; + result->action_record = lsda->action_table + action - 1; } // No landing pad means keep unwinding. if (landing_pad) { // Landing pad is the offset from the value in the header - result.landing_pad = lsda->landing_pads + landing_pad; + result->landing_pad = lsda->landing_pads + landing_pad; } - break; + return true; } } - return result; + return false; } diff --git a/src/exception.cc b/src/exception.cc index 3920cf7..9c4bc4d 100644 --- a/src/exception.cc +++ b/src/exception.cc @@ -774,7 +774,17 @@ extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, if (actions & _UA_SEARCH_PHASE) { struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); - action = dwarf_eh_find_callsite(context, &lsda); + if (!dwarf_eh_find_callsite(context, &lsda, &action)) + { + // EH range not found. This happens if exception is thrown + // and not catched inside cleanup (destructor). + // We should call terminate() in this case + // catchTemp (landing pad) field of exception object will + // contain null when personality function will be called + // with _UA_HANDLER_FRAME action + return _URC_HANDLER_FOUND; + } + handler_type found_handler = check_action_record(context, &lsda, action.action_record, ex, &selector); // If there's no action record, we've only found a cleanup, so keep @@ -803,18 +813,25 @@ extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, // context for a cleanup. if (!(actions & _UA_HANDLER_FRAME)) { + // cleanup + struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); - action = dwarf_eh_find_callsite(context, &lsda); + dwarf_eh_find_callsite(context, &lsda, &action); if (0 == action.landing_pad) { return _URC_CONTINUE_UNWIND; } handler_type found_handler = check_action_record(context, &lsda, action.action_record, ex, &selector); // Ignore handlers this time. if (found_handler != handler_cleanup) { return _URC_CONTINUE_UNWIND; } } + else if (ex->catchTemp == 0) + { + // uncaught exception in claenup, calling terminate + std::terminate(); + } else if (foreignException) { struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); - action = dwarf_eh_find_callsite(context, &lsda); + dwarf_eh_find_callsite(context, &lsda, &action); check_action_record(context, &lsda, action.action_record, ex, &selector); } -- cgit v1.2.3