summaryrefslogtreecommitdiff
path: root/src/exception.cc
diff options
context:
space:
mode:
authorDavid Chisnall <dchisnall@pathscale.com>2011-11-24 20:03:52 +0000
committerDavid Chisnall <dchisnall@pathscale.com>2011-11-24 20:03:52 +0000
commit75ca8259acea380d867f136738e3835250ea0855 (patch)
tree9a3bb29ee4866c62ee5e0d784b81719751cbfb06 /src/exception.cc
parentfa252d2522b4972ac2fdc376e4200db3234d9d3a (diff)
downloadlibcxxrt-75ca8259acea380d867f136738e3835250ea0855.tar.gz
libcxxrt-75ca8259acea380d867f136738e3835250ea0855.tar.bz2
libcxxrt-75ca8259acea380d867f136738e3835250ea0855.tar.xz
Mostly-working ARM exceptions.
Exception specifications are still broken - only the first is checked.
Diffstat (limited to 'src/exception.cc')
-rw-r--r--src/exception.cc65
1 files changed, 63 insertions, 2 deletions
diff --git a/src/exception.cc b/src/exception.cc
index 1e60ee9..3b99735 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -2,6 +2,7 @@
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
+#include <stdint.h>
#include <pthread.h>
#include "typeinfo.h"
#include "dwarf_eh.h"
@@ -25,7 +26,7 @@ static void saveLandingPad(struct _Unwind_Context *context,
ucb->barrier_cache.sp = _Unwind_GetGR(context, 13);
ucb->barrier_cache.bitpattern[1] = (uint32_t)selector;
ucb->barrier_cache.bitpattern[3] = (uint32_t)landingPad;
-#else
+#endif
// Cache the results for the phase 2 unwind, if we found a handler
// and this is not a foreign exception.
if (ex)
@@ -33,7 +34,6 @@ static void saveLandingPad(struct _Unwind_Context *context,
ex->handlerSwitchValue = selector;
ex->catchTemp = landingPad;
}
-#endif
}
/**
@@ -120,6 +120,10 @@ struct __cxa_thread_info
*/
int emergencyBuffersHeld;
/**
+ * The exception currently running in a cleanup.
+ */
+ _Unwind_Exception *currentCleanup;
+ /**
* The public part of this structure, accessible from outside of this
* module.
*/
@@ -580,9 +584,11 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce
case _URC_FATAL_PHASE1_ERROR:
fprintf(stderr, "Fatal error during phase 1 unwinding\n");
break;
+#ifndef __arm__
case _URC_FATAL_PHASE2_ERROR:
fprintf(stderr, "Fatal error during phase 2 unwinding\n");
break;
+#endif
case _URC_END_OF_STACK:
fprintf(stderr, "Terminating due to uncaught exception %p",
(void*)thrown_exception);
@@ -650,6 +656,7 @@ extern "C" void __cxa_throw(void *thrown_exception,
std::type_info *tinfo,
void(*dest)(void*))
{
+ fprintf(stderr, "Thrown exception: %p\n", thrown_exception);
__cxa_exception *ex = ((__cxa_exception*)thrown_exception) - 1;
ex->referenceCount = 1;
@@ -757,6 +764,7 @@ static std::type_info *get_type_info_entry(_Unwind_Context *context,
// Get the address of the record in the table.
dw_eh_ptr_t record = lsda->type_table -
dwarf_size_of_fixed_size_field(lsda->type_table_encoding)*filter;
+ //record -= 4;
dw_eh_ptr_t start = record;
// Read the value, but it's probably an indirect reference...
int64_t offset = read_value(lsda->type_table_encoding, &record);
@@ -770,6 +778,7 @@ static std::type_info *get_type_info_entry(_Unwind_Context *context,
}
+
/**
* Checks the type signature found in a handler against the type of the thrown
* object. If ex is 0 then it is assumed to be a foreign exception and only
@@ -895,7 +904,14 @@ static handler_type check_action_record(_Unwind_Context *context,
*selector = filter;
while (*type_index)
{
+#ifdef __arm__
+ //fprintf(stderr, "Filter: %d\n", filter);
+ std::type_info *handler_type = handler_type = get_type_info_entry(context, lsda, -filter - 1);
+ //fprintf(stderr, "Handler: %p\n", handler_type);
+ type_index++;
+#else
std::type_info *handler_type = get_type_info_entry(context, lsda, *(type_index++));
+#endif
// If the exception spec matches a permitted throw type for
// this function, don't report a handler - we are allowed to
// propagate this exception out.
@@ -1023,6 +1039,8 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0)
action.action_record, realEx, &selector, ex->adjustedPtr);
// Ignore handlers this time.
if (found_handler != handler_cleanup) { return continueUnwinding(exceptionObject, context); }
+ __cxa_thread_info *info = thread_info_fast();
+ info->currentCleanup = exceptionObject;
}
else if (foreignException)
{
@@ -1066,6 +1084,7 @@ extern "C" void *__cxa_begin_catch(void *e) throw()
extern "C" void *__cxa_begin_catch(void *e)
#endif
{
+ fprintf(stderr, "Entering catch\n");
// Decrement the uncaught exceptions count
__cxa_eh_globals *globals = __cxa_get_globals();
globals->uncaughtExceptions--;
@@ -1111,19 +1130,27 @@ extern "C" void *__cxa_begin_catch(void *e)
ex->handlerCount++;
}
+ fprintf(stderr, "Exception base pointer: %p\n", ((char*)exceptionObject + sizeof(_Unwind_Exception)));
+ fprintf(stderr, "Exception edjusted pointer: %p\n", ex->adjustedPtr);
+ fprintf(stderr, "Exception as int: %d\n", *(int*)((char*)exceptionObject + sizeof(_Unwind_Exception)));
+
return ex->adjustedPtr;
}
+ fprintf(stderr, "Exception as int: %d\n", *(int*)((char*)exceptionObject + sizeof(_Unwind_Exception)));
// exceptionObject is the pointer to the _Unwind_Exception within the
// __cxa_exception. The throw object is after this
return ((char*)exceptionObject + sizeof(_Unwind_Exception));
}
+
+
/**
* ABI function called when exiting a catch block. This will free the current
* exception if it is no longer referenced in other catch blocks.
*/
extern "C" void __cxa_end_catch()
{
+ fprintf(stderr, "Leaving catch\n");
// We can call the fast version here because the slow version is called in
// __cxa_throw(), which must have been called before we end a catch block
__cxa_eh_globals *globals = __cxa_get_globals_fast();
@@ -1169,6 +1196,20 @@ extern "C" void __cxa_end_catch()
}
}
+/*
+extern "C" void __cxa_end_cleanup(_Unwind_Exception* exceptionObject)
+{
+ _Unwind_Resume(0);
+// fprintf(stderr, "Leaving cleanup\n");
+}
+
+extern "C" bool __cxa_begin_cleanup(_Unwind_Exception* exceptionObject)
+{
+ fprintf(stderr, "Entering cleanup\n");
+ return true;
+}
+*/
+
/**
* ABI function. Returns the type of the current exception.
*/
@@ -1336,3 +1377,23 @@ namespace std
return terminateHandler;
}
}
+#ifdef __arm__
+extern "C" _Unwind_Exception *__cxa_get_cleanup(void)
+{
+ __cxa_thread_info *info = thread_info_fast();
+ return info->currentCleanup;
+}
+
+asm (
+".pushsection .text.__cxa_end_cleanup \n"
+".global __cxa_end_cleanup \n"
+".type __cxa_end_cleanup, \"function\" \n"
+"__cxa_end_cleanup: \n"
+" push {r1, r2, r3, r4} \n"
+" bl __cxa_get_cleanup \n"
+" push {r1, r2, r3, r4} \n"
+" b _Unwind_Resume \n"
+" bl abort \n"
+".popsection \n"
+);
+#endif