diff --git a/ChangeLog.md b/ChangeLog.md index b758b0f3ec622..f5eab38abdfe7 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,6 +20,7 @@ See docs/process.md for more on how version tagging works. 2.0.23 ------ +- libcxxabi updated to llvm-12. (#14288) - libcxx updated to llvm-12. (#14249) - compiler-rt updated to llvm-12. (#14280) diff --git a/system/lib/libcxxabi/include/__cxxabi_config.h b/system/lib/libcxxabi/include/__cxxabi_config.h index cbbb1c10c1a29..cffedb88df543 100644 --- a/system/lib/libcxxabi/include/__cxxabi_config.h +++ b/system/lib/libcxxabi/include/__cxxabi_config.h @@ -18,6 +18,19 @@ #define __has_attribute(_attribute_) 0 #endif +#if defined(__clang__) +# define _LIBCXXABI_COMPILER_CLANG +# ifndef __apple_build_version__ +# define _LIBCXXABI_CLANG_VER (__clang_major__ * 100 + __clang_minor__) +# endif +#elif defined(__GNUC__) +# define _LIBCXXABI_COMPILER_GCC +#elif defined(_MSC_VER) +# define _LIBCXXABI_COMPILER_MSVC +#elif defined(__IBMCPP__) +# define _LIBCXXABI_COMPILER_IBM +#endif + #if defined(_WIN32) #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) #define _LIBCXXABI_HIDDEN @@ -53,7 +66,7 @@ #endif #endif -#if defined(_WIN32) +#if defined(_LIBCXXABI_COMPILER_MSVC) #define _LIBCXXABI_WEAK #else #define _LIBCXXABI_WEAK __attribute__((__weak__)) @@ -72,8 +85,16 @@ #endif // wasm32 follows the arm32 ABI convention of using 32-bit guard. -#if defined(__arm__) || defined(__wasm32__) +#if defined(__arm__) || defined(__wasm32__) || defined(__ARM64_ARCH_8_32__) # define _LIBCXXABI_GUARD_ABI_ARM #endif +#if defined(_LIBCXXABI_COMPILER_CLANG) +# if !__has_feature(cxx_exceptions) +# define _LIBCXXABI_NO_EXCEPTIONS +# endif +#elif defined(_LIBCXXABI_COMPILER_GCC) && !__EXCEPTIONS +# define _LIBCXXABI_NO_EXCEPTIONS +#endif + #endif // ____CXXABI_CONFIG_H diff --git a/system/lib/libcxxabi/include/cxxabi.h b/system/lib/libcxxabi/include/cxxabi.h index 3ffb1a167f388..8b5368150b8e3 100644 --- a/system/lib/libcxxabi/include/cxxabi.h +++ b/system/lib/libcxxabi/include/cxxabi.h @@ -21,6 +21,7 @@ #define _LIBCPPABI_VERSION 1002 #define _LIBCXXABI_NORETURN __attribute__((noreturn)) +#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold)) #ifdef __cplusplus @@ -82,13 +83,13 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void); // 3.3.2 One-time Construction API #if defined(_LIBCXXABI_GUARD_ABI_ARM) -extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint32_t *); -extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint32_t *); -extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint32_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *); #else -extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint64_t *); -extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint64_t *); -extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint64_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *); #endif // 3.3.3 Array Construction and Destruction API @@ -140,9 +141,9 @@ __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count, void (*destructor)(void *)); // 3.3.5.3 Runtime API -extern _LIBCXXABI_FUNC_VIS int __cxa_atexit(void (*f)(void *), void *p, - void *d); -extern _LIBCXXABI_FUNC_VIS int __cxa_finalize(void *); +// These functions are part of the C++ ABI, but they are not defined in libc++abi: +// int __cxa_atexit(void (*)(void *), void *, void *); +// void __cxa_finalize(void *); // 3.4 Demangler API extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name, diff --git a/system/lib/libcxxabi/readme.txt b/system/lib/libcxxabi/readme.txt index bb5d5adb3898e..7822f8cbc5dc8 100644 --- a/system/lib/libcxxabi/readme.txt +++ b/system/lib/libcxxabi/readme.txt @@ -1,7 +1,7 @@ llvm's libcxxabi ---------------- -These files are from the llvm-project based on release 10.0.0. +These files are from the llvm-project based on release 12.0.0. We maintain a local fork of llvm-project that contains any emscripten specific patches: @@ -10,8 +10,8 @@ specific patches: The current patch is based on: -tag: llvmorg-10.0.0 -git: d32170dbd5b0d54436537b6b75beaf44324e0c28 +tag: llvmorg-12.0.0 +git: d28af7c654d8db0b68c175db5ce212d74fb5e9bc Update Instructions ------------------- diff --git a/system/lib/libcxxabi/src/CMakeLists.txt b/system/lib/libcxxabi/src/CMakeLists.txt index b38973b0b1794..a8e12aa36e643 100644 --- a/system/lib/libcxxabi/src/CMakeLists.txt +++ b/system/lib/libcxxabi/src/CMakeLists.txt @@ -7,7 +7,6 @@ set(LIBCXXABI_SOURCES cxa_exception_storage.cpp cxa_guard.cpp cxa_handlers.cpp - cxa_unexpected.cpp cxa_vector.cpp cxa_virtual.cpp # C++ STL files @@ -21,7 +20,9 @@ set(LIBCXXABI_SOURCES ) if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS) - list(APPEND LIBCXXABI_SOURCES stdlib_new_delete.cpp) + list(APPEND LIBCXXABI_SOURCES + stdlib_new_delete.cpp + ) endif() if (LIBCXXABI_ENABLE_EXCEPTIONS) @@ -60,6 +61,10 @@ if (LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) add_definitions(-DHAVE___CXA_THREAD_ATEXIT_IMPL) endif() +if (LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST) + add_definitions(-D_LIBCXXABI_FORGIVING_DYNAMIC_CAST) +endif() + if (APPLE) add_library_flags_if(LIBCXXABI_HAS_SYSTEM_LIB System) else() @@ -95,6 +100,9 @@ if (MINGW) # MINGW_LIBRARIES is defined in config-ix.cmake list(APPEND LIBCXXABI_LIBRARIES ${MINGW_LIBRARIES}) endif() +if (ANDROID AND ANDROID_PLATFORM_LEVEL LESS 21) + list(APPEND LIBCXXABI_LIBRARIES android_support) +endif() if (NOT LIBCXXABI_USE_COMPILER_RT) add_library_flags_if(LIBCXXABI_HAS_GCC_LIB gcc) @@ -128,6 +136,17 @@ if ( APPLE ) add_link_flags("-Wl,-rpath,${LIBDIR}") endif() endif() + + # Make sure we link in CrashReporterClient if we find it -- it's used by + # abort() on Apple platforms when building the system dylib. + find_library(CrashReporterClient NAMES libCrashReporterClient.a + PATHS "${CMAKE_OSX_SYSROOT}/usr/local/lib") + if (CrashReporterClient) + message(STATUS "Linking with CrashReporterClient at ${CrashReporterClient}") + add_library_flags("${CrashReporterClient}") + else() + message(STATUS "Could not find CrashReporterClient, not linking against it") + endif() endif() split_list(LIBCXXABI_COMPILE_FLAGS) @@ -143,18 +162,9 @@ if (NOT TARGET pstl::ParallelSTL) message(STATUS "Could not find ParallelSTL, libc++abi will not attempt to use it but the build may fail if the libc++ in use needs it to be available.") endif() -if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(armv6|armv7|armv7s)$") - set(LIBCXXABI_USE_SJLJ_EXCEPTIONS ON) -else() - set(LIBCXXABI_USE_SJLJ_EXCEPTIONS OFF) -endif() - # Build the shared library. if (LIBCXXABI_ENABLE_SHARED) add_library(cxxabi_shared SHARED ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS}) - if(COMMAND llvm_setup_rpath) - llvm_setup_rpath(cxxabi_shared) - endif() target_link_libraries(cxxabi_shared PRIVATE ${LIBCXXABI_SHARED_LIBRARIES} ${LIBCXXABI_LIBRARIES}) if (TARGET pstl::ParallelSTL) target_link_libraries(cxxabi_shared PUBLIC pstl::ParallelSTL) @@ -164,9 +174,9 @@ if (LIBCXXABI_ENABLE_SHARED) CXX_EXTENSIONS OFF CXX_STANDARD - 11 + 20 CXX_STANDARD_REQUIRED - ON + OFF COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}" LINK_FLAGS @@ -189,18 +199,32 @@ if (LIBCXXABI_ENABLE_SHARED) list(APPEND LIBCXXABI_INSTALL_TARGETS "cxxabi_shared") endif() + add_library(cxxabi-reexports INTERFACE) + # -exported_symbols_list is only available on Apple platforms if (APPLE) - target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/itanium-base.exp") + function(export_symbols file) + target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${file}") + endfunction() + function(reexport_symbols file) + export_symbols("${file}") + target_link_libraries(cxxabi-reexports INTERFACE "-Wl,-reexported_symbols_list,${file}") + endfunction() + + export_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/itanium-base.exp") if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS) - target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/new-delete.exp") + reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/new-delete.exp") endif() - if (LIBCXXABI_USE_SJLJ_EXCEPTIONS) - target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-sjlj.exp") - else() - target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-v0.exp") + if (LIBCXXABI_ENABLE_EXCEPTIONS) + reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/exceptions.exp") + + if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(armv6|armv7|armv7s)$") + reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-sjlj.exp") + else() + reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-v0.exp") + endif() endif() endif() endif() @@ -217,9 +241,9 @@ if (LIBCXXABI_ENABLE_STATIC) CXX_EXTENSIONS OFF CXX_STANDARD - 11 + 20 CXX_STANDARD_REQUIRED - ON + OFF COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}" LINK_FLAGS @@ -255,10 +279,10 @@ if (LIBCXXABI_ENABLE_STATIC) set(MERGE_ARCHIVES_LIBTOOL "--use-libtool" "--libtool" "${CMAKE_LIBTOOL}") endif() - # Merge the the libc++abi.a and libunwind.a into one. + # Merge the libc++abi.a and libunwind.a into one. if(LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY) add_custom_command(TARGET cxxabi_static POST_BUILD - COMMAND ${PYTHON_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/merge_archives.py + COMMAND ${Python3_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/merge_archives.py ARGS -o "$" --ar "${CMAKE_AR}" @@ -292,7 +316,4 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND LIBCXXABI_INSTALL_LIBRARY) -DCMAKE_INSTALL_COMPONENT=cxxabi -DCMAKE_INSTALL_DO_STRIP=1 -P "${LIBCXXABI_BINARY_DIR}/cmake_install.cmake") - - # TODO: This is a legacy target name and should be removed at some point. - add_custom_target(install-libcxxabi DEPENDS install-cxxabi) endif() diff --git a/system/lib/libcxxabi/src/abort_message.cpp b/system/lib/libcxxabi/src/abort_message.cpp index 4bb7fe37bfb6e..4aa4f71321428 100644 --- a/system/lib/libcxxabi/src/abort_message.cpp +++ b/system/lib/libcxxabi/src/abort_message.cpp @@ -12,61 +12,63 @@ #include "abort_message.h" #ifdef __BIONIC__ -#include -#if __ANDROID_API__ >= 21 -#include -extern "C" void android_set_abort_message(const char* msg); -#else -#include -#endif // __ANDROID_API__ >= 21 +# include +# if __ANDROID_API__ >= 21 +# include + extern "C" void android_set_abort_message(const char* msg); +# else +# include +# endif // __ANDROID_API__ >= 21 #endif // __BIONIC__ -#ifdef __APPLE__ -# if defined(__has_include) && __has_include() -# define HAVE_CRASHREPORTERCLIENT_H -# include -# endif +#if defined(__APPLE__) && __has_include() +# include +# define _LIBCXXABI_USE_CRASHREPORTER_CLIENT #endif void abort_message(const char* format, ...) { - // write message to stderr + // Write message to stderr. We do this before formatting into a + // variable-size buffer so that we still get some information if + // formatting into the variable-sized buffer fails. #if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL) -#ifdef __APPLE__ - fprintf(stderr, "libc++abi.dylib: "); -#endif + { #if defined(__EMSCRIPTEN__) && defined(NDEBUG) - // Just trap in a non-debug build. These internal libcxxabi assertions are - // very rare, and it's not worth linking in vfprintf stdio support or - // even minimal logging for them, as we'll have a proper call stack, which - // will show a call into "abort_message", and can help debugging. (In a - // debug build that won't be inlined.) - __builtin_trap(); + // Just trap in a non-debug build. These internal libcxxabi assertions are + // very rare, and it's not worth linking in vfprintf stdio support or + // even minimal logging for them, as we'll have a proper call stack, which + // will show a call into "abort_message", and can help debugging. (In a + // debug build that won't be inlined.) + __builtin_trap(); #else + fprintf(stderr, "libc++abi: "); + va_list list; + va_start(list, format); + vfprintf(stderr, format, list); + va_end(list); + fprintf(stderr, "\n"); +#endif + } +#endif + + // Format the arguments into an allocated buffer. We leak the buffer on + // purpose, since we're about to abort() anyway. +#if defined(_LIBCXXABI_USE_CRASHREPORTER_CLIENT) + char* buffer; va_list list; va_start(list, format); - vfprintf(stderr, format, list); + vasprintf(&buffer, format, list); va_end(list); - fprintf(stderr, "\n"); -#endif // EMSCRIPTEN -#endif -#if defined(__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) - // record message in crash report - char* buffer; - va_list list2; - va_start(list2, format); - vasprintf(&buffer, format, list2); - va_end(list2); CRSetCrashLogMessage(buffer); #elif defined(__BIONIC__) char* buffer; - va_list list2; - va_start(list2, format); - vasprintf(&buffer, format, list2); - va_end(list2); + va_list list; + va_start(list, format); + vasprintf(&buffer, format, list); + va_end(list); -#if __ANDROID_API__ >= 21 +# if __ANDROID_API__ >= 21 // Show error in tombstone. android_set_abort_message(buffer); @@ -74,12 +76,12 @@ void abort_message(const char* format, ...) openlog("libc++abi", 0, 0); syslog(LOG_CRIT, "%s", buffer); closelog(); -#else +# else // The good error reporting wasn't available in Android until L. Since we're // about to abort anyway, just call __assert2, which will log _somewhere_ // (tombstone and/or logcat) in older releases. __assert2(__FILE__, __LINE__, __func__, buffer); -#endif // __ANDROID_API__ >= 21 +# endif // __ANDROID_API__ >= 21 #endif // __BIONIC__ abort(); diff --git a/system/lib/libcxxabi/src/abort_message.h b/system/lib/libcxxabi/src/abort_message.h index 7cb11f4c2ff56..83f956f74f6ed 100644 --- a/system/lib/libcxxabi/src/abort_message.h +++ b/system/lib/libcxxabi/src/abort_message.h @@ -11,16 +11,7 @@ #include "cxxabi.h" -#ifdef __cplusplus -extern "C" { -#endif - -_LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void +extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void abort_message(const char *format, ...) __attribute__((format(printf, 1, 2))); -#ifdef __cplusplus -} #endif - -#endif - diff --git a/system/lib/libcxxabi/src/cxa_default_handlers.cpp b/system/lib/libcxxabi/src/cxa_default_handlers.cpp index de256c5a68689..a24ee01453436 100644 --- a/system/lib/libcxxabi/src/cxa_default_handlers.cpp +++ b/system/lib/libcxxabi/src/cxa_default_handlers.cpp @@ -45,7 +45,7 @@ static void demangling_terminate_handler() exception_header + 1; const __shim_type_info* thrown_type = static_cast(exception_header->exceptionType); -#ifndef __EMSCRIPTEN__ +#if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE) // Try to get demangled name of thrown_type int status; char buf[1024]; @@ -53,8 +53,7 @@ static void demangling_terminate_handler() const char* name = __cxa_demangle(thrown_type->name(), buf, &len, &status); if (status != 0) name = thrown_type->name(); -#else // __EMSCRIPTEN__ - we can demangle stack traces ourselves, best not to - // pull in all of libcxxabi-demangle for just this file +#else const char* name = thrown_type->name(); #endif // If the uncaught exception can be caught with std::exception& diff --git a/system/lib/libcxxabi/src/cxa_guard_impl.h b/system/lib/libcxxabi/src/cxa_guard_impl.h index a8ec0b72feea2..6f873f241fade 100644 --- a/system/lib/libcxxabi/src/cxa_guard_impl.h +++ b/system/lib/libcxxabi/src/cxa_guard_impl.h @@ -40,7 +40,6 @@ #include "__cxxabi_config.h" #include "include/atomic_support.h" #include -#include #if defined(__has_include) # if __has_include() # include @@ -55,6 +54,14 @@ #endif #endif +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wtautological-pointer-compare" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Waddress" +#endif + // To make testing possible, this header is included from both cxa_guard.cpp // and a number of tests. // @@ -108,6 +115,32 @@ struct LazyValue { bool is_init = false; }; +template +class AtomicInt { +public: + using MemoryOrder = std::__libcpp_atomic_order; + + explicit AtomicInt(IntType *b) : b_(b) {} + AtomicInt(AtomicInt const&) = delete; + AtomicInt& operator=(AtomicInt const&) = delete; + + IntType load(MemoryOrder ord) { + return std::__libcpp_atomic_load(b_, ord); + } + void store(IntType val, MemoryOrder ord) { + std::__libcpp_atomic_store(b_, val, ord); + } + IntType exchange(IntType new_val, MemoryOrder ord) { + return std::__libcpp_atomic_exchange(b_, new_val, ord); + } + bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) { + return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure); + } + +private: + IntType *b_; +}; + //===----------------------------------------------------------------------===// // PlatformGetThreadID //===----------------------------------------------------------------------===// @@ -129,14 +162,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr; constexpr bool PlatformSupportsThreadID() { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#endif return +PlatformThreadID != nullptr; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif } //===----------------------------------------------------------------------===// @@ -195,7 +221,7 @@ struct GuardObject { public: /// base_address - the address of the original guard object. void* const base_address; - /// The address of the guord byte at offset 0. + /// The address of the guard byte at offset 0. uint8_t* const guard_byte_address; /// The address of the byte used by the implementation during initialization. uint8_t* const init_byte_address; @@ -350,18 +376,18 @@ struct InitByteGlobalMutex LockGuard& operator=(LockGuard const&) = delete; explicit LockGuard(const char* calling_func) - : calling_func(calling_func) { + : calling_func_(calling_func) { if (global_mutex.lock()) - ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func); + ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_); } ~LockGuard() { if (global_mutex.unlock()) - ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func); + ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func_); } private: - const char* const calling_func; + const char* const calling_func_; }; }; @@ -386,14 +412,7 @@ constexpr void (*PlatformFutexWake)(int*) = nullptr; #endif constexpr bool PlatformSupportsFutex() { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#endif return +PlatformFutexWait != nullptr; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif } /// InitByteFutex - Manages initialization using atomics and the futex syscall @@ -564,4 +583,10 @@ using SelectedImplementation = } // end namespace } // end namespace __cxxabiv1 +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + #endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H diff --git a/system/lib/libcxxabi/src/cxa_handlers.h b/system/lib/libcxxabi/src/cxa_handlers.h index c8e2e44aee1f0..a96d7e5bcf901 100644 --- a/system/lib/libcxxabi/src/cxa_handlers.h +++ b/system/lib/libcxxabi/src/cxa_handlers.h @@ -12,7 +12,7 @@ #ifndef _CXA_HANDLERS_H #define _CXA_HANDLERS_H -#include <__cxxabi_config.h> +#include "__cxxabi_config.h" #include diff --git a/system/lib/libcxxabi/src/cxa_personality.cpp b/system/lib/libcxxabi/src/cxa_personality.cpp index 3715e7c7dcf08..5b7599792cd86 100644 --- a/system/lib/libcxxabi/src/cxa_personality.cpp +++ b/system/lib/libcxxabi/src/cxa_personality.cpp @@ -686,27 +686,21 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, return; } landingPad = (uintptr_t)lpStart + landingPad; + results.landingPad = landingPad; #else // __USING_SJLJ_OR_WASM_EXCEPTIONS__ ++landingPad; #endif // !__USING_SJLJ_OR_WASM_EXCEPTIONS__ if (actionEntry == 0) { // Found a cleanup - // If this is a type 1 or type 2 search, there are no handlers - // If this is a type 3 search, you want to install the cleanup. - if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) - { - results.ttypeIndex = 0; // Redundant but clarifying - results.landingPad = landingPad; - results.reason = _URC_HANDLER_FOUND; - return; - } - // No handler here - results.reason = _URC_CONTINUE_UNWIND; + results.reason = actions & _UA_SEARCH_PHASE + ? _URC_CONTINUE_UNWIND + : _URC_HANDLER_FOUND; return; } // Convert 1-based byte offset into const uint8_t* action = actionTableStart + (actionEntry - 1); + bool hasCleanup = false; // Scan action entries until you find a matching handler, cleanup, or the end of action list while (true) { @@ -722,32 +716,17 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, native_exception, unwind_exception); if (catchType == 0) { - // Found catch (...) catches everything, including foreign exceptions - // If this is a type 1 search save state and return _URC_HANDLER_FOUND - // If this is a type 2 search save state and return _URC_HANDLER_FOUND - // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! - // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan -#ifdef __USING_WASM_EXCEPTIONS__ - // Wasm does not do two-phase unwinding and only uses cleanup phase - if (actions & _UA_CLEANUP_PHASE) -#else - if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) -#endif - { - // Save state and return _URC_HANDLER_FOUND - results.ttypeIndex = ttypeIndex; - results.actionRecord = actionRecord; - results.landingPad = landingPad; - results.adjustedPtr = get_thrown_object_ptr(unwind_exception); - results.reason = _URC_HANDLER_FOUND; - return; - } - else if (!(actions & _UA_FORCE_UNWIND)) - { - // It looks like the exception table has changed - // on us. Likely stack corruption! - call_terminate(native_exception, unwind_exception); - } + // Found catch (...) catches everything, including + // foreign exceptions. This is search phase, cleanup + // phase with foreign exception, or forced unwinding. + assert(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME | + _UA_FORCE_UNWIND)); + results.ttypeIndex = ttypeIndex; + results.actionRecord = actionRecord; + results.adjustedPtr = + get_thrown_object_ptr(unwind_exception); + results.reason = _URC_HANDLER_FOUND; + return; } // Else this is a catch (T) clause and will never // catch a foreign exception @@ -764,41 +743,25 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, } if (catchType->can_catch(excpType, adjustedPtr)) { - // Found a matching handler - // If this is a type 1 search save state and return _URC_HANDLER_FOUND - // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1! - // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan -#ifdef __USING_WASM_EXCEPTIONS__ - // Wasm does not do two-phase unwinding and only uses cleanup phase - if (actions & _UA_CLEANUP_PHASE) -#else - if (actions & _UA_SEARCH_PHASE) -#endif - { - // Save state and return _URC_HANDLER_FOUND - results.ttypeIndex = ttypeIndex; - results.actionRecord = actionRecord; - results.landingPad = landingPad; - results.adjustedPtr = adjustedPtr; - results.reason = _URC_HANDLER_FOUND; - return; - } - else if (!(actions & _UA_FORCE_UNWIND)) - { - // It looks like the exception table has changed - // on us. Likely stack corruption! - call_terminate(native_exception, unwind_exception); - } + // Found a matching handler. This is either search + // phase or forced unwinding. + assert(actions & + (_UA_SEARCH_PHASE | _UA_FORCE_UNWIND)); + results.ttypeIndex = ttypeIndex; + results.actionRecord = actionRecord; + results.adjustedPtr = adjustedPtr; + results.reason = _URC_HANDLER_FOUND; + return; } } // Scan next action ... } else if (ttypeIndex < 0) { - // Found an exception spec. If this is a foreign exception, - // it is always caught. - if (native_exception) - { + // Found an exception specification. + if (actions & _UA_FORCE_UNWIND) { + // Skip if forced unwinding. + } else if (native_exception) { // Does the exception spec catch this native exception? __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; void* adjustedPtr = get_thrown_object_ptr(unwind_exception); @@ -813,87 +776,36 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, ttypeEncoding, excpType, adjustedPtr, unwind_exception)) { - // native exception caught by exception spec - // If this is a type 1 search, save state and return _URC_HANDLER_FOUND - // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! - // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan -#ifdef __USING_WASM_EXCEPTIONS__ - // Wasm does not do two-phase unwinding and only uses cleanup phase - if (actions & _UA_CLEANUP_PHASE) -#else - if (actions & _UA_SEARCH_PHASE) -#endif - { - // Save state and return _URC_HANDLER_FOUND - results.ttypeIndex = ttypeIndex; - results.actionRecord = actionRecord; - results.landingPad = landingPad; - results.adjustedPtr = adjustedPtr; - results.reason = _URC_HANDLER_FOUND; - return; - } - else if (!(actions & _UA_FORCE_UNWIND)) - { - // It looks like the exception table has changed - // on us. Likely stack corruption! - call_terminate(native_exception, unwind_exception); - } - } - } - else - { - // foreign exception caught by exception spec - // If this is a type 1 search, save state and return _URC_HANDLER_FOUND - // If this is a type 2 search, save state and return _URC_HANDLER_FOUND - // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! - // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan -#ifdef __USING_WASM_EXCEPTIONS__ - // Wasm does not do two-phase unwinding and only uses cleanup phase - if (actions & _UA_CLEANUP_PHASE) -#else - if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) -#endif - { - // Save state and return _URC_HANDLER_FOUND - results.ttypeIndex = ttypeIndex; + // Native exception caught by exception + // specification. results.actionRecord = actionRecord; - results.landingPad = landingPad; - results.adjustedPtr = get_thrown_object_ptr(unwind_exception); + results.adjustedPtr = adjustedPtr; results.reason = _URC_HANDLER_FOUND; return; } - else if (!(actions & _UA_FORCE_UNWIND)) - { - // It looks like the exception table has changed - // on us. Likely stack corruption! - call_terminate(native_exception, unwind_exception); - } - } - // Scan next action ... - } - else // ttypeIndex == 0 - { - // Found a cleanup - // If this is a type 1 search, ignore it and continue scan - // If this is a type 2 search, ignore it and continue scan - // If this is a type 3 search, save state and return _URC_HANDLER_FOUND - if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) - { - // Save state and return _URC_HANDLER_FOUND + } else { + // foreign exception caught by exception spec results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; - results.landingPad = landingPad; - results.adjustedPtr = get_thrown_object_ptr(unwind_exception); + results.adjustedPtr = + get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } + // Scan next action ... + } else { + hasCleanup = true; } const uint8_t* temp = action; int64_t actionOffset = readSLEB128(&temp); if (actionOffset == 0) { - // End of action list, no matching handler or cleanup found - results.reason = _URC_CONTINUE_UNWIND; + // End of action list. If this is phase 2 and we have found + // a cleanup (ttypeIndex=0), return _URC_HANDLER_FOUND; + // otherwise return _URC_CONTINUE_UNWIND. + results.reason = hasCleanup && actions & _UA_CLEANUP_PHASE + ? _URC_HANDLER_FOUND + : _URC_CONTINUE_UNWIND; return; } // Go to next action @@ -986,88 +898,61 @@ __gxx_personality_v0 bool native_exception = (exceptionClass & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language); scan_results results; + // Process a catch handler for a native exception first. + if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME) && + native_exception) { + // Reload the results from the phase 1 cache. + __cxa_exception* exception_header = + (__cxa_exception*)(unwind_exception + 1) - 1; + results.ttypeIndex = exception_header->handlerSwitchValue; + results.actionRecord = exception_header->actionRecord; + results.languageSpecificData = exception_header->languageSpecificData; + results.landingPad = + reinterpret_cast(exception_header->catchTemp); + results.adjustedPtr = exception_header->adjustedPtr; + + // Jump to the handler. + set_registers(unwind_exception, context, results); + return _URC_INSTALL_CONTEXT; + } + + // In other cases we need to scan LSDA. + scan_eh_tab(results, actions, native_exception, unwind_exception, context); + if (results.reason == _URC_CONTINUE_UNWIND || + results.reason == _URC_FATAL_PHASE1_ERROR) + return results.reason; + if (actions & _UA_SEARCH_PHASE) { // Phase 1 search: All we're looking for in phase 1 is a handler that // halts unwinding - scan_eh_tab(results, actions, native_exception, unwind_exception, context); - if (results.reason == _URC_HANDLER_FOUND) - { - // Found one. Can we cache the results somewhere to optimize phase 2? - if (native_exception) - { - __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; - exception_header->handlerSwitchValue = static_cast(results.ttypeIndex); - exception_header->actionRecord = results.actionRecord; - exception_header->languageSpecificData = results.languageSpecificData; - exception_header->catchTemp = reinterpret_cast(results.landingPad); - exception_header->adjustedPtr = results.adjustedPtr; - } - return _URC_HANDLER_FOUND; + assert(results.reason == _URC_HANDLER_FOUND); + if (native_exception) { + // For a native exception, cache the LSDA result. + __cxa_exception* exc = (__cxa_exception*)(unwind_exception + 1) - 1; + exc->handlerSwitchValue = static_cast(results.ttypeIndex); + exc->actionRecord = results.actionRecord; + exc->languageSpecificData = results.languageSpecificData; + exc->catchTemp = reinterpret_cast(results.landingPad); + exc->adjustedPtr = results.adjustedPtr; } - // Did not find a catching-handler. Return the results of the scan - // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR - // if we were called improperly). - return results.reason; + return _URC_HANDLER_FOUND; } - if (actions & _UA_CLEANUP_PHASE) - { - // Phase 2 search: - // Did we find a catching handler in phase 1? - if (actions & _UA_HANDLER_FRAME) - { - // Yes, phase 1 said we have a catching handler here. - // Did we cache the results of the scan? - if (native_exception) - { - // Yes, reload the results from the cache. - __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; - results.ttypeIndex = exception_header->handlerSwitchValue; - results.actionRecord = exception_header->actionRecord; - results.languageSpecificData = exception_header->languageSpecificData; - results.landingPad = reinterpret_cast(exception_header->catchTemp); - results.adjustedPtr = exception_header->adjustedPtr; - } - else - { - // No, do the scan again to reload the results. - scan_eh_tab(results, actions, native_exception, unwind_exception, context); - // Phase 1 told us we would find a handler. Now in Phase 2 we - // didn't find a handler. The eh table should not be changing! - if (results.reason != _URC_HANDLER_FOUND) - call_terminate(native_exception, unwind_exception); - } - // Jump to the handler - set_registers(unwind_exception, context, results); - return _URC_INSTALL_CONTEXT; - } - // Either we didn't do a phase 1 search (due to forced unwinding), or - // phase 1 reported no catching-handlers. - // Search for a (non-catching) cleanup - scan_eh_tab(results, actions, native_exception, unwind_exception, context); - if (results.reason == _URC_HANDLER_FOUND) - { - // Found a non-catching handler. Jump to it: - set_registers(unwind_exception, context, results); + + assert(actions & _UA_CLEANUP_PHASE); + assert(results.reason == _URC_HANDLER_FOUND); + set_registers(unwind_exception, context, results); #ifdef __USING_WASM_EXCEPTIONS__ - // Wasm uses only one phase in _UA_CLEANUP_PHASE, so we should set - // these here. - __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; - exception_header->handlerSwitchValue = static_cast(results.ttypeIndex); - exception_header->actionRecord = results.actionRecord; - exception_header->languageSpecificData = results.languageSpecificData; - exception_header->catchTemp = reinterpret_cast(results.landingPad); - exception_header->adjustedPtr = results.adjustedPtr; + // Wasm uses only one phase in _UA_CLEANUP_PHASE, so we should set + // these here. + __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; + exception_header->handlerSwitchValue = static_cast(results.ttypeIndex); + exception_header->actionRecord = results.actionRecord; + exception_header->languageSpecificData = results.languageSpecificData; + exception_header->catchTemp = reinterpret_cast(results.landingPad); + exception_header->adjustedPtr = results.adjustedPtr; #endif - return _URC_INSTALL_CONTEXT; - } - // Did not find a cleanup. Return the results of the scan - // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR - // if we were called improperly). - return results.reason; - } - // We were called improperly: neither a phase 1 or phase 2 search - return _URC_FATAL_PHASE1_ERROR; + return _URC_INSTALL_CONTEXT; } #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) diff --git a/system/lib/libcxxabi/src/cxa_unexpected.cpp b/system/lib/libcxxabi/src/cxa_unexpected.cpp deleted file mode 100644 index bbfa6684efa74..0000000000000 --- a/system/lib/libcxxabi/src/cxa_unexpected.cpp +++ /dev/null @@ -1,22 +0,0 @@ -//===------------------------- cxa_unexpected.cpp -------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include -#include "cxxabi.h" -#include "cxa_exception.h" - -namespace __cxxabiv1 -{ - -extern "C" -{ - -} - -} // namespace __cxxabiv1 - diff --git a/system/lib/libcxxabi/src/cxa_vector.cpp b/system/lib/libcxxabi/src/cxa_vector.cpp index f20e978d36ef3..325bbf22d2011 100644 --- a/system/lib/libcxxabi/src/cxa_vector.cpp +++ b/system/lib/libcxxabi/src/cxa_vector.cpp @@ -24,9 +24,9 @@ namespace __cxxabiv1 { -#if 0 -#pragma mark --Helper routines and classes -- -#endif +// +// Helper routines and classes +// namespace { inline static size_t __get_element_count ( void *p ) { @@ -111,9 +111,9 @@ namespace { }; } -#if 0 -#pragma mark --Externally visible routines-- -#endif +// +// Externally visible routines +// namespace { _LIBCXXABI_NORETURN diff --git a/system/lib/libcxxabi/src/demangle/ItaniumDemangle.h b/system/lib/libcxxabi/src/demangle/ItaniumDemangle.h index 376e0efea423d..e5fca98f92717 100644 --- a/system/lib/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/system/lib/libcxxabi/src/demangle/ItaniumDemangle.h @@ -82,6 +82,7 @@ X(PostfixExpr) \ X(ConditionalExpr) \ X(MemberExpr) \ + X(SubobjectExpr) \ X(EnclosingExpr) \ X(CastExpr) \ X(SizeofParamPackExpr) \ @@ -91,14 +92,14 @@ X(PrefixExpr) \ X(FunctionParam) \ X(ConversionExpr) \ + X(PointerToMemberConversionExpr) \ X(InitListExpr) \ X(FoldExpr) \ X(ThrowExpr) \ - X(UUIDOfExpr) \ X(BoolExpr) \ X(StringLiteral) \ X(LambdaExpr) \ - X(IntegerCastExpr) \ + X(EnumLiteral) \ X(IntegerLiteral) \ X(FloatLiteral) \ X(DoubleLiteral) \ @@ -1656,6 +1657,40 @@ class MemberExpr : public Node { } }; +class SubobjectExpr : public Node { + const Node *Type; + const Node *SubExpr; + StringView Offset; + NodeArray UnionSelectors; + bool OnePastTheEnd; + +public: + SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_, + NodeArray UnionSelectors_, bool OnePastTheEnd_) + : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_), + UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {} + + template void match(Fn F) const { + F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd); + } + + void printLeft(OutputStream &S) const override { + SubExpr->print(S); + S += ".<"; + Type->print(S); + S += " at offset "; + if (Offset.empty()) { + S += "0"; + } else if (Offset[0] == 'n') { + S += "-"; + S += Offset.dropFront(); + } else { + S += Offset; + } + S += ">"; + } +}; + class EnclosingExpr : public Node { const StringView Prefix; const Node *Infix; @@ -1843,6 +1878,28 @@ class ConversionExpr : public Node { } }; +class PointerToMemberConversionExpr : public Node { + const Node *Type; + const Node *SubExpr; + StringView Offset; + +public: + PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_, + StringView Offset_) + : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_), + Offset(Offset_) {} + + template void match(Fn F) const { F(Type, SubExpr, Offset); } + + void printLeft(OutputStream &S) const override { + S += "("; + Type->print(S); + S += ")("; + SubExpr->print(S); + S += ")"; + } +}; + class InitListExpr : public Node { const Node *Ty; NodeArray Inits; @@ -1977,21 +2034,6 @@ class ThrowExpr : public Node { } }; -// MSVC __uuidof extension, generated by clang in -fms-extensions mode. -class UUIDOfExpr : public Node { - Node *Operand; -public: - UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {} - - template void match(Fn F) const { F(Operand); } - - void printLeft(OutputStream &S) const override { - S << "__uuidof("; - Operand->print(S); - S << ")"; - } -}; - class BoolExpr : public Node { bool Value; @@ -2036,22 +2078,26 @@ class LambdaExpr : public Node { } }; -class IntegerCastExpr : public Node { +class EnumLiteral : public Node { // ty(integer) const Node *Ty; StringView Integer; public: - IntegerCastExpr(const Node *Ty_, StringView Integer_) - : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {} + EnumLiteral(const Node *Ty_, StringView Integer_) + : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {} template void match(Fn F) const { F(Ty, Integer); } void printLeft(OutputStream &S) const override { - S += "("; + S << "("; Ty->print(S); - S += ")"; - S += Integer; + S << ")"; + + if (Integer[0] == 'n') + S << "-" << Integer.dropFront(1); + else + S << Integer; } }; @@ -2309,9 +2355,9 @@ template struct AbstractManglingParser { TemplateParamList Params; public: - ScopedTemplateParamList(AbstractManglingParser *Parser) - : Parser(Parser), - OldNumTemplateParamLists(Parser->TemplateParams.size()) { + ScopedTemplateParamList(AbstractManglingParser *TheParser) + : Parser(TheParser), + OldNumTemplateParamLists(TheParser->TemplateParams.size()) { Parser->TemplateParams.push_back(&Params); } ~ScopedTemplateParamList() { @@ -2433,6 +2479,8 @@ template struct AbstractManglingParser { Node *parseConversionExpr(); Node *parseBracedExpr(); Node *parseFoldExpr(); + Node *parsePointerToMemberConversionExpr(); + Node *parseSubobjectExpr(); /// Parse the production. Node *parseType(); @@ -4064,8 +4112,11 @@ Qualifiers AbstractManglingParser::parseCVQualifiers() { // ::= fp _ # L == 0, second and later parameters // ::= fL p _ # L > 0, first parameter // ::= fL p _ # L > 0, second and later parameters +// ::= fpT # 'this' expression (not part of standard?) template Node *AbstractManglingParser::parseFunctionParam() { + if (consumeIf("fpT")) + return make("this"); if (consumeIf("fp")) { parseCVQualifiers(); StringView Num = parseNumber(); @@ -4225,7 +4276,13 @@ Node *AbstractManglingParser::parseExprPrimary() { return getDerived().template parseFloatingLiteral(); case 'e': ++First; +#if defined(__powerpc__) || defined(__s390__) + // Handle cases where long doubles encoded with e have the same size + // and representation as doubles. + return getDerived().template parseFloatingLiteral(); +#else return getDerived().template parseFloatingLiteral(); +#endif case '_': if (consumeIf("_Z")) { Node *R = getDerived().parseEncoding(); @@ -4264,12 +4321,12 @@ Node *AbstractManglingParser::parseExprPrimary() { Node *T = getDerived().parseType(); if (T == nullptr) return nullptr; - StringView N = parseNumber(); + StringView N = parseNumber(/*AllowNegative=*/true); if (N.empty()) return nullptr; if (!consumeIf('E')) return nullptr; - return make(T, N); + return make(T, N); } } } @@ -4391,6 +4448,50 @@ Node *AbstractManglingParser::parseFoldExpr() { return make(IsLeftFold, OperatorName, Pack, Init); } +// ::= mc [] E +// +// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 +template +Node *AbstractManglingParser::parsePointerToMemberConversionExpr() { + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + Node *Expr = getDerived().parseExpr(); + if (!Expr) + return nullptr; + StringView Offset = getDerived().parseNumber(true); + if (!consumeIf('E')) + return nullptr; + return make(Ty, Expr, Offset); +} + +// ::= so [] * [p] E +// ::= _ [] +// +// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 +template +Node *AbstractManglingParser::parseSubobjectExpr() { + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + Node *Expr = getDerived().parseExpr(); + if (!Expr) + return nullptr; + StringView Offset = getDerived().parseNumber(true); + size_t SelectorsBegin = Names.size(); + while (consumeIf('_')) { + Node *Selector = make(parseNumber()); + if (!Selector) + return nullptr; + Names.push_back(Selector); + } + bool OnePastTheEnd = consumeIf('p'); + if (!consumeIf('E')) + return nullptr; + return make( + Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd); +} + // ::= // ::= // ::= @@ -4648,6 +4749,9 @@ Node *AbstractManglingParser::parseExpr() { return nullptr; case 'm': switch (First[1]) { + case 'c': + First += 2; + return parsePointerToMemberConversionExpr(); case 'i': First += 2; return getDerived().parseBinaryExpr("-"); @@ -4795,6 +4899,9 @@ Node *AbstractManglingParser::parseExpr() { return Ex; return make("static_cast", T, Ex); } + case 'o': + First += 2; + return parseSubobjectExpr(); case 'p': { First += 2; Node *Child = getDerived().parseExpr(); @@ -4890,6 +4997,43 @@ Node *AbstractManglingParser::parseExpr() { } } return nullptr; + case 'u': { + ++First; + Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr); + if (!Name) + return nullptr; + // Special case legacy __uuidof mangling. The 't' and 'z' appear where the + // standard encoding expects a , and would be otherwise be + // interpreted as node 'short' or 'ellipsis'. However, neither + // __uuidof(short) nor __uuidof(...) can actually appear, so there is no + // actual conflict here. + if (Name->getBaseName() == "__uuidof") { + if (numLeft() < 2) + return nullptr; + if (*First == 't') { + ++First; + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + return make(Name, makeNodeArray(&Ty, &Ty + 1)); + } + if (*First == 'z') { + ++First; + Node *Ex = getDerived().parseExpr(); + if (!Ex) + return nullptr; + return make(Name, makeNodeArray(&Ex, &Ex + 1)); + } + } + size_t ExprsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseTemplateArg(); + if (E == nullptr) + return E; + Names.push_back(E); + } + return make(Name, popTrailingNodeArray(ExprsBegin)); + } case '1': case '2': case '3': @@ -4901,21 +5045,6 @@ Node *AbstractManglingParser::parseExpr() { case '9': return getDerived().parseUnresolvedName(); } - - if (consumeIf("u8__uuidoft")) { - Node *Ty = getDerived().parseType(); - if (!Ty) - return nullptr; - return make(Ty); - } - - if (consumeIf("u8__uuidofz")) { - Node *Ex = getDerived().parseExpr(); - if (!Ex) - return nullptr; - return make(Ex); - } - return nullptr; } @@ -4962,6 +5091,16 @@ Node *AbstractManglingParser::parseSpecialName() { switch (look()) { case 'T': switch (look(1)) { + // TA # template parameter object + // + // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63 + case 'A': { + First += 2; + Node *Arg = getDerived().parseTemplateArg(); + if (Arg == nullptr) + return nullptr; + return make("template parameter object for ", Arg); + } // TV # virtual table case 'V': { First += 2; @@ -5083,6 +5222,22 @@ Node *AbstractManglingParser::parseSpecialName() { // ::= template Node *AbstractManglingParser::parseEncoding() { + // The template parameters of an encoding are unrelated to those of the + // enclosing context. + class SaveTemplateParams { + AbstractManglingParser *Parser; + decltype(TemplateParams) OldParams; + + public: + SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) { + OldParams = std::move(Parser->TemplateParams); + Parser->TemplateParams.clear(); + } + ~SaveTemplateParams() { + Parser->TemplateParams = std::move(OldParams); + } + } SaveTemplateParams(this); + if (look() == 'G' || look() == 'T') return getDerived().parseSpecialName(); @@ -5174,7 +5329,12 @@ struct FloatData #else static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms #endif - static const size_t max_demangled_size = 40; + // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes. + // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits. + // Negatives are one character longer than positives. + // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the + // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128. + static const size_t max_demangled_size = 42; static constexpr const char *spec = "%LaL"; }; diff --git a/system/lib/libcxxabi/src/demangle/Utility.h b/system/lib/libcxxabi/src/demangle/Utility.h index 04e1936ebbe78..846a5f0818e7e 100644 --- a/system/lib/libcxxabi/src/demangle/Utility.h +++ b/system/lib/libcxxabi/src/demangle/Utility.h @@ -52,7 +52,7 @@ class OutputStream { char *TempPtr = std::end(Temp); while (N) { - *--TempPtr = '0' + char(N % 10); + *--TempPtr = char('0' + N % 10); N /= 10; } diff --git a/system/lib/libcxxabi/src/fallback_malloc.cpp b/system/lib/libcxxabi/src/fallback_malloc.cpp index fdae40764abef..f3d7937793ce4 100644 --- a/system/lib/libcxxabi/src/fallback_malloc.cpp +++ b/system/lib/libcxxabi/src/fallback_malloc.cpp @@ -6,9 +6,6 @@ // //===----------------------------------------------------------------------===// -// Define _LIBCPP_BUILDING_LIBRARY to ensure _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION -// is only defined when libc aligned allocation is not available. -#define _LIBCPP_BUILDING_LIBRARY #include "fallback_malloc.h" #include <__threading_support> @@ -20,6 +17,7 @@ #include // for malloc, calloc, free #include // for memset +#include // for std::__libcpp_aligned_{alloc,free} // A small, simple heap manager based (loosely) on // the startup heap manager from FreeBSD, optimized for space. @@ -144,29 +142,26 @@ void fallback_free(void* ptr) { mutexor mtx(&heap_mutex); #ifdef DEBUG_FALLBACK_MALLOC - std::cout << "Freeing item at " << offset_from_node(cp) << " of size " - << cp->len << std::endl; + std::printf("Freeing item at %d of size %d\n", offset_from_node(cp), cp->len); #endif for (p = freelist, prev = 0; p && p != list_end; prev = p, p = node_from_offset(p->next_node)) { #ifdef DEBUG_FALLBACK_MALLOC - std::cout << " p, cp, after (p), after(cp) " << offset_from_node(p) << ' ' - << offset_from_node(cp) << ' ' << offset_from_node(after(p)) - << ' ' << offset_from_node(after(cp)) << std::endl; + std::printf(" p=%d, cp=%d, after(p)=%d, after(cp)=%d\n", + offset_from_node(p), offset_from_node(cp), + offset_from_node(after(p)), offset_from_node(after(cp))); #endif if (after(p) == cp) { #ifdef DEBUG_FALLBACK_MALLOC - std::cout << " Appending onto chunk at " << offset_from_node(p) - << std::endl; + std::printf(" Appending onto chunk at %d\n", offset_from_node(p)); #endif p->len = static_cast( p->len + cp->len); // make the free heap_node larger return; } else if (after(cp) == p) { // there's a free heap_node right after #ifdef DEBUG_FALLBACK_MALLOC - std::cout << " Appending free chunk at " << offset_from_node(p) - << std::endl; + std::printf(" Appending free chunk at %d\n", offset_from_node(p)); #endif cp->len = static_cast(cp->len + p->len); if (prev == 0) { @@ -179,8 +174,7 @@ void fallback_free(void* ptr) { } // Nothing to merge with, add it to the start of the free list #ifdef DEBUG_FALLBACK_MALLOC - std::cout << " Making new free list entry " << offset_from_node(cp) - << std::endl; + std::printf(" Making new free list entry %d\n", offset_from_node(cp)); #endif cp->next_node = offset_from_node(freelist); freelist = cp; @@ -195,11 +189,11 @@ size_t print_free_list() { for (p = freelist, prev = 0; p && p != list_end; prev = p, p = node_from_offset(p->next_node)) { - std::cout << (prev == 0 ? "" : " ") << "Offset: " << offset_from_node(p) - << "\tsize: " << p->len << " Next: " << p->next_node << std::endl; + std::printf("%sOffset: %d\tsize: %d Next: %d\n", + (prev == 0 ? "" : " "), offset_from_node(p), p->len, p->next_node); total_free += p->len; } - std::cout << "Total Free space: " << total_free << std::endl; + std::printf("Total Free space: %d\n", total_free); return total_free; } #endif @@ -211,7 +205,7 @@ struct __attribute__((aligned)) __aligned_type {}; void* __aligned_malloc_with_fallback(size_t size) { #if defined(_WIN32) - if (void* dest = _aligned_malloc(size, alignof(__aligned_type))) + if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size)) return dest; #elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) if (void* dest = ::malloc(size)) @@ -219,8 +213,7 @@ void* __aligned_malloc_with_fallback(size_t size) { #else if (size == 0) size = 1; - void* dest; - if (::posix_memalign(&dest, __alignof(__aligned_type), size) == 0) + if (void* dest = std::__libcpp_aligned_alloc(__alignof(__aligned_type), size)) return dest; #endif return fallback_malloc(size); @@ -241,10 +234,10 @@ void __aligned_free_with_fallback(void* ptr) { if (is_fallback_ptr(ptr)) fallback_free(ptr); else { -#if defined(_WIN32) - ::_aligned_free(ptr); -#else +#if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) ::free(ptr); +#else + std::__libcpp_aligned_free(ptr); #endif } } diff --git a/system/lib/libcxxabi/src/include/atomic_support.h b/system/lib/libcxxabi/src/include/atomic_support.h index 4ff45eb93add9..6f9dbf4360479 100644 --- a/system/lib/libcxxabi/src/include/atomic_support.h +++ b/system/lib/libcxxabi/src/include/atomic_support.h @@ -177,34 +177,4 @@ bool __libcpp_atomic_compare_exchange(_ValueType* __val, _LIBCPP_END_NAMESPACE_STD -namespace { - -template -class AtomicInt { -public: - using MemoryOrder = std::__libcpp_atomic_order; - - explicit AtomicInt(IntType *b) : b(b) {} - AtomicInt(AtomicInt const&) = delete; - AtomicInt& operator=(AtomicInt const&) = delete; - - IntType load(MemoryOrder ord) { - return std::__libcpp_atomic_load(b, ord); - } - void store(IntType val, MemoryOrder ord) { - std::__libcpp_atomic_store(b, val, ord); - } - IntType exchange(IntType new_val, MemoryOrder ord) { - return std::__libcpp_atomic_exchange(b, new_val, ord); - } - bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) { - return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure); - } - -private: - IntType *b; -}; - -} // end namespace - #endif // ATOMIC_SUPPORT_H diff --git a/system/lib/libcxxabi/src/include/refstring.h b/system/lib/libcxxabi/src/include/refstring.h deleted file mode 100644 index 5905b5c9327ba..0000000000000 --- a/system/lib/libcxxabi/src/include/refstring.h +++ /dev/null @@ -1,131 +0,0 @@ -//===------------------------ __refstring ---------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of -// duplicating the file in libc++abi we should require that the libc++ sources -// are available when building libc++abi. - -#ifndef _LIBCPPABI_REFSTRING_H -#define _LIBCPPABI_REFSTRING_H - -#include <__config> -#include -#include -#include -#ifdef __APPLE__ -#include -#include -#endif -#include "atomic_support.h" - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace __refstring_imp { namespace { -typedef int count_t; - -struct _Rep_base { - std::size_t len; - std::size_t cap; - count_t count; -}; - -inline _Rep_base* rep_from_data(const char *data_) noexcept { - char *data = const_cast(data_); - return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); -} - -inline char * data_from_rep(_Rep_base *rep) noexcept { - char *data = reinterpret_cast(rep); - return data + sizeof(*rep); -} - -#if defined(__APPLE__) -inline -const char* compute_gcc_empty_string_storage() _NOEXCEPT -{ - void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); - if (handle == nullptr) - return nullptr; - void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); - if (sym == nullptr) - return nullptr; - return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); -} - -inline -const char* -get_gcc_empty_string_storage() _NOEXCEPT -{ - static const char* p = compute_gcc_empty_string_storage(); - return p; -} -#endif - -}} // namespace __refstring_imp - -using namespace __refstring_imp; - -inline -__libcpp_refstring::__libcpp_refstring(const char* msg) { - std::size_t len = strlen(msg); - _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); - rep->len = len; - rep->cap = len; - rep->count = 0; - char *data = data_from_rep(rep); - std::memcpy(data, msg, len + 1); - __imp_ = data; -} - -inline -__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT - : __imp_(s.__imp_) -{ - if (__uses_refcount()) - __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); -} - -inline -__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { - bool adjust_old_count = __uses_refcount(); - struct _Rep_base *old_rep = rep_from_data(__imp_); - __imp_ = s.__imp_; - if (__uses_refcount()) - __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); - if (adjust_old_count) - { - if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) - { - ::operator delete(old_rep); - } - } - return *this; -} - -inline -__libcpp_refstring::~__libcpp_refstring() { - if (__uses_refcount()) { - _Rep_base* rep = rep_from_data(__imp_); - if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) { - ::operator delete(rep); - } - } -} - -inline -bool __libcpp_refstring::__uses_refcount() const { -#ifdef __APPLE__ - return __imp_ != get_gcc_empty_string_storage(); -#else - return true; -#endif -} - -_LIBCPP_END_NAMESPACE_STD - -#endif //_LIBCPPABI_REFSTRING_H diff --git a/system/lib/libcxxabi/src/private_typeinfo.cpp b/system/lib/libcxxabi/src/private_typeinfo.cpp index 99c6fa021d377..8072ebb7ef2d0 100644 --- a/system/lib/libcxxabi/src/private_typeinfo.cpp +++ b/system/lib/libcxxabi/src/private_typeinfo.cpp @@ -8,11 +8,11 @@ #include "private_typeinfo.h" -// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more -// forgiving when type_info's mistakenly have hidden visibility and thus -// multiple type_infos can exist for a single type. +// The flag _LIBCXXABI_FORGIVING_DYNAMIC_CAST is used to make dynamic_cast +// more forgiving when type_info's mistakenly have hidden visibility and +// thus multiple type_infos can exist for a single type. // -// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where +// When _LIBCXXABI_FORGIVING_DYNAMIC_CAST is defined, and only in the case where // there is a detected inconsistency in the type_info hierarchy during a // dynamic_cast, then the equality operation will fall back to using strcmp // on type_info names to determine type_info equality. @@ -23,7 +23,7 @@ // algorithm and an inconsistency is still detected, dynamic_cast will call // abort with an appropriate message. // -// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a +// The current implementation of _LIBCXXABI_FORGIVING_DYNAMIC_CAST requires a // printf-like function called syslog: // // void syslog(int facility_priority, const char* format, ...); @@ -31,21 +31,22 @@ // If you want this functionality but your platform doesn't have syslog, // just implement it in terms of fprintf(stderr, ...). // -// _LIBCXX_DYNAMIC_FALLBACK is currently off by default. +// _LIBCXXABI_FORGIVING_DYNAMIC_CAST is currently off by default. // On Windows, typeids are different between DLLs and EXEs, so comparing // type_info* will work for typeids from the same compiled file but fail // for typeids from a DLL and an executable. Among other things, exceptions // are not caught by handlers since can_catch() returns false. // -// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls +// Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST does not help since can_catch() calls // is_equal() with use_strcmp=false so the string names are not compared. #include -#ifdef _LIBCXX_DYNAMIC_FALLBACK +#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST #include "abort_message.h" #include +#include #endif static inline @@ -60,6 +61,16 @@ is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp) return x == y || strcmp(x->name(), y->name()) == 0; } +static inline ptrdiff_t update_offset_to_base(const char* vtable, + ptrdiff_t offset_to_base) { +#if __has_feature(cxx_abi_relative_vtable) + // VTable components are 32 bits in the relative vtables ABI. + return *reinterpret_cast(vtable + offset_to_base); +#else + return *reinterpret_cast(vtable + offset_to_base); +#endif +} + namespace __cxxabiv1 { @@ -296,7 +307,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(adjustedPtr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } } __base_type->has_unambiguous_public_base( @@ -614,10 +625,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, // Possible future optimization: Take advantage of src2dst_offset // Get (dynamic_ptr, dynamic_type) from static_ptr +#if __has_feature(cxx_abi_relative_vtable) + // The vtable address will point to the first virtual function, which is 8 + // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component). + const int32_t* vtable = + *reinterpret_cast(static_ptr); + int32_t offset_to_derived = vtable[-2]; + const void* dynamic_ptr = static_cast(static_ptr) + offset_to_derived; + + // The typeinfo component is now a relative offset to a proxy. + int32_t offset_to_ti_proxy = vtable[-1]; + const uint8_t* ptr_to_ti_proxy = + reinterpret_cast(vtable) + offset_to_ti_proxy; + const __class_type_info* dynamic_type = + *(reinterpret_cast(ptr_to_ti_proxy)); +#else void **vtable = *static_cast(static_ptr); ptrdiff_t offset_to_derived = reinterpret_cast(vtable[-2]); const void* dynamic_ptr = static_cast(static_ptr) + offset_to_derived; const __class_type_info* dynamic_type = static_cast(vtable[-1]); +#endif // Initialize answer to nullptr. This will be changed from the search // results if a non-null answer is found. Regardless, this is what will @@ -633,22 +660,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, info.number_of_dst_type = 1; // Do the search dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false); -#ifdef _LIBCXX_DYNAMIC_FALLBACK +#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST // The following if should always be false because we should definitely // find (static_ptr, static_type), either on a public or private path if (info.path_dst_ptr_to_static_ptr == unknown) { // We get here only if there is some kind of visibility problem // in client code. - syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's " - "should have public visibility. At least one of them is hidden. %s" - ", %s.\n", static_type->name(), dynamic_type->name()); + static_assert(std::atomic::is_always_lock_free, ""); + static std::atomic error_count(0); + size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); + if ((error_count_snapshot & (error_count_snapshot-1)) == 0) + syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's " + "should have public visibility. At least one of them is hidden. %s" + ", %s.\n", static_type->name(), dynamic_type->name()); // Redo the search comparing type_info's using strcmp info = {dst_type, static_ptr, static_type, src2dst_offset, 0}; info.number_of_dst_type = 1; dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true); } -#endif // _LIBCXX_DYNAMIC_FALLBACK +#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST // Query the search. if (info.path_dst_ptr_to_static_ptr == public_path) dst_ptr = dynamic_ptr; @@ -657,22 +688,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, { // Not using giant short cut. Do the search dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false); - #ifdef _LIBCXX_DYNAMIC_FALLBACK + #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST // The following if should always be false because we should definitely // find (static_ptr, static_type), either on a public or private path if (info.path_dst_ptr_to_static_ptr == unknown && info.path_dynamic_ptr_to_static_ptr == unknown) { - syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's " - "has hidden visibility or is defined in more than one translation " - "unit. They should all have public visibility. " - "%s, %s, %s.\n", static_type->name(), dynamic_type->name(), - dst_type->name()); + static_assert(std::atomic::is_always_lock_free, ""); + static std::atomic error_count(0); + size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); + if ((error_count_snapshot & (error_count_snapshot-1)) == 0) + syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's " + "has hidden visibility or is defined in more than one translation " + "unit. They should all have public visibility. " + "%s, %s, %s.\n", static_type->name(), dynamic_type->name(), + dst_type->name()); // Redo the search comparing type_info's using strcmp info = {dst_type, static_ptr, static_type, src2dst_offset, 0}; dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true); } -#endif // _LIBCXX_DYNAMIC_FALLBACK +#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST // Query the search. switch (info.number_to_static_ptr) { @@ -1258,7 +1293,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info, if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(current_ptr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_above_dst(info, dst_ptr, static_cast(current_ptr) + offset_to_base, @@ -1278,7 +1313,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info, if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(current_ptr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_below_dst(info, static_cast(current_ptr) + offset_to_base, diff --git a/system/lib/libcxxabi/src/stdlib_exception.cpp b/system/lib/libcxxabi/src/stdlib_exception.cpp index 88d911d96c96f..b0cc431f24154 100644 --- a/system/lib/libcxxabi/src/stdlib_exception.cpp +++ b/system/lib/libcxxabi/src/stdlib_exception.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_LIBRARY #include #include diff --git a/system/lib/libcxxabi/src/stdlib_new_delete.cpp b/system/lib/libcxxabi/src/stdlib_new_delete.cpp index 0fcb486ec663a..14370c862211b 100644 --- a/system/lib/libcxxabi/src/stdlib_new_delete.cpp +++ b/system/lib/libcxxabi/src/stdlib_new_delete.cpp @@ -8,7 +8,6 @@ // This file implements the new and delete operators. //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_LIBRARY #include "__cxxabi_config.h" #include #include @@ -28,7 +27,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC if (size == 0) size = 1; void* p; - while ((p = ::malloc(size)) == 0) + while ((p = ::malloc(size)) == nullptr) { // If malloc fails and there is a new_handler, // call it to try free up memory. @@ -58,7 +57,7 @@ _LIBCXXABI_WEAK void* operator new(size_t size, const std::nothrow_t&) _NOEXCEPT { - void* p = 0; + void* p = nullptr; #ifndef _LIBCXXABI_NO_EXCEPTIONS try { @@ -84,7 +83,7 @@ _LIBCXXABI_WEAK void* operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT { - void* p = 0; + void* p = nullptr; #ifndef _LIBCXXABI_NO_EXCEPTIONS try { @@ -103,8 +102,7 @@ _LIBCXXABI_WEAK void operator delete(void* ptr) _NOEXCEPT { - if (ptr) - ::free(ptr); + ::free(ptr); } _LIBCXXABI_WEAK @@ -152,15 +150,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC size = 1; if (static_cast(alignment) < sizeof(void*)) alignment = std::align_val_t(sizeof(void*)); + + // Try allocating memory. If allocation fails and there is a new_handler, + // call it to try free up memory, and try again until it succeeds, or until + // the new_handler decides to terminate. + // + // If allocation fails and there is no new_handler, we throw bad_alloc + // (or return nullptr if exceptions are disabled). void* p; -#if defined(_LIBCPP_WIN32API) - while ((p = _aligned_malloc(size, static_cast(alignment))) == nullptr) -#else - while (::posix_memalign(&p, static_cast(alignment), size) != 0) -#endif + while ((p = std::__libcpp_aligned_alloc(static_cast(alignment), size)) == nullptr) { - // If posix_memalign fails and there is a new_handler, - // call it to try free up memory. std::new_handler nh = std::get_new_handler(); if (nh) nh(); @@ -168,7 +167,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC #ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_alloc(); #else - p = nullptr; // posix_memalign doesn't initialize 'p' on failure break; #endif } @@ -180,7 +178,7 @@ _LIBCXXABI_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT { - void* p = 0; + void* p = nullptr; #ifndef _LIBCXXABI_NO_EXCEPTIONS try { @@ -206,7 +204,7 @@ _LIBCXXABI_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT { - void* p = 0; + void* p = nullptr; #ifndef _LIBCXXABI_NO_EXCEPTIONS try { @@ -225,12 +223,7 @@ _LIBCXXABI_WEAK void operator delete(void* ptr, std::align_val_t) _NOEXCEPT { - if (ptr) -#if defined(_LIBCPP_WIN32API) - ::_aligned_free(ptr); -#else - ::free(ptr); -#endif + std::__libcpp_aligned_free(ptr); } _LIBCXXABI_WEAK diff --git a/system/lib/libcxxabi/src/stdlib_stdexcept.cpp b/system/lib/libcxxabi/src/stdlib_stdexcept.cpp index 2cff8ee2f083a..4a464e48893de 100644 --- a/system/lib/libcxxabi/src/stdlib_stdexcept.cpp +++ b/system/lib/libcxxabi/src/stdlib_stdexcept.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "include/refstring.h" +#include "../../libcxx/src/include/refstring.h" #include "stdexcept" #include "new" #include diff --git a/tools/system_libs.py b/tools/system_libs.py index 9232c083b33ed..157bc9beb3b44 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -906,9 +906,7 @@ class libcxxabi(NoExceptLibrary, MTLibrary): cflags = [ '-Oz', '-D_LIBCXXABI_BUILDING_LIBRARY', - # Remove this once we update to include this llvm - # revision: https://reviews.llvm.org/D64961 - '-D_LIBCXXABI_GUARD_ABI_ARM', + '-DLIBCXXABI_NON_DEMANGLING_TERMINATE', ] def get_cflags(self):