summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoranonymous <local@localhost>2011-01-06 05:36:17 +0600
committeranonymous <local@localhost>2011-01-06 05:36:17 +0600
commita41c5557e2da79f03873a232189cb1a569424394 (patch)
tree3474a06d2802d8f31b0c152642ce8bf0ede00283
parentaca9afa6aa45f18979da31391902933f7da65e27 (diff)
downloadlibcxxrt-a41c5557e2da79f03873a232189cb1a569424394.tar.gz
libcxxrt-a41c5557e2da79f03873a232189cb1a569424394.tar.bz2
libcxxrt-a41c5557e2da79f03873a232189cb1a569424394.tar.xz
Fix for COMPILER-8909
-rw-r--r--src/dwarf_eh.h28
-rw-r--r--src/exception.cc23
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);
}