Make Hello World run with libcxx and gabi++.
This change does 2 things:
(1) Modifies gabi++ source compatible with libcxx.
(2) Adds stubs for missing libc functions needed by libcxx.
It introduces a new macro, GXXABI_LIBCXX, into gabi++ which conditionally
enables and disables functions in gabi++ to make the exported API behave
like libcxxabi's. Existing gabi++ code is also refactored to remove
symbols + APIs that shouldn't really be in namespace std.
Locale handling code has been patched to hobble along in the c-abi, but
there are TODOs.
The exception handling logic in gabi++ isn't complete, nor are the
libc stubs. Where incomplete functionality is introduced a
preprocess warning is left to indicate lack of functionality.
After this CL, it is possible to make a running Hello World using
libcxx on Android.
Change-Id: Iceafd6f8d6dead6b64320b0c0f852d579cceb34c
diff --git a/sources/cxx-stl/gabi++/include/cxxabi.h b/sources/cxx-stl/gabi++/include/cxxabi.h
index c6a4f8a..958a9de 100644
--- a/sources/cxx-stl/gabi++/include/cxxabi.h
+++ b/sources/cxx-stl/gabi++/include/cxxabi.h
@@ -37,39 +37,47 @@
{
// Derived types of type_info below are based on 2.9.5 of C++ ABI.
+ class __shim_type_info : public std::type_info
+ {
+ public:
+ virtual ~__shim_type_info();
+ virtual bool can_catch(const __shim_type_info* thrown_type,
+ void*& adjustedPtr) const = 0;
+ };
+
// Typeinfo for fundamental types.
- class __fundamental_type_info : public std::type_info
+ class __fundamental_type_info : public __shim_type_info
{
public:
virtual ~__fundamental_type_info();
- virtual bool can_catch(const std::type_info* thrown_type,
+ virtual bool can_catch(const __shim_type_info* thrown_type,
void*& adjustedPtr) const;
};
// Typeinfo for array types.
- class __array_type_info : public std::type_info
+ class __array_type_info : public __shim_type_info
{
public:
virtual ~__array_type_info();
- virtual bool can_catch(const std::type_info* thrown_type,
+ virtual bool can_catch(const __shim_type_info* thrown_type,
void*& adjustedPtr) const;
};
// Typeinfo for function types.
- class __function_type_info : public std::type_info
+ class __function_type_info : public __shim_type_info
{
public:
virtual ~__function_type_info();
- virtual bool can_catch(const std::type_info* thrown_type,
+ virtual bool can_catch(const __shim_type_info* thrown_type,
void*& adjustedPtr) const;
};
// Typeinfo for enum types.
- class __enum_type_info : public std::type_info
+ class __enum_type_info : public __shim_type_info
{
public:
virtual ~__enum_type_info();
- virtual bool can_catch(const std::type_info* thrown_type,
+ virtual bool can_catch(const __shim_type_info* thrown_type,
void*& adjustedPtr) const;
};
@@ -127,12 +135,12 @@
};
// Typeinfo for classes with no bases.
- class __class_type_info : public std::type_info
+ class __class_type_info : public __shim_type_info
{
public:
virtual ~__class_type_info();
- virtual bool can_catch(const std::type_info* thrown_type,
- void*& adjustedPtr) const;
+ virtual bool can_catch(const __shim_type_info* thrown_type,
+ void*& adjustedPtr) const;
enum class_type_info_code {
CLASS_TYPE_INFO_CODE,
@@ -193,14 +201,14 @@
__UpcastInfo& info) const;
};
- class __pbase_type_info : public std::type_info
+ class __pbase_type_info : public __shim_type_info
{
public:
virtual ~__pbase_type_info();
- virtual bool can_catch(const std::type_info* thrown_type,
- void*& adjustedPtr) const;
+ virtual bool can_catch(const __shim_type_info* thrown_type,
+ void*& adjustedPtr) const;
unsigned int __flags;
- const std::type_info *__pointee;
+ const __shim_type_info* __pointee;
enum __masks {
__const_mask = 0x1,
@@ -211,7 +219,7 @@
};
- virtual bool can_catch_typeinfo_wrapper(const std::type_info* thrown_type,
+ virtual bool can_catch_typeinfo_wrapper(const __shim_type_info* thrown_type,
void*& adjustedPtr,
unsigned tracker) const;
@@ -271,6 +279,8 @@
// TODO: Support C++0x exception propagation
// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
struct __cxa_exception {
+ size_t referenceCount;
+
std::type_info* exceptionType;
void (*exceptionDestructor)(void*);
std::unexpected_handler unexpectedHandler;
@@ -334,18 +344,12 @@
void __cxa_pure_virtual();
-#ifdef __arm__
- typedef enum {
- ctm_failed = 0,
- ctm_succeeded = 1,
- ctm_succeeded_with_ptr_to_base = 2
- } __cxa_type_match_result;
-
- __cxa_type_match_result __cxa_type_match(_Unwind_Control_Block* ucbp,
- const std::type_info* rttip,
- bool is_reference_type,
- void** matched_object);
-#endif
+ // Missing libcxxabi functions.
+ bool __cxa_uncaught_exception() throw();
+ void __cxa_decrement_exception_refcount(void* exceptionObject) throw();
+ void __cxa_increment_exception_refcount(void* exceptionObject) throw();
+ void __cxa_rethrow_primary_exception(void* exceptionObject);
+ void* __cxa_current_primary_exception() throw();
} // extern "C"
diff --git a/sources/cxx-stl/gabi++/include/exception b/sources/cxx-stl/gabi++/include/exception
index 53b1ab9..d4019ce 100644
--- a/sources/cxx-stl/gabi++/include/exception
+++ b/sources/cxx-stl/gabi++/include/exception
@@ -28,6 +28,8 @@
#ifndef __GABIXX_EXCEPTION__
#define __GABIXX_EXCEPTION__
+#if !defined(GABIXX_LIBCXX)
+
namespace std {
class exception {
@@ -56,18 +58,8 @@
bool uncaught_exception() throw();
- /*
- * Below APIs are used internally
- */
- void __terminate(terminate_handler);
- void __unexpected(unexpected_handler);
-
- extern terminate_handler default_terminate_fn;
- extern terminate_handler current_terminate_fn;
-
- extern unexpected_handler default_unexpected_fn;
- extern unexpected_handler current_unexpected_fn;
-
} // namespace std
+#endif // !defined(GABIXX_LIBCXX)
+
#endif // __GABIXX_EXCEPTION__
diff --git a/sources/cxx-stl/gabi++/include/new b/sources/cxx-stl/gabi++/include/new
index f026b1c..7687c9b 100644
--- a/sources/cxx-stl/gabi++/include/new
+++ b/sources/cxx-stl/gabi++/include/new
@@ -30,6 +30,8 @@
#ifndef __GABIXX_NEW__
#define __GABIXX_NEW__
+#if !defined(GABIXX_LIBCXX)
+
#include <cstddef>
#include <exception>
@@ -63,4 +65,6 @@
inline void operator delete(void*, void*) throw() {}
inline void operator delete[](void*, void*) throw() {}
+#endif // !defined(GABIXX_LIBCXX)
+
#endif // __GABIXX_NEW__
diff --git a/sources/cxx-stl/gabi++/include/typeinfo b/sources/cxx-stl/gabi++/include/typeinfo
index 3d03179..486eb40 100644
--- a/sources/cxx-stl/gabi++/include/typeinfo
+++ b/sources/cxx-stl/gabi++/include/typeinfo
@@ -35,6 +35,8 @@
#ifndef __GABIXX_TYPEINFO__
#define __GABIXX_TYPEINFO__
+#if !defined(GABIXX_LIBCXX)
+
#include <exception>
namespace std
@@ -63,9 +65,6 @@
return (__type_name[0] == '*') ? __type_name + 1 : __type_name;
}
- virtual bool can_catch(const type_info* thrown_type,
- void*& adjustedPtr) const = 0;
-
private:
// Assignment of type_info is not allowed.
type_info (const type_info& rhs);
@@ -94,4 +93,6 @@
} // namespace std
+#endif // !defined(GABIXX_LIBCXX)
+
#endif // _GABIXX_TYPEINFO_
diff --git a/sources/cxx-stl/gabi++/src/array_type_info.cc b/sources/cxx-stl/gabi++/src/array_type_info.cc
index 7eb11a6..302c5ae 100644
--- a/sources/cxx-stl/gabi++/src/array_type_info.cc
+++ b/sources/cxx-stl/gabi++/src/array_type_info.cc
@@ -35,7 +35,7 @@
{
}
- bool __array_type_info::can_catch(const std::type_info* thrown_type,
+ bool __array_type_info::can_catch(const __shim_type_info* thrown_type,
void*& adjustedPtr) const {
// Thrown array will be decayed to pointer, we cannot convert it back
return false;
diff --git a/sources/cxx-stl/gabi++/src/call_unexpected.cc b/sources/cxx-stl/gabi++/src/call_unexpected.cc
index 28c7076..4614aa9 100644
--- a/sources/cxx-stl/gabi++/src/call_unexpected.cc
+++ b/sources/cxx-stl/gabi++/src/call_unexpected.cc
@@ -63,6 +63,7 @@
*/
+#include <cstdlib>
#include <cxxabi.h>
#include <unwind.h>
#include "dwarf_helper.h"
@@ -71,33 +72,61 @@
namespace __cxxabiv1 {
#ifdef __arm__
- extern "C" __cxa_type_match_result __cxa_type_match(_Unwind_Exception* ucbp,
- const std::type_info* rttip,
- bool is_reference_type,
- void** matched_object) {
- __cxa_exception* header = reinterpret_cast<__cxa_exception*>(ucbp+1)-1;
- __cxa_type_match_result result = ctm_succeeded;
+extern "C" enum type_match_result {
+ ctm_failed = 0,
+ ctm_succeeded = 1,
+ ctm_succeeded_with_ptr_to_base = 2
+};
- void* adjustedPtr = header+1;
- if (dynamic_cast<const __pointer_type_info*>(header->exceptionType)) {
- adjustedPtr = *reinterpret_cast<void**>(adjustedPtr);
- result = ctm_succeeded_with_ptr_to_base;
- }
+extern "C" type_match_result __cxa_type_match(_Unwind_Exception* ucbp,
+ const __shim_type_info* rttip,
+ bool is_reference_type,
+ void** matched_object) {
- const std::type_info* catch_type = rttip;
- const std::type_info* thrown_type = header->exceptionType;
- if (!catch_type || !thrown_type) {
- return ctm_failed;
- }
+ __cxa_exception* header = reinterpret_cast<__cxa_exception*>(ucbp+1)-1;
+ type_match_result result = ctm_succeeded;
- if (catch_type->can_catch(thrown_type, adjustedPtr)) {
- *matched_object = adjustedPtr;
- return result;
- }
+ void* adjustedPtr = header+1;
+ if (dynamic_cast<const __pointer_type_info*>(header->exceptionType)) {
+ adjustedPtr = *reinterpret_cast<void**>(adjustedPtr);
+ result = ctm_succeeded_with_ptr_to_base;
+ }
+ const __shim_type_info* catch_type = rttip;
+ const __shim_type_info* thrown_type =
+ static_cast<const __shim_type_info*>(header->exceptionType);
+ if (!catch_type || !thrown_type) {
return ctm_failed;
}
+ if (catch_type->can_catch(thrown_type, adjustedPtr)) {
+ *matched_object = adjustedPtr;
+ return result;
+ }
+
+ return ctm_failed;
+}
+#endif // __arm__
+
+namespace {
+
+void terminate_helper(std::terminate_handler t_handler) {
+ try {
+ t_handler();
+ abort();
+ } catch (...) {
+ abort();
+ }
+}
+
+void unexpected_helper(std::unexpected_handler u_handler) {
+ u_handler();
+ std::terminate();
+}
+
+} // namespace
+
+#ifdef __arm__
extern "C" bool __cxa_begin_cleanup(_Unwind_Exception* exc) {
__cxa_eh_globals *globals = __cxa_get_globals();
__cxa_exception *header = reinterpret_cast<__cxa_exception*>(exc+1)-1;
@@ -174,7 +203,7 @@
__cxa_begin_catch(unwind_exception); // unexpected is also a handler
try {
- std::__unexpected(header->unexpectedHandler);
+ unexpected_helper(header->unexpectedHandler);
} catch (...) {
// A new exception thrown when calling unexpected.
bool allow_bad_exception = false;
@@ -182,7 +211,7 @@
for (uint32_t i = 0; i != count; ++i) {
uint32_t offset = reinterpret_cast<uint32_t>(&list[i * (stride >> 2)]);
offset = decodeRelocTarget2(offset);
- const std::type_info* catch_type = reinterpret_cast<const std::type_info*>(offset);
+ const __shim_type_info* catch_type = reinterpret_cast<const __shim_type_info*>(offset);
__cxa_exception* new_header = __cxa_get_globals()->caughtExceptions;
void* adjustedPtr = new_header + 1;
@@ -194,7 +223,9 @@
}
void* null_adjustedPtr = NULL;
- if (catch_type->can_catch(&typeid(std::bad_exception), null_adjustedPtr)) {
+ const __shim_type_info* bad_excp =
+ static_cast<const __shim_type_info*>(&typeid(std::bad_exception));
+ if (catch_type->can_catch(bad_excp, null_adjustedPtr)) {
allow_bad_exception = true;
}
}
@@ -206,7 +237,7 @@
throw std::bad_exception();
}
- std::__terminate(header->terminateHandler);
+ terminate_helper(header->terminateHandler);
}
}
#else // ! __arm__
@@ -227,7 +258,7 @@
old_exception_header = reinterpret_cast<__cxa_exception*>(unwind_exception+1)-1;
t_handler = old_exception_header->terminateHandler;
u_handler = old_exception_header->unexpectedHandler;
- // If std::__unexpected(u_handler) rethrows the same exception,
+ // If unexpected_helper(u_handler) rethrows the same exception,
// these values get overwritten by the rethrow. So save them now:
ttypeIndex = old_exception_header->handlerSwitchValue;
lsda = old_exception_header->languageSpecificData;
@@ -237,7 +268,7 @@
}
try {
- std::__unexpected(u_handler);
+ unexpected_helper(u_handler);
} catch (...) {
// A new exception thrown when calling unexpected.
@@ -248,14 +279,14 @@
const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
uint8_t ttypeEncoding = *lsda++;
if (ttypeEncoding == DW_EH_PE_omit) {
- std::__terminate(t_handler);
+ terminate_helper(t_handler);
}
uintptr_t classInfoOffset = readULEB128(&lsda);
const uint8_t* classInfo = lsda + classInfoOffset;
__cxa_eh_globals* globals = __cxa_get_globals_fast();
__cxa_exception* new_exception_header = globals->caughtExceptions;
if (new_exception_header == 0) { // This shouldn't be able to happen!
- std::__terminate(t_handler);
+ terminate_helper(t_handler);
}
bool native_new_exception =
new_exception_header->unwindHeader.exception_class == __gxx_exception_class;
@@ -289,7 +320,7 @@
} // catch (...)
// Call terminate after unexpected normally done
- std::__terminate(t_handler);
+ terminate_helper(t_handler);
}
#endif // __arm__
diff --git a/sources/cxx-stl/gabi++/src/class_type_info.cc b/sources/cxx-stl/gabi++/src/class_type_info.cc
index 6131fce..c2eabfa 100644
--- a/sources/cxx-stl/gabi++/src/class_type_info.cc
+++ b/sources/cxx-stl/gabi++/src/class_type_info.cc
@@ -35,7 +35,7 @@
{
}
- bool __class_type_info::can_catch(const std::type_info* thrown_type,
+ bool __class_type_info::can_catch(const __shim_type_info* thrown_type,
void*& adjustedPtr) const {
if (*this == *thrown_type) {
return true;
diff --git a/sources/cxx-stl/gabi++/src/cxxabi.cc b/sources/cxx-stl/gabi++/src/cxxabi.cc
index 60d1884..318fe5b 100644
--- a/sources/cxx-stl/gabi++/src/cxxabi.cc
+++ b/sources/cxx-stl/gabi++/src/cxxabi.cc
@@ -112,11 +112,11 @@
__cxa_thread_info *info = CxaThreadKey::getSlow();
header->unexpectedHandler = info->unexpectedHandler;
if (!header->unexpectedHandler) {
- header->unexpectedHandler = std::current_unexpected_fn;
+ header->unexpectedHandler = std::get_unexpected();
}
header->terminateHandler = info->terminateHandler;
if (!header->terminateHandler) {
- header->terminateHandler = std::current_terminate_fn;
+ header->terminateHandler = std::get_terminate();
}
info->globals.uncaughtExceptions += 1;
@@ -130,6 +130,8 @@
namespace __cxxabiv1 {
+ __shim_type_info::~__shim_type_info() {
+ }
extern "C" void __cxa_pure_virtual() {
fatalError("Pure virtual function called!");
@@ -268,4 +270,51 @@
return header->adjustedPtr;
}
+ extern "C" bool __cxa_uncaught_exception() throw() {
+ __cxa_eh_globals* globals = __cxa_get_globals();
+ if (globals == NULL)
+ return false;
+ return globals->uncaughtExceptions == 0;
+ }
+
+ extern "C" void __cxa_decrement_exception_refcount(void* exceptionObject) throw() {
+ if (exceptionObject != NULL)
+ {
+ __cxa_exception* header =
+ reinterpret_cast<__cxa_exception*>(
+ reinterpret_cast<_Unwind_Exception *>(exceptionObject)+1)-1;
+ if (__sync_sub_and_fetch(&header->referenceCount, 1) == 0) {
+ if (header->exceptionDestructor)
+ header->exceptionDestructor(exceptionObject);
+ __cxa_free_exception(exceptionObject);
+ }
+ }
+ }
+
+ extern "C" void __cxa_increment_exception_refcount(void* exceptionObject) throw() {
+ if (exceptionObject != NULL)
+ {
+ __cxa_exception* header =
+ reinterpret_cast<__cxa_exception*>(
+ reinterpret_cast<_Unwind_Exception *>(exceptionObject)+1)-1;
+ __sync_add_and_fetch(&header->referenceCount, 1);
+ }
+ }
+
+ extern "C" void __cxa_rethrow_primary_exception(void* primary_exception) {
+#if defined(GABIXX_LIBCXX)
+// Only warn if we're building for libcxx since other libraries do not use
+// this.
+#warning "not implemented."
+#endif /* defined(GABIXX_LIBCXX) */
+ }
+
+ extern "C" void* __cxa_current_primary_exception() throw() {
+#if defined(GABIXX_LIBCXX)
+// Only warn if we're building for libcxx since other libraries do not use
+// this.
+#warning "not implemented."
+#endif /* defined(GABIXX_LIBCXX) */
+ }
+
} // namespace __cxxabiv1
diff --git a/sources/cxx-stl/gabi++/src/enum_type_info.cc b/sources/cxx-stl/gabi++/src/enum_type_info.cc
index f6bb61b..c99b4c5 100644
--- a/sources/cxx-stl/gabi++/src/enum_type_info.cc
+++ b/sources/cxx-stl/gabi++/src/enum_type_info.cc
@@ -35,8 +35,8 @@
{
}
- bool __enum_type_info::can_catch(const std::type_info* thrown_type,
- void*& adjustedPtr) const {
+ bool __enum_type_info::can_catch(const __shim_type_info* thrown_type,
+ void*& adjustedPtr) const {
return *this == *thrown_type;
}
} // namespace __cxxabiv1
diff --git a/sources/cxx-stl/gabi++/src/function_type_info.cc b/sources/cxx-stl/gabi++/src/function_type_info.cc
index ca0daa6..a8d7164 100644
--- a/sources/cxx-stl/gabi++/src/function_type_info.cc
+++ b/sources/cxx-stl/gabi++/src/function_type_info.cc
@@ -35,8 +35,8 @@
{
}
- bool __function_type_info::can_catch(const std::type_info* thrown_type,
- void*& adjustedPtr) const {
+ bool __function_type_info::can_catch(const __shim_type_info* thrown_type,
+ void*& adjustedPtr) const {
// Thrown function will be converted to pointer, cannot convert it back
return false;
}
diff --git a/sources/cxx-stl/gabi++/src/fundamental_type_info.cc b/sources/cxx-stl/gabi++/src/fundamental_type_info.cc
index 6b28d2c..026a87a 100644
--- a/sources/cxx-stl/gabi++/src/fundamental_type_info.cc
+++ b/sources/cxx-stl/gabi++/src/fundamental_type_info.cc
@@ -35,7 +35,7 @@
{
}
- bool __fundamental_type_info::can_catch(const std::type_info* thrown_type,
+ bool __fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
void*& adjustedPtr) const {
return *this == *thrown_type;
}
diff --git a/sources/cxx-stl/gabi++/src/helper_func_internal.cc b/sources/cxx-stl/gabi++/src/helper_func_internal.cc
index 8425327..848f8de 100644
--- a/sources/cxx-stl/gabi++/src/helper_func_internal.cc
+++ b/sources/cxx-stl/gabi++/src/helper_func_internal.cc
@@ -48,6 +48,11 @@
namespace __cxxabiv1 {
+ const __shim_type_info* getTypePtr(uint64_t ttypeIndex,
+ const uint8_t* classInfo,
+ uint8_t ttypeEncoding,
+ _Unwind_Exception* unwind_exception);
+
void call_terminate(_Unwind_Exception* unwind_exception) {
__cxa_begin_catch(unwind_exception); // terminate is also a handler
std::terminate();
@@ -147,7 +152,7 @@
if (ttypeIndex > 0) {
// Found a catch, does it actually catch?
// First check for catch (...)
- const std::type_info* catchType =
+ const __shim_type_info* catchType =
getTypePtr(static_cast<uint64_t>(ttypeIndex),
classInfo, ttypeEncoding, unwind_exception);
if (catchType == 0) {
@@ -171,7 +176,8 @@
} else if (native_exception) {
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
void* adjustedPtr = unwind_exception+1;
- const std::type_info* excpType = exception_header->exceptionType;
+ const __shim_type_info* excpType =
+ static_cast<const __shim_type_info*>(exception_header->exceptionType);
if (adjustedPtr == 0 || excpType == 0) {
// Such a disaster! What's wrong?
call_terminate(unwind_exception);
@@ -297,15 +303,15 @@
return tmp;
}
- const std::type_info* getTypePtr(uint64_t ttypeIndex,
- const uint8_t* classInfo,
- uint8_t ttypeEncoding,
- _Unwind_Exception* unwind_exception) {
+ const __shim_type_info* getTypePtr(uint64_t ttypeIndex,
+ const uint8_t* classInfo,
+ uint8_t ttypeEncoding,
+ _Unwind_Exception* unwind_exception) {
if (classInfo == 0) { // eh table corrupted!
call_terminate(unwind_exception);
}
const uint8_t* ptr = classInfo - ttypeIndex * 4;
- return (const std::type_info*)decodeRelocTarget2((uint32_t)ptr);
+ return (const __shim_type_info*)decodeRelocTarget2((uint32_t)ptr);
}
bool canExceptionSpecCatch(int64_t specIndex,
@@ -329,9 +335,10 @@
}
ttypeIndex = decodeRelocTarget2((uint32_t)temp);
temp += 1;
- const std::type_info* catchType = (const std::type_info*) ttypeIndex;
+ const __shim_type_info* catchType = (const __shim_type_info*) ttypeIndex;
void* tempPtr = adjustedPtr;
- if (catchType->can_catch(excpType, tempPtr)) {
+ if (catchType->can_catch(
+ static_cast<const __shim_type_info*>(excpType), tempPtr)) {
return false;
}
} // while
@@ -409,10 +416,10 @@
#else // ! __arm__
- const std::type_info* getTypePtr(uint64_t ttypeIndex,
- const uint8_t* classInfo,
- uint8_t ttypeEncoding,
- _Unwind_Exception* unwind_exception) {
+ const __shim_type_info* getTypePtr(uint64_t ttypeIndex,
+ const uint8_t* classInfo,
+ uint8_t ttypeEncoding,
+ _Unwind_Exception* unwind_exception) {
if (classInfo == 0) { // eh table corrupted!
call_terminate(unwind_exception);
}
@@ -438,7 +445,7 @@
call_terminate(unwind_exception);
}
classInfo -= ttypeIndex;
- return (const std::type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
+ return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
}
bool canExceptionSpecCatch(int64_t specIndex,
@@ -460,12 +467,13 @@
if (ttypeIndex == 0) {
break;
}
- const std::type_info* catchType = getTypePtr(ttypeIndex,
- classInfo,
- ttypeEncoding,
- unwind_exception);
+ const __shim_type_info* catchType = getTypePtr(ttypeIndex,
+ classInfo,
+ ttypeEncoding,
+ unwind_exception);
void* tempPtr = adjustedPtr;
- if (catchType->can_catch(excpType, tempPtr)) {
+ if (catchType->can_catch(
+ static_cast<const __shim_type_info*>(excpType), tempPtr)) {
return false;
}
} // while
diff --git a/sources/cxx-stl/gabi++/src/helper_func_internal.h b/sources/cxx-stl/gabi++/src/helper_func_internal.h
index 2b0a189..c01681e 100644
--- a/sources/cxx-stl/gabi++/src/helper_func_internal.h
+++ b/sources/cxx-stl/gabi++/src/helper_func_internal.h
@@ -42,11 +42,6 @@
uint32_t decodeRelocTarget2 (uint32_t ptr);
#endif
- const std::type_info* getTypePtr(uint64_t ttypeIndex,
- const uint8_t* classInfo,
- uint8_t ttypeEncoding,
- _Unwind_Exception* unwind_exception);
-
// An exception spec acts like a catch handler, but in reverse.
// If any catchType in the list can catch an excpType,
// then this exception spec does not catch the excpType.
diff --git a/sources/cxx-stl/gabi++/src/new.cc b/sources/cxx-stl/gabi++/src/new.cc
index 6008900..de9cf7d 100644
--- a/sources/cxx-stl/gabi++/src/new.cc
+++ b/sources/cxx-stl/gabi++/src/new.cc
@@ -31,7 +31,9 @@
namespace std {
+#if !defined(GABIXX_LIBCXX)
const nothrow_t nothrow = {};
+#endif // !defined(GABIXX_LIBCXX)
bad_alloc::bad_alloc() throw() {
}
diff --git a/sources/cxx-stl/gabi++/src/pbase_type_info.cc b/sources/cxx-stl/gabi++/src/pbase_type_info.cc
index 09e8e2e..3169b57 100644
--- a/sources/cxx-stl/gabi++/src/pbase_type_info.cc
+++ b/sources/cxx-stl/gabi++/src/pbase_type_info.cc
@@ -35,13 +35,13 @@
{
}
- bool __pbase_type_info::can_catch(const std::type_info* thr_type,
+ bool __pbase_type_info::can_catch(const __shim_type_info* thr_type,
void*& adjustedPtr) const {
unsigned tracker = first_time_init;
return can_catch_typeinfo_wrapper(thr_type, adjustedPtr, tracker);
}
- bool __pbase_type_info::can_catch_typeinfo_wrapper(const std::type_info* thr_type,
+ bool __pbase_type_info::can_catch_typeinfo_wrapper(const __shim_type_info* thr_type,
void*& adjustedPtr,
unsigned tracker) const {
if (*this == *thr_type) {
diff --git a/sources/cxx-stl/gabi++/src/terminate.cc b/sources/cxx-stl/gabi++/src/terminate.cc
index 17435f9..2e70d35 100644
--- a/sources/cxx-stl/gabi++/src/terminate.cc
+++ b/sources/cxx-stl/gabi++/src/terminate.cc
@@ -31,43 +31,43 @@
namespace std {
- // The default std::terminate() implementation will crash the process.
- // This is done to help debugging, i.e.:
- // - When running the program in a debugger, it's trivial to get
- // a complete stack trace explaining the failure.
- //
- // - Otherwise, the default SIGSEGV handler will generate a stack
- // trace in the log, that can later be processed with ndk-stack
- // and other tools.
- //
- // - Finally, this also works when a custom SIGSEGV handler has been
- // installed. E.g. when using Google Breakpad, the termination will
- // be recorded in a Minidump, which contains a stack trace to be
- // later analyzed.
- //
- // The C++ specification states that the default std::terminate()
- // handler is library-specific, even though most implementation simply
- // choose to call abort() in this case.
- //
- static void default_terminate(void) {
- // The crash address is just a "magic" constant that can be used to
- // identify stack traces (like 0xdeadbaad is used when heap corruption
- // is detected in the C library). 'cab1' stands for "C++ ABI" :-)
- *(reinterpret_cast<char*>(0xdeadcab1)) = 0;
+ namespace {
+ // The default std::terminate() implementation will crash the process.
+ // This is done to help debugging, i.e.:
+ // - When running the program in a debugger, it's trivial to get
+ // a complete stack trace explaining the failure.
+ //
+ // - Otherwise, the default SIGSEGV handler will generate a stack
+ // trace in the log, that can later be processed with ndk-stack
+ // and other tools.
+ //
+ // - Finally, this also works when a custom SIGSEGV handler has been
+ // installed. E.g. when using Google Breakpad, the termination will
+ // be recorded in a Minidump, which contains a stack trace to be
+ // later analyzed.
+ //
+ // The C++ specification states that the default std::terminate()
+ // handler is library-specific, even though most implementation simply
+ // choose to call abort() in this case.
+ //
+ void default_terminate(void) {
+ // The crash address is just a "magic" constant that can be used to
+ // identify stack traces (like 0xdeadbaad is used when heap corruption
+ // is detected in the C library). 'cab1' stands for "C++ ABI" :-)
+ *(reinterpret_cast<char*>(0xdeadcab1)) = 0;
- // should not be here, but just in case.
- abort();
- }
+ // should not be here, but just in case.
+ abort();
+ }
- terminate_handler default_terminate_fn = default_terminate;
- terminate_handler current_terminate_fn = default_terminate_fn;
+ terminate_handler current_terminate_fn = default_terminate;
+ unexpected_handler current_unexpected_fn = terminate;
+ } // namespace
- unexpected_handler default_unexpected_fn = terminate;
- unexpected_handler current_unexpected_fn = default_unexpected_fn;
-
-
+#if !defined(GABIXX_LIBCXX)
exception::exception() throw() {
}
+#endif // !defined(GABIXX_LIBCXX)
exception::~exception() throw() {
}
@@ -76,6 +76,7 @@
return "std::exception";
}
+#if !defined(GABIXX_LIBCXX)
bad_exception::bad_exception() throw() {
}
@@ -85,6 +86,7 @@
const char* bad_exception::what() const throw() {
return "std::bad_exception";
}
+#endif // !defined(GABIXX_LIBCXX)
bad_cast::bad_cast() throw() {
}
@@ -140,20 +142,6 @@
terminate();
}
- void __terminate(terminate_handler t_handler) {
- try {
- t_handler();
- abort();
- } catch (...) {
- abort();
- }
- }
-
- void __unexpected(unexpected_handler u_handler) {
- u_handler();
- terminate();
- }
-
bool uncaught_exception() throw() {
using namespace __cxxabiv1;
diff --git a/sources/cxx-stl/gabi++/src/type_info.cc b/sources/cxx-stl/gabi++/src/type_info.cc
index 69b9f3a..fedc144 100644
--- a/sources/cxx-stl/gabi++/src/type_info.cc
+++ b/sources/cxx-stl/gabi++/src/type_info.cc
@@ -43,6 +43,7 @@
{
}
+#if !defined(GABIXX_LIBCXX)
bool
type_info::operator==(const type_info& rhs) const
{
@@ -72,4 +73,6 @@
return this < &rhs;
#endif
}
+
+#endif // !defined(GABIXX_LIBCXX)
} // end namespace std
diff --git a/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk b/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
index 0a178bc..191bfb8 100644
--- a/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
+++ b/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
@@ -33,28 +33,37 @@
llvm_libc++_sources += \
support/android/locale_support.c \
- support/android/wchar_support.c
+ support/android/nl_types_support.c \
+ support/android/stdlib_support.c \
+ support/android/wchar_support.c \
+ support/android/wctype_support.c
llvm_libc++_sources := $(llvm_libc++_sources:%=src/%)
-llvm_libc++_cxxflags := -std=c++11
+llvm_libc++_export_cxxflags := -std=c++11
+llvm_libc++_cxxflags := $(llvm_libc++_export_cxxflags) \
+ -DGABIXX_LIBCXX=1 -DLIBCXXRT=1
+
+include $(dir $(LOCAL_PATH))../../gabi++/sources.mk
+llvm_libc++_includes += $(libgabi++_c_includes)
include $(CLEAR_VARS)
LOCAL_MODULE := llvm_libc++_static
LOCAL_SRC_FILES := $(llvm_libc++_sources)
+LOCAL_SRC_FILES += $(libgabi++_src_files:%=../gabi++/%)
LOCAL_C_INCLUDES := $(llvm_libc++_includes)
LOCAL_CPPFLAGS := $(llvm_libc++_cxxflags)
+LOCAL_CPP_FEATURES := rtti exceptions
LOCAL_EXPORT_C_INCLUDES := $(llvm_libc++_export_includes)
-LOCAL_EXPORT_STATIC_LIBRARIES := libgabi++_static
+LOCAL_EXPORT_CPPFLAGS := $(llvm_libc++_export_cxxflags)
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := llvm_libc++_shared
LOCAL_SRC_FILES := $(llvm_libc++_sources)
+LOCAL_SRC_FILES += $(libgabi++_src_files:%=../gabi++/%)
LOCAL_C_INCLUDES := $(llvm_libc++_includes)
-LOCAL_CPPFLAGS := $(llvm_libc++_cxxflags)
+LOCAL_CPPFLAGS := $(llvm_libc++_cxxflags) -DGABIXX_LIBCXX=1 -DLIBCXXRT=1
+LOCAL_CPP_FEATURES := rtti exceptions
LOCAL_EXPORT_C_INCLUDES := $(llvm_libc++_export_includes)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgabi++_static
+LOCAL_EXPORT_CPPFLAGS := $(llvm_libc++_export_cxxflags)
include $(BUILD_SHARED_LIBRARY)
-
-$(call import-module,cxx-stl/gabi++)
-
diff --git a/sources/cxx-stl/llvm-libc++/android/test/jni/Android.mk b/sources/cxx-stl/llvm-libc++/android/test/jni/Android.mk
index 345dfb6..aff740c 100644
--- a/sources/cxx-stl/llvm-libc++/android/test/jni/Android.mk
+++ b/sources/cxx-stl/llvm-libc++/android/test/jni/Android.mk
@@ -13,7 +13,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := test_1_static
LOCAL_SRC_FILES := test_1.cc
-LOCAL_SHARED_LIBRARIES := llvm_libc++_static
+LOCAL_STATIC_LIBRARIES := llvm_libc++_static
include $(BUILD_EXECUTABLE)
include $(LOCAL_PATH)/../../llvm-libc++/Android.mk
diff --git a/sources/cxx-stl/llvm-libc++/android/test/jni/Application.mk b/sources/cxx-stl/llvm-libc++/android/test/jni/Application.mk
index 0da80f3..091cc9f 100644
--- a/sources/cxx-stl/llvm-libc++/android/test/jni/Application.mk
+++ b/sources/cxx-stl/llvm-libc++/android/test/jni/Application.mk
@@ -1,4 +1,6 @@
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.TXT for details.
+APP_OPTIM := debug
APP_ABI := all
+APP_STL := none
diff --git a/sources/cxx-stl/llvm-libc++/android/test/jni/test_1.cc b/sources/cxx-stl/llvm-libc++/android/test/jni/test_1.cc
index 963d8a1..7ed5af3 100644
--- a/sources/cxx-stl/llvm-libc++/android/test/jni/test_1.cc
+++ b/sources/cxx-stl/llvm-libc++/android/test/jni/test_1.cc
@@ -9,8 +9,14 @@
//===----------------------------------------------------------------------===//
#include <iostream>
+#include <locale>
int main(void) {
- std::cout << "Hello World\n" << std::endl;
+ // TODO(ajwong): This imbue should not be required. There is a problem with
+ // the module initialization code that causes the default "C" locale to not
+ // be created correctly. The manual imbue allows us to proceed with
+ // development for now.
+ std::cout.imbue(std::locale("C"));
+ std::cout << "Hello World" << std::endl;
return 0;
}
diff --git a/sources/cxx-stl/llvm-libc++/include/__locale b/sources/cxx-stl/llvm-libc++/include/__locale
index 4176720..64e350b 100644
--- a/sources/cxx-stl/llvm-libc++/include/__locale
+++ b/sources/cxx-stl/llvm-libc++/include/__locale
@@ -367,6 +367,20 @@
static const mask punct = _ISPUNCT;
static const mask xdigit = _ISXDIGIT;
static const mask blank = _ISBLANK;
+#elif __ANDROID__
+ typedef char mask;
+ static const mask space = _S;
+ static const mask print = _P | _U | _L | _N | _B;
+ static const mask cntrl = _C;
+ static const mask upper = _U;
+ static const mask lower = _L;
+ static const mask alpha = _U | _L;
+ static const mask digit = _N;
+ static const mask punct = _P;
+ static const mask xdigit = _N | _X;
+
+ // TODO(ajwong): bionic doesn't have a blank mask
+ static const mask blank = 0;
#else // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ || __sun__
typedef unsigned long mask;
static const mask space = 1<<0;
@@ -585,6 +599,8 @@
#ifdef _CACHED_RUNES
static const size_t table_size = _CACHED_RUNES;
+#elif __ANDROID__
+ static const size_t table_size = __ctype_c_mask_table_size;
#else
static const size_t table_size = 256; // FIXME: Don't hardcode this.
#endif
diff --git a/sources/cxx-stl/llvm-libc++/include/regex b/sources/cxx-stl/llvm-libc++/include/regex
index 982500f..85f3882 100644
--- a/sources/cxx-stl/llvm-libc++/include/regex
+++ b/sources/cxx-stl/llvm-libc++/include/regex
@@ -933,7 +933,7 @@
typedef locale locale_type;
typedef ctype_base::mask char_class_type;
- static const char_class_type __regex_word = 0x80;
+ static const char_class_type __regex_word;
private:
locale __loc_;
const ctype<char_type>* __ct_;
@@ -1008,6 +1008,8 @@
int __value(wchar_t __ch, int __radix) const;
};
+template <class _CharT> const typename regex_traits<_CharT>::char_class_type regex_traits<_CharT>::__regex_word = 0x80;
+
template <class _CharT>
regex_traits<_CharT>::regex_traits()
{
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/locale.h b/sources/cxx-stl/llvm-libc++/include/support/android/locale.h
index 01c834f..ab099aa 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/locale.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/locale.h
@@ -85,6 +85,11 @@
struct lconv* localeconv(void);
+// Used to implement the std::ctype<char> specialization.
+extern const char * const __ctype_c_mask_table;
+// TODO(ajwong): Make this based on some exported bionic constant.
+const int __ctype_c_mask_table_size = 256;
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/stdlib.h b/sources/cxx-stl/llvm-libc++/include/support/android/stdlib.h
index bafbfe5..35d21c9 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/stdlib.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/stdlib.h
@@ -28,6 +28,8 @@
unsigned long long strtoull_l(const char *nptr, char **endptr, int base, locale_t loc);
long double strtold_l (const char *nptr, char **endptr, locale_t loc);
+int mbtowc(wchar_t *pwc, const char *pmb, size_t max);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/sources/cxx-stl/llvm-libc++/src/locale.cpp b/sources/cxx-stl/llvm-libc++/src/locale.cpp
index 53a8a4c..e4c40de 100644
--- a/sources/cxx-stl/llvm-libc++/src/locale.cpp
+++ b/sources/cxx-stl/llvm-libc++/src/locale.cpp
@@ -978,6 +978,11 @@
return _DefaultRuneLocale.__runetype;
#elif defined(__GLIBC__)
return __cloc()->__ctype_b;
+#elif defined(__ANDROID__)
+ // TODO(ajwong): Should the actual traits functions delegate to the
+ // bionic ctype variants? Or should we do something similar to how we
+ // handle glibc where we use the _tolower_tab_ and _toupper_tab_ directly?
+ return __ctype_c_mask_table;
#elif __sun__
return __ctype_mask;
#elif _WIN32
diff --git a/sources/cxx-stl/llvm-libc++/src/support/android/locale_support.c b/sources/cxx-stl/llvm-libc++/src/support/android/locale_support.c
index 7bad7ec..8aa2919 100644
--- a/sources/cxx-stl/llvm-libc++/src/support/android/locale_support.c
+++ b/sources/cxx-stl/llvm-libc++/src/support/android/locale_support.c
@@ -51,6 +51,49 @@
define_char_wrapper_l (tolower)
define_char_wrapper_l (toupper)
+// TODO(ajwong): This table is copied from bionic's ctype implementation.
+// It doesn't support signed chars and will index out of bounds. The best way
+// to fix is to patch bionic's ctype array to support both signed and
+// unsigned char and then just directly reference it.
+static char const real_ctype_c_mask_table[256] = {
+ 0,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _S|(char)_B, _P, _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, _P, _P, _P, _P,
+ _N, _N, _N, _N, _N, _N, _N, _N,
+ _N, _N, _P, _P, _P, _P, _P, _P,
+ _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _P, _P, _P, _P, _P,
+ _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ /* determine printability based on the IS0 8859 8-bit standard */
+ _L, _L, _L, _P, _P, _P, _P, _C,
+
+ _C, _C, _C, _C, _C, _C, _C, _C, /* 80 */
+ _C, _C, _C, _C, _C, _C, _C, _C, /* 88 */
+ _C, _C, _C, _C, _C, _C, _C, _C, /* 90 */
+ _C, _C, _C, _C, _C, _C, _C, _C, /* 98 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* A0 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* A8 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* B0 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* B8 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* C0 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* C8 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* D0 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* D8 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* E0 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* E8 */
+ _P, _P, _P, _P, _P, _P, _P, _P, /* F0 */
+ _P, _P, _P, _P, _P, _P, _P, _P /* F8 */
+};
+char const* const __ctype_c_mask_table = &real_ctype_c_mask_table[0];
+
///////////////////////////////////////////////////////////////////////
// stdio.h declarations
@@ -209,7 +252,6 @@
return copy;
}
-
// Static mutable variable because setlocale() is supposed to return
// a pointer to a writable C string.
static char g_C_LOCALE_SETTING[] = "C";
diff --git a/sources/cxx-stl/llvm-libc++/src/support/android/nl_types_support.c b/sources/cxx-stl/llvm-libc++/src/support/android/nl_types_support.c
new file mode 100644
index 0000000..b30e0e6
--- /dev/null
+++ b/sources/cxx-stl/llvm-libc++/src/support/android/nl_types_support.c
@@ -0,0 +1,20 @@
+// Contains an implementation of nl_types functions missing from bionic.
+//
+// TODO(ajwong): Make these work.
+
+#include <nl_types.h>
+
+nl_catd catopen(const char* name, int oflag) {
+#warning Not implemented
+ return 0;
+}
+
+char* catgets(nl_catd catd, int set_id, int msg_id, const char* s) {
+#warning Not implemented
+ return 0;
+}
+
+int catclose(nl_catd catd) {
+#warning Not implemented
+ return 0;
+}
diff --git a/sources/cxx-stl/llvm-libc++/src/support/android/stdlib_support.c b/sources/cxx-stl/llvm-libc++/src/support/android/stdlib_support.c
new file mode 100644
index 0000000..9cea38d
--- /dev/null
+++ b/sources/cxx-stl/llvm-libc++/src/support/android/stdlib_support.c
@@ -0,0 +1,15 @@
+// Contains an implementation of all stdlib functions missing from bionic.
+//
+// TODO(ajwong): Make these work.
+
+#include <stdlib.h>
+
+long double strtold(const char* nptr, char** endptr) {
+#warning Not implemented
+ return 0;
+}
+
+int mbtowc(wchar_t *pwc, const char *pmb, size_t max) {
+#warning Not implemented
+ return 0;
+}
diff --git a/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c b/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c
index 5227382..748f5d4 100644
--- a/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c
+++ b/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c
@@ -382,3 +382,42 @@
return s;
}
+float wcstof(const wchar_t* nptr, wchar_t** endptr) {
+#warning Not implemented
+ return 0;
+}
+
+long wcstol(const wchar_t* nptr, wchar_t** endptr, int base) {
+#warning Not implemented
+ return 0;
+}
+
+long double wcstold(const wchar_t* nptr, wchar_t** endptr) {
+#warning Not implemented
+ return 0;
+}
+
+long long wcstoll(const wchar_t* nptr, wchar_t** endptr, int base) {
+#warning Not implemented
+ return 0;
+}
+
+unsigned long long wcstoull(const wchar_t* nptr, wchar_t** endptr, int base) {
+#warning Not implemented
+ return 0;
+}
+
+size_t wcsnrtombs(char *dst,
+ const wchar_t **src,
+ size_t nwc, size_t len,
+ mbstate_t *ps) {
+#warning Not implemented
+ return 0;
+}
+
+size_t mbsnrtowcs(wchar_t *dst,
+ const char **src, size_t nmc,
+ size_t len, mbstate_t *ps) {
+#warning Not implemented
+ return 0;
+}
diff --git a/sources/cxx-stl/llvm-libc++/src/support/android/wctype_support.c b/sources/cxx-stl/llvm-libc++/src/support/android/wctype_support.c
new file mode 100644
index 0000000..1961459
--- /dev/null
+++ b/sources/cxx-stl/llvm-libc++/src/support/android/wctype_support.c
@@ -0,0 +1,9 @@
+// Contains an implementation of stdlib functions missing from bionic.
+//
+// TODO(ajwong): Make these work.
+
+#include <wctype.h>
+
+int iswblank(wint_t c) {
+ return 0;
+}