summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoranonymous <local@localhost>2010-06-28 17:44:35 +0000
committeranonymous <local@localhost>2010-06-28 17:44:35 +0000
commit81adee0f2476af72ce3923874f35dceff9fedf9a (patch)
treecaa361ed02d8ce227bf982a36f4219e97211dddc /src
parente55300bb3884cf91c0d2735649a68984703a6350 (diff)
downloadlibcxxrt-81adee0f2476af72ce3923874f35dceff9fedf9a.tar.gz
libcxxrt-81adee0f2476af72ce3923874f35dceff9fedf9a.tar.bz2
libcxxrt-81adee0f2476af72ce3923874f35dceff9fedf9a.tar.xz
Added std:: functions for setting unexpected / terminate handlers.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile47
-rw-r--r--src/dwarf_eh.h1
-rw-r--r--src/exception.cc54
3 files changed, 57 insertions, 45 deletions
diff --git a/src/Makefile b/src/Makefile
index 0d0e203..d8240a7 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,5 @@
OBJECTS = typeinfo.o exception.o dynamic_cast.o terminate.o guard.o
-TEST_OBJECTS = test_typeinfo.o test.o test_exception.o new.o test_guard.o
-
# Needed for building the shared library
CXXFLAGS = -fPIC
# Needed for GCC atomic ops to work on x86.
@@ -20,42 +18,7 @@ CXXFLAGS += -Wall -pedantic -g
CPPFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib -L. -lpthread -fexceptions
-
-
-
-
-all: test libcxxabi.so.1
-
-PRODUCTS = test libcxxabi.so.1 system_test
-
-test: $(TEST_OBJECTS) libcxxabi.so.1
- @echo
- @gcc $(CPPFLAGS) $(LDFLAGS) -lcxxabi -o test $(TEST_OBJECTS)
-
-# Fudge the dynamic library search path to include the current directory so
-# that we can run the tests without having to install the .so
-runtest: test
- @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ./test
-
-# Run the test program in the debugger
-debug: test
- @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) gdb ./test
-
-# Run the test program with valgrind. Make sure that the output from this has
-# no memory leaks
-valgrind: test
- @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) valgrind --leak-check=full ./test
-
-# Compile another version of the test program linked against libstdc++, run it,
-# and ensure that both versions pass the same number of tests. Bugs in the
-# unwinding can cause some test not to be executed - this is a quick way of
-# testing that the correct number pass.
-compare: test
- @$(CXX) $(CXXFLAGS) $(LDFLAGS) $(TEST_OBJECTS) -lstdc++ -o system_test
- @./system_test 2>&1 | tail -1 > system_test.out
- @echo Comparing libcxxabi and libstdc++ versions...
- @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ./test 2>&1 | tail -1 | diff system_test.out -
-
+PRODUCTS = libcxxabi.so.1
libcxxabi.so.1: $(OBJECTS)
@echo Linking $@...
@@ -63,9 +26,15 @@ libcxxabi.so.1: $(OBJECTS)
.cc.o:
@echo Compiling $<...
- @echo $(CXXFLAGS)
@$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
clean:
@echo Cleaning...
@rm -f $(OBJECTS) $(PRODUCTS) $(TEST_OBJECTS) vgcore* *.core
+
+
+dynamic_cast.o: dynamic_cast.cc typeinfo.h abi_namespace.h typeinfo
+exception.o: exception.cc typeinfo.h abi_namespace.h typeinfo dwarf_eh.h
+guard.o: guard.cc
+terminate.o: terminate.cc
+typeinfo.o: typeinfo.cc typeinfo.h abi_namespace.h typeinfo
diff --git a/src/dwarf_eh.h b/src/dwarf_eh.h
index 466f792..1ab25db 100644
--- a/src/dwarf_eh.h
+++ b/src/dwarf_eh.h
@@ -73,6 +73,7 @@ static inline int dwarf_size_of_fixed_size_field(unsigned char type)
case DW_EH_PE_udata2: return 2;
case DW_EH_PE_udata4: return 4;
case DW_EH_PE_udata8: return 8;
+ case DW_EH_PE_absptr: return sizeof(void*);
}
abort();
}
diff --git a/src/exception.cc b/src/exception.cc
index bf49bb2..5bfd921 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -815,17 +815,59 @@ extern "C" std::type_info *__cxa_current_exception_type()
*/
extern "C" void __cxa_call_unexpected(void*exception)
{
- // FIXME: This should call the unexpected handler from the exception, or
- // the global per-thread one if that one doesn't exist.
_Unwind_Exception *exceptionObject = (_Unwind_Exception*)exception;
- fprintf(stderr, "Exception spec violated! You have no skill!\n");
if (exceptionObject->exception_class == exception_class)
{
__cxa_exception *ex = (__cxa_exception*)
((char*)exceptionObject - offsetof(struct __cxa_exception, unwindHeader));
+ if (ex->unexpectedHandler)
+ {
+ ex->unexpectedHandler();
+ // Should not be reached.
+ abort();
+ }
+ }
+ std::unexpected();
+}
- // TODO: Demangle type name
- fprintf(stderr, "Thrown exception was: %s\n", ex->exceptionType->name());
+namespace std
+{
+ unexpected_handler set_unexpected(unexpected_handler f) throw()
+ {
+ static __cxa_thread_info *info = thread_info();
+ unexpected_handler old = info->unexpectedHandler;
+ info->unexpectedHandler = f;
+ return old;
+ }
+ terminate_handler set_terminate(terminate_handler f) throw()
+ {
+ static __cxa_thread_info *info = thread_info();
+ terminate_handler old = info->terminateHandler;
+ info->terminateHandler = f;
+ return old;
}
- exit(1);
+ void terminate()
+ {
+ static __cxa_thread_info *info = thread_info_fast();
+ if (0 != info && 0 != info->terminateHandler)
+ {
+ info->terminateHandler();
+ // Should not be reached - a terminate handler is not expected to
+ // return.
+ }
+ abort();
+ }
+ void unexpected()
+ {
+ static __cxa_thread_info *info = thread_info_fast();
+ if (0 != info && 0 != info->unexpectedHandler)
+ {
+ info->unexpectedHandler();
+ // Should not be reached - a terminate handler is not expected to
+ // return.
+ abort();
+ }
+ terminate();
+ }
+
}