From 2f3e82a7b2847e6ff7d65e73295bf3d6469236ab Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 18 May 2014 23:51:17 +0800 Subject: [PATCH 1/1] Usermode/libc++ - Exception handling in progress (build broken) --- Usermode/Libraries/Makefile.cfg | 1 + Usermode/Libraries/libc++.so_src/Makefile | 2 + Usermode/Libraries/libc++.so_src/cxxabi.cc | 4 + .../libc++.so_src/exception_handling.cc | 86 ++++++++ .../Libraries/libc++.so_src/exceptions.cc | 46 +++++ .../libc++.so_src/include_exp/allocator | 6 +- .../libc++.so_src/include_exp/exception | 5 + .../libc++.so_src/include_exp/stdexcept | 6 +- .../libc++.so_src/include_exp/string | 195 +++++++++++++----- Usermode/Libraries/libc++.so_src/string.cc | 15 ++ 10 files changed, 310 insertions(+), 56 deletions(-) create mode 100644 Usermode/Libraries/libc++.so_src/exception_handling.cc create mode 100644 Usermode/Libraries/libc++.so_src/exceptions.cc create mode 100644 Usermode/Libraries/libc++.so_src/string.cc diff --git a/Usermode/Libraries/Makefile.cfg b/Usermode/Libraries/Makefile.cfg index 5920059e..16f423de 100644 --- a/Usermode/Libraries/Makefile.cfg +++ b/Usermode/Libraries/Makefile.cfg @@ -33,6 +33,7 @@ else LDFLAGS := -I/Acess/Libs/ld-acess.so -lld-acess `$(CC) -print-libgcc-file-name` endif LDFLAGS += -g -nostdlib -shared -eSoMain -x --no-undefined -L$(OUTPUTDIR)Libs/ +CXXFLAGS += -std=gnu++11 -include $(_libsdir)../common_settings.mk diff --git a/Usermode/Libraries/libc++.so_src/Makefile b/Usermode/Libraries/libc++.so_src/Makefile index 6cec94f1..0e62c53a 100644 --- a/Usermode/Libraries/libc++.so_src/Makefile +++ b/Usermode/Libraries/libc++.so_src/Makefile @@ -10,6 +10,8 @@ ASFLAGS += LDFLAGS += -Map map.txt -lc OBJ = misc.o new.o guard.o cxxabi.o typeinfo.o +OBJ += string.o +OBJ += exceptions.o exception_handling.o DEPFILES := $(OBJ:%.o=%.d) BIN = libc++.so ifeq ($(ARCHDIR),native) diff --git a/Usermode/Libraries/libc++.so_src/cxxabi.cc b/Usermode/Libraries/libc++.so_src/cxxabi.cc index adda291c..84cedf2c 100644 --- a/Usermode/Libraries/libc++.so_src/cxxabi.cc +++ b/Usermode/Libraries/libc++.so_src/cxxabi.cc @@ -4,6 +4,10 @@ * * cxxabi.cc * - C++ ABI Namespace + * + * NOTE: GCC follows the Itanium™ C++ ABI on all platforms + * http://mentorembedded.github.io/cxx-abi/abi.html + * http://libcxxabi.llvm.org/spec.html */ #include diff --git a/Usermode/Libraries/libc++.so_src/exception_handling.cc b/Usermode/Libraries/libc++.so_src/exception_handling.cc new file mode 100644 index 00000000..23039803 --- /dev/null +++ b/Usermode/Libraries/libc++.so_src/exception_handling.cc @@ -0,0 +1,86 @@ +/* + */ +#include +#include + +typedef void *(unexpected_handler)(void); +typedef void *(terminate_handler)(void); + +struct _Unwind_Context; + +typedef enum { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +} _Unwind_Reason_Code; + +typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code reason, struct _Unwind_Exception *exc); + +struct _Unwind_Exception +{ + uint64_t exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + uint64_t private_1; + uint64_t private_2; +}; + +struct __cxa_exception +{ + std::type_info* exceptionType; + void (*exceptionDestructor)(void *); + unexpected_handler unexpectedHandler; + terminate_handler terminateHandler; + __cxa_exception* nextException; + + int handlerCount; + + int handlerSwitchValue; + const char* actionRecord; + const char* languageSpecificData; + void* catchTemp; + void* adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + + int uncaught_exception_count; +__cxa_exception *uncaught_exception_top; + +extern "C" void __cxa_call_unexpected(void *) +{ + // An unexpected exception was thrown from a function that lists its possible exceptions + for(;;); +} + +extern "C" void *__cxa_begin_catch(void *exceptionObject) +{ + struct __cxa_exception *except = static_cast<__cxa_exception*>( exceptionObject ); + except --; + + except->handlerCount ++; + + except->nextException = uncaught_exception_top; + uncaught_exception_top = except; + + uncaught_exception_count --; + + return except; +} + +extern "C" void __cxa_end_catch() +{ + struct __cxa_exception *except = uncaught_exception_top; + except->handlerCount --; + uncaught_exception_top = except->nextException; + + if( except->handlerCount == 0 ) { + //__cxa_free_exception(except+1); + } +} + diff --git a/Usermode/Libraries/libc++.so_src/exceptions.cc b/Usermode/Libraries/libc++.so_src/exceptions.cc new file mode 100644 index 00000000..2b66dcee --- /dev/null +++ b/Usermode/Libraries/libc++.so_src/exceptions.cc @@ -0,0 +1,46 @@ +/* + * Acess2 C++ Library + * - By John Hodge (thePowersGang) + * + * exceptions.cc + * - ::std::exception and friends + */ +#include +#include +#include + +// === CODE === +::std::exception::exception() throw(): + m_what_str("-empty-") +{ +} +::std::exception::exception(const exception& other) throw(): + m_what_str(other.m_what_str) +{ +} +::std::exception::exception(const string& str) throw(): + m_what_str(str) +{ +} +::std::exception& ::std::exception::operator=(const exception& other) throw() +{ + m_what_str = other.m_what_str; + return *this; +} +::std::exception::~exception() throw() +{ +} +const char* ::std::exception::what() const throw() +{ + return m_what_str.c_str(); +} + +::std::logic_error::logic_error(const ::std::string& what_str): + exception(what_str) +{ +} + +::std::out_of_range::out_of_range(const ::std::string& what_str): + logic_error(what_str) +{ +} diff --git a/Usermode/Libraries/libc++.so_src/include_exp/allocator b/Usermode/Libraries/libc++.so_src/include_exp/allocator index 0bb12ea2..d9faae97 100644 --- a/Usermode/Libraries/libc++.so_src/include_exp/allocator +++ b/Usermode/Libraries/libc++.so_src/include_exp/allocator @@ -31,7 +31,7 @@ public: allocator() throw() { } - allocator(const allocator& alloc) throw() { + allocator(const allocator& alloc __attribute__((unused))) throw() { } template allocator(const allocator& alloc) throw() { @@ -46,9 +46,11 @@ public: return &x; } pointer allocate(size_type n, const void* hint=0) { - ::operator new (n * sizeof(value_type)); + hint = hint; + return static_cast( ::operator new (n * sizeof(value_type)) ); } void deallocate(pointer p, size_type n) { + n=n; ::operator delete(p); } }; diff --git a/Usermode/Libraries/libc++.so_src/include_exp/exception b/Usermode/Libraries/libc++.so_src/include_exp/exception index 6edf82b8..0beb0160 100644 --- a/Usermode/Libraries/libc++.so_src/include_exp/exception +++ b/Usermode/Libraries/libc++.so_src/include_exp/exception @@ -10,16 +10,21 @@ #define noexcept throw() +#include "string" + namespace std { class exception { + string m_what_str; public: exception() noexcept; exception(const exception& e) noexcept; exception& operator= (const exception& e) noexcept; virtual ~exception() noexcept; virtual const char* what() const noexcept; +protected: + exception(const string& what_str) noexcept; }; }; // namespace std diff --git a/Usermode/Libraries/libc++.so_src/include_exp/stdexcept b/Usermode/Libraries/libc++.so_src/include_exp/stdexcept index f9e3e3e8..aea1afd3 100644 --- a/Usermode/Libraries/libc++.so_src/include_exp/stdexcept +++ b/Usermode/Libraries/libc++.so_src/include_exp/stdexcept @@ -16,14 +16,14 @@ class logic_error: public exception { public: - explicit logic_error(const basic_string& what_arg); + explicit logic_error(const string& what_arg); }; class runtime_error: public exception { public: - explicit runtime_error(const basic_string& what_arg); + explicit runtime_error(const string& what_arg); }; class out_of_range: @@ -33,7 +33,7 @@ public: explicit out_of_range(const string& what_arg); }; -} // namespace std +}; // namespace std #endif diff --git a/Usermode/Libraries/libc++.so_src/include_exp/string b/Usermode/Libraries/libc++.so_src/include_exp/string index 73262176..a32c9e96 100644 --- a/Usermode/Libraries/libc++.so_src/include_exp/string +++ b/Usermode/Libraries/libc++.so_src/include_exp/string @@ -61,18 +61,9 @@ struct char_traits } }; -template < class charT, class traits=char_traits, class Alloc=allocator > -class basic_string; - -typedef basic_string string; +extern void _throw_out_of_range(const char *message); -}; // namespace std - -#include - -namespace std { - -template < class charT, class traits, class Alloc > +template < class charT, class traits=char_traits, class Alloc=allocator > class basic_string { public: @@ -83,16 +74,40 @@ public: typedef typename allocator_type::const_reference const_reference; typedef size_t size_type; +private: + struct dynamic_info + { + allocator_type m_allocator; + int m_ref_count = 1; + size_type m_capacity = 0; + size_type m_size = 0; + typename allocator_type::pointer m_data = 0; + dynamic_info(const allocator_type& alloc): + m_allocator(alloc) + { + } + dynamic_info(const dynamic_info& other): + m_allocator(other.m_allocator), + m_ref_count(1), + m_capacity(other.m_capacity), + m_size(other.m_size) + { + m_data = m_allocator.allocate(m_capacity); + for( size_type i = 0; i < m_size; i ++ ) + m_data[i] = other.m_data[i]; + } + }; + +public: basic_string(const allocator_type& alloc = allocator_type()): m_allocator(alloc), - m_capacity(0), - m_length(0), - m_data(0) + m_content(0) { } - basic_string(const basic_string& str): - basic_string(str, allocator_type()) + basic_string(const basic_string& str) throw(): + basic_string(allocator_type()) { + *this = str; } basic_string(const basic_string& str, const allocator_type& alloc): basic_string(str, 0, str.length(), alloc) @@ -107,8 +122,8 @@ public: len = str.length() - pos; reserve(len); for( size_type i = 0; i < len; i ++ ) - m_data[i] = str.m_data[pos+i]; - m_length = len; + m_content->m_data[i] = str.m_content->m_data[pos+i]; + m_content->m_size = len; } } basic_string(const charT *s, const allocator_type& alloc = allocator_type()): @@ -122,8 +137,8 @@ public: { reserve(n); for( size_type i = 0; i < n; i ++ ) - m_data[i] = s[i]; - m_length = n; + m_content->m_data[i] = s[i]; + m_content->m_size = n; } } basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()): @@ -133,16 +148,29 @@ public: { reserve(n); for( size_type i = 0; i < n; i ++ ) - m_data[i] = c; - m_length = n; + m_content->m_data[i] = c; + m_content->m_size = n; } } + ~basic_string() + { + release_content(); + } + basic_string& operator=(const basic_string& str) throw() { + return assign(str); + } + basic_string& operator=(const charT* s) { + return assign(s); + } + basic_string& operator=(charT c) { + return assign(c); + } // iterators // capacity size_type size() const { - return m_size; + return m_content ? m_content->m_size : 0; } size_type length() const { return size(); @@ -152,29 +180,31 @@ public: } void resize(size_type size, charT c = 0) { reserve(size); - if( m_size < size ) { - for( size_type ofs = m_size; ofs < size; ofs ++ ) - m_data[ofs] = c; + if( m_content->m_size < size ) { + for( size_type ofs = m_content->m_size; ofs < size; ofs ++ ) + m_content->m_data[ofs] = c; } - m_size = size; - m_data[m_size] = 0; + m_content->m_size = size; + m_content->m_data[size] = 0; } size_type capacity() const { - return m_capacity; + return m_content ? m_content->m_capacity : 0; } void reserve(size_type size) { + own_content(); size = (size+1 + 31) & ~31; - if( size > m_capacity ) { + if( size > m_content->m_capacity ) { auto new_area = m_allocator.allocate(size); - for( size_type i = 0; i < m_length; i ++ ) - new_area[i] = m_data[i]; - m_allocator.deallocate(m_data, m_capacity); - m_data = new_area; - m_capacity = size; + for( size_type i = 0; i < m_content->m_size; i ++ ) + new_area[i] = m_content->m_data[i]; + m_allocator.deallocate(m_content->m_data, m_content->m_capacity); + m_content->m_data = new_area; + m_content->m_capacity = size; } } void clear() { - m_size = 0; + own_content(); + m_content->m_size = 0; } bool empty() const { return length() == 0; @@ -182,37 +212,100 @@ public: // Access reference operator[] (size_type pos) { - return m_data[pos]; + own_content(); + return m_content->m_data[pos]; } const_reference operator[] (size_type pos) const { - return m_data[pos]; + return (m_content ? m_content->m_data[pos] : *(const charT*)0); } reference at(size_type pos) { - if(pos >= m_size) throw ::std::out_of_range("basic_string - at"); - return m_data[pos]; + own_content(); + if(pos >= m_content->m_size) + _throw_out_of_range("basic_string - at"); + return m_content->m_data[pos]; } const_reference at(size_type pos) const { - if(pos >= m_size) throw ::std::out_of_range("basic_string - at"); - return m_data[pos]; + if(!m_content || pos >= m_content.m_size) + _throw_out_of_range("basic_string - at"); + return m_content->m_data[pos]; } // Modifiers - basic_string& operator +=(const basic_string& str); - basic_string& operator +=(const charT* s); - basic_string& operator +=(charT c); + basic_string& operator +=(const basic_string& str) { + return append(str); + } + basic_string& operator +=(const charT* s) { + return append(s); + } + basic_string& operator +=(charT c) { + push_back(c); + return *this; + } + basic_string& append(const basic_string& str) { + return append(str, 0, npos); + } + basic_string& append(const basic_string& str, size_type subpos, size_type sublen); + basic_string& append(const charT* s) { + return append(s, traits::length(s)); + } + basic_string& append(const charT* s, size_type n); + basic_string& append(size_type n, charT c); + void push_back(charT c); + basic_string& assign(const basic_string& str) throw() { + // Special case, triggers copy-on-write. + release_content(); + m_content = str.m_content; + m_content->m_ref_count ++; + return *this; + } + basic_string& assign(const basic_string& str, size_type subpos, size_type sublen); + + // String operations + const char *c_str() const { + // TODO: this is const, but also might need to do processing + return (m_content ? m_content->m_data : ""); + } + const char *data() const { + return (m_content ? m_content->m_data : NULL); + } static const size_type npos = -1; private: allocator_type m_allocator; - size_type m_capacity; - size_type m_size; - size_type m_length; - typename allocator_type::pointer m_data; -}; + dynamic_info *m_content; + void own_content() { + if(!m_content) + { + m_content = new dynamic_info(m_allocator); + } + else if( m_content->m_ref_count > 1 ) + { + dynamic_info *new_cont = new dynamic_info(*m_content); + m_content->m_ref_count --; + m_content = new_cont; + } + else + { + // already owned + } + } + void release_content() { + if( m_content ) + { + m_content->m_ref_count --; + if( m_content->m_ref_count == 0 ) { + m_allocator.deallocate(m_content->m_data, m_content->m_capacity); + delete m_content; + } + m_content = NULL; + } + } }; -#include +typedef basic_string string; + +}; #endif diff --git a/Usermode/Libraries/libc++.so_src/string.cc b/Usermode/Libraries/libc++.so_src/string.cc new file mode 100644 index 00000000..94ca722b --- /dev/null +++ b/Usermode/Libraries/libc++.so_src/string.cc @@ -0,0 +1,15 @@ +/* + * Acess2 C++ Library + * - By John Hodge (thePowersGang) + * + * exceptions.cc + * - ::std::exception and friends + */ +#include +#include + +void ::std::_throw_out_of_range(const char *message) +{ + throw ::std::out_of_range(message); +} + -- 2.20.1