diff options
author | Dan Albert <danalbert@google.com> | 2015-03-04 17:08:25 -0800 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2015-03-10 17:59:36 -0700 |
commit | 0a1ce9cae10bf7e2e6640e2a8f1efe7062c47292 (patch) | |
tree | cd4a0cb49f6717bc6659095706a376ad3a00436c /src | |
parent | da0677d3172e235acc6a35a5d4fcf2b4dca86fea (diff) | |
download | libcxxabi-0a1ce9cae10bf7e2e6640e2a8f1efe7062c47292.tar.gz |
Merge to upstream r231075.
Change-Id: If60a5707fa4299ce03b7bfd605b360486bcd9d2f
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 68 | ||||
-rw-r--r-- | src/Unwind/AddressSpace.hpp | 113 | ||||
-rw-r--r-- | src/Unwind/CMakeLists.txt | 62 | ||||
-rw-r--r-- | src/Unwind/CompactUnwinder.hpp | 2 | ||||
-rw-r--r-- | src/Unwind/DwarfInstructions.hpp | 14 | ||||
-rw-r--r-- | src/Unwind/DwarfParser.hpp | 2 | ||||
-rw-r--r-- | src/Unwind/EHHeaderParser.hpp | 161 | ||||
-rw-r--r-- | src/Unwind/Registers.hpp | 25 | ||||
-rw-r--r-- | src/Unwind/Unwind-EHABI.cpp | 292 | ||||
-rw-r--r-- | src/Unwind/Unwind-EHABI.h | 51 | ||||
-rw-r--r-- | src/Unwind/UnwindCursor.hpp | 106 | ||||
-rw-r--r-- | src/Unwind/UnwindLevel1-gcc-ext.c | 80 | ||||
-rw-r--r-- | src/Unwind/UnwindLevel1.c | 264 | ||||
-rw-r--r-- | src/Unwind/UnwindRegistersRestore.S | 35 | ||||
-rw-r--r-- | src/Unwind/UnwindRegistersSave.S | 42 | ||||
-rw-r--r-- | src/Unwind/Unwind_AppleExtras.cpp | 6 | ||||
-rw-r--r-- | src/Unwind/assembly.h | 4 | ||||
-rw-r--r-- | src/Unwind/config.h | 26 | ||||
-rw-r--r-- | src/Unwind/libunwind.cpp | 63 | ||||
-rw-r--r-- | src/abort_message.cpp | 10 | ||||
-rw-r--r-- | src/cxa_exception.cpp | 14 | ||||
-rw-r--r-- | src/cxa_exception.hpp | 26 | ||||
-rw-r--r-- | src/cxa_guard.cpp | 2 | ||||
-rw-r--r-- | src/cxa_personality.cpp | 101 | ||||
-rw-r--r-- | src/private_typeinfo.cpp | 8 |
25 files changed, 980 insertions, 597 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c9e38b..fda2d10 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,18 +34,6 @@ if (MSVC_IDE OR XCODE) endif() endif() -if (LIBCXXABI_ENABLE_SHARED) - add_library(cxxabi SHARED - ${LIBCXXABI_SOURCES} - ${LIBCXXABI_HEADERS} - ) -else() - add_library(cxxabi STATIC - ${LIBCXXABI_SOURCES} - ${LIBCXXABI_HEADERS} - ) -endif() - include_directories("${LIBCXXABI_LIBCXX_INCLUDES}") if (LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) @@ -65,22 +53,23 @@ else() append_if(libraries LIBCXXABI_HAS_GCC_EH_LIB gcc_eh) endif() -target_link_libraries(cxxabi ${libraries}) - # Setup flags. append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_FPIC_FLAG -fPIC) append_if(LIBCXXABI_LINK_FLAGS LIBCXXABI_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs) +set(LIBCXXABI_SHARED_LINK_FLAGS) + if ( APPLE ) if ( CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.6" ) list(APPEND LIBCXXABI_COMPILE_FLAGS "-U__STRICT_ANSI__") - list(APPEND LIBCXXABI_LINK_FLAGS + list(APPEND LIBCXXABI_SHARED_LINK_FLAGS "-compatibility_version 1" "-current_version 1" - "-install_name /usr/lib/libc++abi.1.dylib" - "/usr/lib/libSystem.B.dylib") - else() + "-install_name /usr/lib/libc++abi.1.dylib") list(APPEND LIBCXXABI_LINK_FLAGS + "/usr/lib/libSystem.B.dylib") + else() + list(APPEND LIBCXXABI_SHARED_LINK_FLAGS "-compatibility_version 1" "-install_name /usr/lib/libc++abi.1.dylib") endif() @@ -88,17 +77,48 @@ endif() string(REPLACE ";" " " LIBCXXABI_COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}") string(REPLACE ";" " " LIBCXXABI_LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}") +string(REPLACE ";" " " LIBCXXABI_SHARED_LINK_FLAGS "${LIBCXXABI_SHARED_LINK_FLAGS}") + +# Add a object library that contains the compiled source files. +add_library(cxxabi_objects OBJECT ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS}) -set_target_properties(cxxabi +set_target_properties(cxxabi_objects PROPERTIES COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}" - LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}" - OUTPUT_NAME "c++abi" - VERSION "1.0" - SOVERSION "1" ) -install(TARGETS cxxabi +set(LIBCXXABI_TARGETS) + +# Build the shared library. +if (LIBCXXABI_ENABLE_SHARED) + add_library(cxxabi_shared SHARED $<TARGET_OBJECTS:cxxabi_objects>) + target_link_libraries(cxxabi_shared ${libraries}) + set_target_properties(cxxabi_shared + PROPERTIES + LINK_FLAGS "${LIBCXXABI_LINK_FLAGS} ${LIBCXXABI_SHARED_LINK_FLAGS}" + OUTPUT_NAME "c++abi" + VERSION "1.0" + SOVERSION "1" + ) + list(APPEND LIBCXXABI_TARGETS "cxxabi_shared") +endif() + +# Build the static library. +if (LIBCXXABI_ENABLE_STATIC) + add_library(cxxabi_static STATIC $<TARGET_OBJECTS:cxxabi_objects>) + target_link_libraries(cxxabi_static ${libraries}) + set_target_properties(cxxabi_static + PROPERTIES + LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}" + OUTPUT_NAME "c++abi" + ) + list(APPEND LIBCXXABI_TARGETS "cxxabi_static") +endif() + +# Add a meta-target for both libraries. +add_custom_target(cxxabi DEPENDS ${LIBCXXABI_TARGETS}) + +install(TARGETS ${LIBCXXABI_TARGETS} LIBRARY DESTINATION lib${LIBCXXABI_LIBDIR_SUFFIX} ARCHIVE DESTINATION lib${LIBCXXABI_LIBDIR_SUFFIX} ) diff --git a/src/Unwind/AddressSpace.hpp b/src/Unwind/AddressSpace.hpp index 4e94afc..abcac41 100644 --- a/src/Unwind/AddressSpace.hpp +++ b/src/Unwind/AddressSpace.hpp @@ -18,11 +18,11 @@ #include <stdlib.h> #include <string.h> -#if !_LIBUNWIND_IS_BAREMETAL +#ifndef _LIBUNWIND_IS_BAREMETAL #include <dlfcn.h> #endif -#if __APPLE__ +#ifdef __APPLE__ #include <mach-o/getsect.h> namespace libunwind { bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde); @@ -35,7 +35,7 @@ namespace libunwind { #include "Registers.hpp" #if LIBCXXABI_ARM_EHABI -#if __linux__ +#ifdef __linux__ typedef long unsigned int *_Unwind_Ptr; extern "C" _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr addr, int *len); @@ -43,9 +43,9 @@ extern "C" _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr addr, int *len); // Emulate the BSD dl_unwind_find_exidx API when on a GNU libdl system. #define dl_unwind_find_exidx __gnu_Unwind_Find_exidx -#elif !_LIBUNWIND_IS_BAREMETAL +#elif !defined(_LIBUNWIND_IS_BAREMETAL) #include <link.h> -#else // _LIBUNWIND_IS_BAREMETAL +#else // !defined(_LIBUNWIND_IS_BAREMETAL) // When statically linked on bare-metal, the symbols for the EH table are looked // up without going through the dynamic loader. struct EHTEntry { @@ -54,10 +54,16 @@ struct EHTEntry { }; extern EHTEntry __exidx_start; extern EHTEntry __exidx_end; -#endif // !_LIBUNWIND_IS_BAREMETAL - +#endif // !defined(_LIBUNWIND_IS_BAREMETAL) #endif // LIBCXXABI_ARM_EHABI +#if defined(__linux__) +#if _LIBUNWIND_SUPPORT_DWARF_UNWIND && _LIBUNWIND_SUPPORT_DWARF_INDEX +#include <link.h> +#include "EHHeaderParser.hpp" +#endif +#endif + namespace libunwind { /// Used by findUnwindSections() to return info about needed sections. @@ -91,7 +97,7 @@ struct UnwindInfoSections { /// making local unwinds fast. class __attribute__((visibility("hidden"))) LocalAddressSpace { public: -#if __LP64__ +#ifdef __LP64__ typedef uint64_t pint_t; typedef int64_t sint_t; #else @@ -132,7 +138,8 @@ public: static uint64_t getULEB128(pint_t &addr, pint_t end); static int64_t getSLEB128(pint_t &addr, pint_t end); - pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding); + pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, + pint_t datarelBase = 0); bool findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset); bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); @@ -142,7 +149,7 @@ public: }; inline uintptr_t LocalAddressSpace::getP(pint_t addr) { -#if __LP64__ +#ifdef __LP64__ return get64(addr); #else return get32(addr); @@ -195,9 +202,9 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { return result; } -inline LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t &addr, - pint_t end, - uint8_t encoding) { +inline LocalAddressSpace::pint_t +LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, + pint_t datarelBase) { pint_t startAddr = addr; const uint8_t *p = (uint8_t *)addr; pint_t result; @@ -263,7 +270,12 @@ inline LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t &addr, _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported"); break; case DW_EH_PE_datarel: - _LIBUNWIND_ABORT("DW_EH_PE_datarel pointer encoding not supported"); + // DW_EH_PE_datarel is only valid in a few places, so the parameter has a + // default value of 0, and we abort in the event that someone calls this + // function with a datarelBase of 0 and DW_EH_PE_datarel encoding. + if (datarelBase == 0) + _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0"); + result += datarelBase; break; case DW_EH_PE_funcrel: _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported"); @@ -282,7 +294,7 @@ inline LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t &addr, return result; } -#if __APPLE__ +#ifdef __APPLE__ struct dyld_unwind_sections { const struct mach_header* mh; @@ -326,7 +338,7 @@ inline LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t &addr, inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, UnwindInfoSections &info) { -#if __APPLE__ +#ifdef __APPLE__ dyld_unwind_sections dyldInfo; if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { info.dso_base = (uintptr_t)dyldInfo.mh; @@ -339,7 +351,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, return true; } #elif LIBCXXABI_ARM_EHABI - #if _LIBUNWIND_IS_BAREMETAL + #ifdef _LIBUNWIND_IS_BAREMETAL // Bare metal is statically linked, so no need to ask the dynamic loader info.arm_section = (uintptr_t)(&__exidx_start); info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); @@ -353,6 +365,64 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, info.arm_section, info.arm_section_length); if (info.arm_section && info.arm_section_length) return true; +#elif _LIBUNWIND_SUPPORT_DWARF_UNWIND +#if _LIBUNWIND_SUPPORT_DWARF_INDEX + struct dl_iterate_cb_data { + LocalAddressSpace *addressSpace; + UnwindInfoSections *sects; + uintptr_t targetAddr; + }; + + dl_iterate_cb_data cb_data = {this, &info, targetAddr}; + int found = dl_iterate_phdr( + [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { + auto cbdata = static_cast<dl_iterate_cb_data *>(data); + size_t object_length; + bool found_obj = false; + bool found_hdr = false; + + assert(cbdata); + assert(cbdata->sects); + + if (cbdata->targetAddr < pinfo->dlpi_addr) { + return false; + } + + for (ElfW(Half) i = 0; i < pinfo->dlpi_phnum; i++) { + const ElfW(Phdr) *phdr = &pinfo->dlpi_phdr[i]; + if (phdr->p_type == PT_LOAD) { + uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; + uintptr_t end = begin + phdr->p_memsz; + if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { + cbdata->sects->dso_base = begin; + object_length = phdr->p_memsz; + found_obj = true; + } + } else if (phdr->p_type == PT_GNU_EH_FRAME) { + EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; + uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr; + cbdata->sects->dwarf_index_section = eh_frame_hdr_start; + cbdata->sects->dwarf_index_section_length = phdr->p_memsz; + EHHeaderParser<LocalAddressSpace>::decodeEHHdr( + *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, + hdrInfo); + cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; + found_hdr = true; + } + } + + if (found_obj && found_hdr) { + cbdata->sects->dwarf_section_length = object_length; + return true; + } else { + return false; + } + }, + &cb_data); + return static_cast<bool>(found); +#else +#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." +#endif #endif return false; @@ -360,7 +430,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { -#if __APPLE__ +#ifdef __APPLE__ return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); #else // TO DO: if OS has way to dynamically register FDEs, check that. @@ -373,7 +443,7 @@ inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset) { -#if !_LIBUNWIND_IS_BAREMETAL +#ifndef _LIBUNWIND_IS_BAREMETAL Dl_info dyldInfo; if (dladdr((void *)addr, &dyldInfo)) { if (dyldInfo.dli_sname != NULL) { @@ -388,7 +458,7 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, -#if UNW_REMOTE +#ifdef UNW_REMOTE /// OtherAddressSpace is used as a template parameter to UnwindCursor when /// unwinding a thread in the another process. The other process can be a @@ -408,7 +478,8 @@ public: pint_t getP(pint_t addr); uint64_t getULEB128(pint_t &addr, pint_t end); int64_t getSLEB128(pint_t &addr, pint_t end); - pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding); + pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, + pint_t datarelBase = 0); bool findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset); bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); diff --git a/src/Unwind/CMakeLists.txt b/src/Unwind/CMakeLists.txt index 598a081..2aa45dc 100644 --- a/src/Unwind/CMakeLists.txt +++ b/src/Unwind/CMakeLists.txt @@ -1,20 +1,24 @@ # Get sources -set(LIBUNWIND_SOURCES - libunwind.cpp - Unwind-EHABI.cpp - UnwindLevel1.c - UnwindLevel1-gcc-ext.c - Unwind-sjlj.c -) -append_if(LIBUNWIND_SOURCES APPLE Unwind_AppleExtras.cpp) +set(LIBUNWIND_CXX_SOURCES + libunwind.cpp + Unwind-EHABI.cpp) +append_if(LIBUNWIND_CXX_SOURCES APPLE Unwind_AppleExtras.cpp) -set(LIBUNWIND_ASM_SOURCES - UnwindRegistersRestore.S - UnwindRegistersSave.S -) +set(LIBUNWIND_C_SOURCES + UnwindLevel1.c + UnwindLevel1-gcc-ext.c + Unwind-sjlj.c) +set_source_files_properties(${LIBUNWIND_C_SOURCES} + PROPERTIES + COMPILE_FLAGS "-std=c99") -set_source_files_properties(${LIBUNWIND_ASM_SOURCES} PROPERTIES LANGUAGE C) +set(LIBUNWIND_ASM_SOURCES + UnwindRegistersRestore.S + UnwindRegistersSave.S) +set_source_files_properties(${LIBUNWIND_ASM_SOURCES} + PROPERTIES + LANGUAGE C) set(LIBUNWIND_HEADERS AddressSpace.hpp @@ -40,18 +44,15 @@ if (MSVC_IDE) source_group("Header Files" FILES ${LIBUNWIND_HEADERS}) endif() +set(LIBUNWIND_SOURCES + ${LIBUNWIND_CXX_SOURCES} + ${LIBUNWIND_C_SOURCES} + ${LIBUNWIND_ASM_SOURCES}) + if (LIBUNWIND_ENABLE_SHARED) - add_library(unwind SHARED - ${LIBUNWIND_SOURCES} - ${LIBUNWIND_ASM_SOURCES} - ${LIBUNWIND_HEADERS} - ) + add_library(unwind SHARED ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS}) else() - add_library(unwind STATIC - ${LIBUNWIND_SOURCES} - ${LIBUNWIND_ASM_SOURCES} - ${LIBUNWIND_HEADERS} - ) + add_library(unwind STATIC ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS}) endif() include_directories("${LIBCXXABI_LIBCXX_INCLUDES}") @@ -68,6 +69,18 @@ target_link_libraries(unwind ${libraries}) append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_FPIC_FLAG -fPIC) append_if(LIBCXXABI_LINK_FLAGS LIBCXXABI_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs) +set(LIBUNWIND_COMPILE_FLAGS) +append_if(LIBUNWIND_COMPILE_FLAGS LIBCXXABI_HAS_NO_RTTI_FLAG -fno-rtti) +if ( LIBCXXABI_HAS_NO_EXCEPTIONS_FLAG AND LIBCXXABI_HAS_FUNWIND_TABLES ) + list(APPEND LIBUNWIND_COMPILE_FLAGS -fno-exceptions) + list(APPEND LIBUNWIND_COMPILE_FLAGS -funwind-tables) +elseif( LIBUNWIND_ENABLE_SHARED ) + message(FATAL_ERROR "Compiler doesn't support generation of unwind tables " + "if exception support is disabled. Building libunwind " + "DSO with runtime dependency on libcxxabi is not " + "supported.") +endif() + set(LIBCXXABI_UNWINDER_NAME "unwind") if ( APPLE ) @@ -86,11 +99,12 @@ if ( APPLE ) endif() string(REPLACE ";" " " LIBCXXABI_COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}") +string(REPLACE ";" " " LIBUNWIND_COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}") string(REPLACE ";" " " LIBCXXABI_LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}") set_target_properties(unwind PROPERTIES - COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}" + COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS} ${LIBUNWIND_COMPILE_FLAGS}" LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}" OUTPUT_NAME "${LIBCXXABI_UNWINDER_NAME}" VERSION "1.0" diff --git a/src/Unwind/CompactUnwinder.hpp b/src/Unwind/CompactUnwinder.hpp index 0dc187f..cd9ce3e 100644 --- a/src/Unwind/CompactUnwinder.hpp +++ b/src/Unwind/CompactUnwinder.hpp @@ -688,6 +688,6 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( } -}; // namespace libunwind +} // namespace libunwind #endif // __COMPACT_UNWINDER_HPP__ diff --git a/src/Unwind/DwarfInstructions.hpp b/src/Unwind/DwarfInstructions.hpp index 4fbd53c..99737e0 100644 --- a/src/Unwind/DwarfInstructions.hpp +++ b/src/Unwind/DwarfInstructions.hpp @@ -605,7 +605,7 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: - value = opcode - DW_OP_lit0; + value = static_cast<pint_t>(opcode - DW_OP_lit0); *(++sp) = value; if (log) fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value); @@ -643,14 +643,14 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: - reg = opcode - DW_OP_reg0; + reg = static_cast<uint32_t>(opcode - DW_OP_reg0); *(++sp) = registers.getRegister((int)reg); if (log) fprintf(stderr, "push reg %d\n", reg); break; case DW_OP_regx: - reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd); + reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd)); *(++sp) = registers.getRegister((int)reg); if (log) fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); @@ -688,18 +688,18 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: - reg = opcode - DW_OP_breg0; + reg = static_cast<uint32_t>(opcode - DW_OP_breg0); svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); - svalue += registers.getRegister((int)reg); + svalue += static_cast<sint_t>(registers.getRegister((int)reg)); *(++sp) = (pint_t)(svalue); if (log) fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); break; case DW_OP_bregx: - reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd); + reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd)); svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); - svalue += registers.getRegister((int)reg); + svalue += static_cast<sint_t>(registers.getRegister((int)reg)); *(++sp) = (pint_t)(svalue); if (log) fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); diff --git a/src/Unwind/DwarfParser.hpp b/src/Unwind/DwarfParser.hpp index a9de345..f6ef738 100644 --- a/src/Unwind/DwarfParser.hpp +++ b/src/Unwind/DwarfParser.hpp @@ -347,7 +347,7 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, const CIE_Info &cieInfo, pint_t upToPC, PrologInfo *results) { // clear results - bzero(results, sizeof(PrologInfo)); + memset(results, '\0', sizeof(PrologInfo)); PrologInfoStackEntry *rememberStack = NULL; // parse CIE then FDE instructions diff --git a/src/Unwind/EHHeaderParser.hpp b/src/Unwind/EHHeaderParser.hpp new file mode 100644 index 0000000..7945c7b --- /dev/null +++ b/src/Unwind/EHHeaderParser.hpp @@ -0,0 +1,161 @@ +//===------------------------- EHHeaderParser.hpp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Parses ELF .eh_frame_hdr sections. +// +//===----------------------------------------------------------------------===// + +#ifndef __EHHEADERPARSER_HPP__ +#define __EHHEADERPARSER_HPP__ + +#include "libunwind.h" + +#include "AddressSpace.hpp" +#include "DwarfParser.hpp" + +namespace libunwind { + +/// \brief EHHeaderParser does basic parsing of an ELF .eh_frame_hdr section. +/// +/// See DWARF spec for details: +/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html +/// +template <typename A> class EHHeaderParser { +public: + typedef typename A::pint_t pint_t; + + /// Information encoded in the EH frame header. + struct EHHeaderInfo { + pint_t eh_frame_ptr; + size_t fde_count; + pint_t table; + uint8_t table_enc; + }; + + static void decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, + EHHeaderInfo &ehHdrInfo); + static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, + uint32_t sectionLength, + typename CFI_Parser<A>::FDE_Info *fdeInfo, + typename CFI_Parser<A>::CIE_Info *cieInfo); + +private: + static bool decodeTableEntry(A &addressSpace, pint_t &tableEntry, + pint_t ehHdrStart, pint_t ehHdrEnd, + uint8_t tableEnc, + typename CFI_Parser<A>::FDE_Info *fdeInfo, + typename CFI_Parser<A>::CIE_Info *cieInfo); + static size_t getTableEntrySize(uint8_t tableEnc); +}; + +template <typename A> +void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, + pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) { + pint_t p = ehHdrStart; + uint8_t version = addressSpace.get8(p++); + if (version != 1) + _LIBUNWIND_ABORT("Unsupported .eh_frame_hdr version"); + + uint8_t eh_frame_ptr_enc = addressSpace.get8(p++); + uint8_t fde_count_enc = addressSpace.get8(p++); + ehHdrInfo.table_enc = addressSpace.get8(p++); + + ehHdrInfo.eh_frame_ptr = + addressSpace.getEncodedP(p, ehHdrEnd, eh_frame_ptr_enc, ehHdrStart); + ehHdrInfo.fde_count = + addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart); + ehHdrInfo.table = p; +} + +template <typename A> +bool EHHeaderParser<A>::decodeTableEntry( + A &addressSpace, pint_t &tableEntry, pint_t ehHdrStart, pint_t ehHdrEnd, + uint8_t tableEnc, typename CFI_Parser<A>::FDE_Info *fdeInfo, + typename CFI_Parser<A>::CIE_Info *cieInfo) { + // Have to decode the whole FDE for the PC range anyway, so just throw away + // the PC start. + addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart); + pint_t fde = + addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart); + const char *message = + CFI_Parser<A>::decodeFDE(addressSpace, fde, fdeInfo, cieInfo); + if (message != NULL) { + _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s\n", + message); + return false; + } + + return true; +} + +template <typename A> +bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, + uint32_t sectionLength, + typename CFI_Parser<A>::FDE_Info *fdeInfo, + typename CFI_Parser<A>::CIE_Info *cieInfo) { + pint_t ehHdrEnd = ehHdrStart + sectionLength; + + EHHeaderParser<A>::EHHeaderInfo hdrInfo; + EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, hdrInfo); + + size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc); + pint_t tableEntry; + + size_t low = 0; + for (size_t len = hdrInfo.fde_count; len > 1;) { + size_t mid = low + (len / 2); + tableEntry = hdrInfo.table + mid * tableEntrySize; + pint_t start = addressSpace.getEncodedP(tableEntry, ehHdrEnd, + hdrInfo.table_enc, ehHdrStart); + + if (start == pc) { + low = mid; + break; + } else if (start < pc) { + low = mid; + len -= (len / 2); + } else { + len /= 2; + } + } + + tableEntry = hdrInfo.table + low * tableEntrySize; + if (decodeTableEntry(addressSpace, tableEntry, ehHdrStart, ehHdrEnd, + hdrInfo.table_enc, fdeInfo, cieInfo)) { + if (pc >= fdeInfo->pcStart && pc < fdeInfo->pcEnd) + return true; + } + + return false; +} + +template <typename A> +size_t EHHeaderParser<A>::getTableEntrySize(uint8_t tableEnc) { + switch (tableEnc & 0x0f) { + case DW_EH_PE_sdata2: + case DW_EH_PE_udata2: + return 4; + case DW_EH_PE_sdata4: + case DW_EH_PE_udata4: + return 8; + case DW_EH_PE_sdata8: + case DW_EH_PE_udata8: + return 16; + case DW_EH_PE_sleb128: + case DW_EH_PE_uleb128: + _LIBUNWIND_ABORT("Can't binary search on variable length encoded data."); + case DW_EH_PE_omit: + return 0; + default: + _LIBUNWIND_ABORT("Unknown DWARF encoding for search table."); + } +} + +} + +#endif diff --git a/src/Unwind/Registers.hpp b/src/Unwind/Registers.hpp index 8c1acfc..4a441b7 100644 --- a/src/Unwind/Registers.hpp +++ b/src/Unwind/Registers.hpp @@ -89,7 +89,7 @@ private: inline Registers_x86::Registers_x86(const void *registers) { static_assert(sizeof(Registers_x86) < sizeof(unw_context_t), "x86 registers do not fit into unw_context_t"); - _registers = *((GPRs *)registers); + memcpy(&_registers, registers, sizeof(_registers)); } inline Registers_x86::Registers_x86() { @@ -281,7 +281,7 @@ private: inline Registers_x86_64::Registers_x86_64(const void *registers) { static_assert(sizeof(Registers_x86_64) < sizeof(unw_context_t), "x86_64 registers do not fit into unw_context_t"); - _registers = *((GPRs *)registers); + memcpy(&_registers, registers, sizeof(_registers)); } inline Registers_x86_64::Registers_x86_64() { @@ -546,9 +546,19 @@ private: inline Registers_ppc::Registers_ppc(const void *registers) { static_assert(sizeof(Registers_ppc) < sizeof(unw_context_t), "ppc registers do not fit into unw_context_t"); - _registers = *((ppc_thread_state_t *)registers); - _floatRegisters = *((ppc_float_state_t *)((char *)registers + 160)); - memcpy(_vectorRegisters, ((char *)registers + 424), sizeof(_vectorRegisters)); + memcpy(&_registers, static_cast<const uint8_t *>(registers), + sizeof(_registers)); + static_assert(sizeof(ppc_thread_state_t) == 160, + "expected float register offset to be 160"); + memcpy(&_floatRegisters, + static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t), + sizeof(_floatRegisters)); + static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424, + "expected vector register offset to be 424 bytes"); + memcpy(_vectorRegisters, + static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) + + sizeof(ppc_float_state_t), + sizeof(_vectorRegisters)); } inline Registers_ppc::Registers_ppc() { @@ -1065,7 +1075,10 @@ inline Registers_arm64::Registers_arm64(const void *registers) { static_assert(sizeof(Registers_arm64) < sizeof(unw_context_t), "arm64 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); - memcpy(_vectorHalfRegisters, (((char *)registers) + 0x110), + static_assert(sizeof(GPRs) == 0x110, + "expected VFP registers to be at offset 272"); + memcpy(_vectorHalfRegisters, + static_cast<const uint8_t *>(registers) + sizeof(GPRs), sizeof(_vectorHalfRegisters)); } diff --git a/src/Unwind/Unwind-EHABI.cpp b/src/Unwind/Unwind-EHABI.cpp index 55bef5a..7ebba67 100644 --- a/src/Unwind/Unwind-EHABI.cpp +++ b/src/Unwind/Unwind-EHABI.cpp @@ -10,7 +10,9 @@ // //===----------------------------------------------------------------------===// -#include <unwind.h> +#include "Unwind-EHABI.h" + +#if LIBCXXABI_ARM_EHABI #include <stdbool.h> #include <stdint.h> @@ -18,13 +20,14 @@ #include <stdlib.h> #include <string.h> +#include <type_traits> + #include "config.h" #include "libunwind.h" #include "libunwind_ext.h" #include "unwind.h" #include "../private_typeinfo.h" -#if LIBCXXABI_ARM_EHABI namespace { // Strange order: take words in order, but inside word, take from most to least @@ -44,28 +47,24 @@ const char* getNextNibble(const char* data, uint32_t* out) { return data + 2; } -static inline uint32_t signExtendPrel31(uint32_t data) { - return data | ((data & 0x40000000u) << 1); -} - struct Descriptor { - // See # 9.2 - typedef enum { - SU16 = 0, // Short descriptor, 16-bit entries - LU16 = 1, // Long descriptor, 16-bit entries - LU32 = 3, // Long descriptor, 32-bit entries - RESERVED0 = 4, RESERVED1 = 5, RESERVED2 = 6, RESERVED3 = 7, - RESERVED4 = 8, RESERVED5 = 9, RESERVED6 = 10, RESERVED7 = 11, - RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 15 - } Format; - - // See # 9.2 - typedef enum { - CLEANUP = 0x0, - FUNC = 0x1, - CATCH = 0x2, - INVALID = 0x4 - } Kind; + // See # 9.2 + typedef enum { + SU16 = 0, // Short descriptor, 16-bit entries + LU16 = 1, // Long descriptor, 16-bit entries + LU32 = 3, // Long descriptor, 32-bit entries + RESERVED0 = 4, RESERVED1 = 5, RESERVED2 = 6, RESERVED3 = 7, + RESERVED4 = 8, RESERVED5 = 9, RESERVED6 = 10, RESERVED7 = 11, + RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 15 + } Format; + + // See # 9.2 + typedef enum { + CLEANUP = 0x0, + FUNC = 0x1, + CATCH = 0x2, + INVALID = 0x4 + } Kind; }; _Unwind_Reason_Code ProcessDescriptors( @@ -135,7 +134,7 @@ _Unwind_Reason_Code ProcessDescriptors( landing_pad = signExtendPrel31(landing_pad & ~0x80000000); if (landing_pad == 0xffffffff) { return _URC_HANDLER_FOUND; - } else if (landing_pad == 0xfffffffe ) { + } else if (landing_pad == 0xfffffffe) { return _URC_FAILURE; } else { /* @@ -154,7 +153,7 @@ _Unwind_Reason_Code ProcessDescriptors( } default: _LIBUNWIND_ABORT("Invalid descriptor kind found."); - }; + } getNextWord(descriptor, &descriptorWord); } @@ -162,10 +161,9 @@ _Unwind_Reason_Code ProcessDescriptors( return _URC_CONTINUE_UNWIND; } -_Unwind_Reason_Code unwindOneFrame( - _Unwind_State state, - _Unwind_Control_Block* ucbp, - struct _Unwind_Context* context) { +static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state, + _Unwind_Control_Block* ucbp, + struct _Unwind_Context* context) { // Read the compact model EHT entry's header # 6.3 const uint32_t* unwindingData = ucbp->pr_cache.ehtp; assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry"); @@ -206,28 +204,6 @@ uint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) { } // end anonymous namespace -uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index) { - uintptr_t value = 0; - _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); - return value; -} - -void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t - new_value) { - _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, - _UVRSD_UINT32, &new_value); -} - -uintptr_t _Unwind_GetIP(struct _Unwind_Context* context) { - // remove the thumb-bit before returning - return (_Unwind_GetGR(context, 15) & (~(uintptr_t)0x1)); -} - -void _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value) { - uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); - _Unwind_SetGR(context, 15, new_value | thumb_bit); -} - /** * Decodes an EHT entry. * @@ -238,44 +214,27 @@ void _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value) { */ extern "C" const uint32_t* decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { - if ((*data & 0x80000000) == 0) { - // 6.2: Generic Model - // EHT entry is a prel31 pointing to the PR, followed by data understood only - // by the personality routine. Since EHABI doesn't guarantee the location or - // availability of the unwind opcodes in the generic model, we have to check - // for them on a case-by-case basis: - _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, - uint64_t exceptionClass, - _Unwind_Exception* unwind_exception, - _Unwind_Context* context); - void *PR = (void*)signExtendPrel31(*data); - if (PR == (void*)&__gxx_personality_v0) { - *off = 1; // First byte is size data. - *len = (((data[1] >> 24) & 0xff) + 1) * 4; - } else + assert((*data & 0x80000000) != 0 && + "decode_eht_entry() does not support user-defined personality"); + + // 6.3: ARM Compact Model + // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded + // by format: + Descriptor::Format format = + static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24); + switch (format) { + case Descriptor::SU16: + *len = 4; + *off = 1; + break; + case Descriptor::LU16: + case Descriptor::LU32: + *len = 4 + 4 * ((*data & 0x00ff0000) >> 16); + *off = 2; + break; + default: return nullptr; - data++; // Skip the first word, which is the prel31 offset. - } else { - // 6.3: ARM Compact Model - // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded - // by format: - Descriptor::Format format = - static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24); - switch (format) { - case Descriptor::SU16: - *len = 4; - *off = 1; - break; - case Descriptor::LU16: - case Descriptor::LU32: - *len = 4 + 4 * ((*data & 0x00ff0000) >> 16); - *off = 2; - break; - default: - return nullptr; - } } - return data; } @@ -367,7 +326,8 @@ _Unwind_Reason_Code _Unwind_VRS_Interpret( case 0xb3: { uint8_t v = getByte(data, offset++); _Unwind_VRS_Pop(context, _UVRSC_VFP, - RegisterRange(v >> 4, v & 0x0f), _UVRSD_VFPX); + RegisterRange(static_cast<uint8_t>(v >> 4), + v & 0x0f), _UVRSD_VFPX); break; } case 0xb4: @@ -395,7 +355,7 @@ _Unwind_Reason_Code _Unwind_VRS_Interpret( break; case 0xc6: { uint8_t v = getByte(data, offset++); - uint8_t start = v >> 4; + uint8_t start = static_cast<uint8_t>(v >> 4); uint8_t count_minus_one = v & 0xf; if (start + count_minus_one >= 16) return _URC_FAILURE; @@ -414,7 +374,8 @@ _Unwind_Reason_Code _Unwind_VRS_Interpret( case 0xc8: case 0xc9: { uint8_t v = getByte(data, offset++); - uint8_t start = ((byte == 0xc8) ? 16 : 0) + (v >> 4); + uint8_t start = + static_cast<uint8_t>(((byte == 0xc8) ? 16 : 0) + (v >> 4)); uint8_t count_minus_one = v & 0xf; if (start + count_minus_one >= 32) return _URC_FAILURE; @@ -488,13 +449,13 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { int stepResult = unw_step(&cursor1); if (stepResult == 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK\n", - exception_object); + "bottom => _URC_END_OF_STACK\n", + static_cast<void *>(exception_object)); return _URC_END_OF_STACK; } else if (stepResult < 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => " - "_URC_FATAL_PHASE1_ERROR\n", - exception_object); + "_URC_FATAL_PHASE1_ERROR\n", + static_cast<void *>(exception_object)); return _URC_FATAL_PHASE1_ERROR; } @@ -502,26 +463,28 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { unw_proc_info_t frameInfo; if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR\n", - exception_object); + "failed => _URC_FATAL_PHASE1_ERROR\n", + static_cast<void *>(exception_object)); return _URC_FATAL_PHASE1_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { - char functionName[512]; + char functionBuf[512]; + const char *functionName = functionBuf; unw_word_t offset; - if ((unw_get_proc_name(&cursor1, functionName, 512, &offset) != - UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) - strcpy(functionName, ".anonymous."); + if ((unw_get_proc_name(&cursor1, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; unw_word_t pc; unw_get_reg(&cursor1, UNW_REG_IP, &pc); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, " "lsda=0x%llX, personality=0x%llX\n", - exception_object, (long long)pc, (long long)frameInfo.start_ip, - functionName, (long long)frameInfo.lsda, - (long long)frameInfo.handler); + static_cast<void *>(exception_object), (long long)pc, + (long long)frameInfo.start_ip, functionName, + (long long)frameInfo.lsda, (long long)frameInfo.handler); } // If there is a personality routine, ask it if it will want to stop at @@ -531,7 +494,8 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { (__personality_routine)(long)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): calling personality function %p\n", - exception_object, p); + static_cast<void *>(exception_object), + reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p))); struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor1); exception_object->pr_cache.fnstart = frameInfo.start_ip; exception_object->pr_cache.ehtp = @@ -540,10 +504,11 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { _Unwind_Reason_Code personalityResult = (*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): personality result %d " - "start_ip %x ehtp %p additional %x\n", - exception_object, personalityResult, - exception_object->pr_cache.fnstart, exception_object->pr_cache.ehtp, + "unwind_phase1(ex_ojb=%p): personality result %d start_ip %x ehtp %p " + "additional %x\n", + static_cast<void *>(exception_object), personalityResult, + exception_object->pr_cache.fnstart, + static_cast<void *>(exception_object->pr_cache.ehtp), exception_object->pr_cache.additional); switch (personalityResult) { case _URC_HANDLER_FOUND: @@ -551,15 +516,15 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { // stop search and remember stack pointer at the frame handlerNotFound = false; // p should have initialized barrier_cache. EHABI #7.3.5 - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " - "_URC_HANDLER_FOUND \n", - exception_object); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n", + static_cast<void *>(exception_object)); return _URC_NO_REASON; case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", - exception_object); + static_cast<void *>(exception_object)); // continue unwinding break; @@ -571,7 +536,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { // something went wrong _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", - exception_object); + static_cast<void *>(exception_object)); return _URC_FATAL_PHASE1_ERROR; } } @@ -586,7 +551,8 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t cursor2; unw_init_local(&cursor2, uc); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", + static_cast<void *>(exception_object)); int frame_count = 0; // Walk each frame until we reach where search phase said to stop. @@ -613,13 +579,13 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, int stepResult = unw_step(&cursor2); if (stepResult == 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK\n", - exception_object); + "bottom => _URC_END_OF_STACK\n", + static_cast<void *>(exception_object)); return _URC_END_OF_STACK; } else if (stepResult < 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => " - "_URC_FATAL_PHASE1_ERROR\n", - exception_object); + "_URC_FATAL_PHASE1_ERROR\n", + static_cast<void *>(exception_object)); return _URC_FATAL_PHASE2_ERROR; } @@ -629,23 +595,25 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_get_reg(&cursor2, UNW_REG_SP, &sp); if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR\n", - exception_object); + "failed => _URC_FATAL_PHASE1_ERROR\n", + static_cast<void *>(exception_object)); return _URC_FATAL_PHASE2_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { - char functionName[512]; + char functionBuf[512]; + const char *functionName = functionBuf; unw_word_t offset; - if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) != - UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) - strcpy(functionName, ".anonymous."); + if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, " "lsda=0x%llX, personality=0x%llX\n", - exception_object, (long long)frameInfo.start_ip, functionName, - (long long)sp, (long long)frameInfo.lsda, + static_cast<void *>(exception_object), (long long)frameInfo.start_ip, + functionName, (long long)sp, (long long)frameInfo.lsda, (long long)frameInfo.handler); } @@ -666,7 +634,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, // Continue unwinding _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", - exception_object); + static_cast<void *>(exception_object)); // EHABI #7.2 if (sp == exception_object->barrier_cache.sp) { // Phase 1 said we would stop at this frame, but we did not... @@ -677,17 +645,17 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", - exception_object); + static_cast<void *>(exception_object)); // Personality routine says to transfer control to landing pad. // We may get control back if landing pad calls _Unwind_Resume(). if (_LIBUNWIND_TRACING_UNWINDING) { unw_word_t pc; unw_get_reg(&cursor2, UNW_REG_IP, &pc); unw_get_reg(&cursor2, UNW_REG_SP, &sp); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " "user code with ip=0x%llX, sp=0x%llX\n", - exception_object, (long long)pc, - (long long)sp); + static_cast<void *>(exception_object), + (long long)pc, (long long)sp); } { @@ -724,7 +692,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object) { _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n", - exception_object); + static_cast<void *>(exception_object)); unw_context_t uc; unw_getcontext(&uc); @@ -760,7 +728,8 @@ _LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) { /// in turn calls _Unwind_Resume_or_Rethrow(). _LIBUNWIND_EXPORT void _Unwind_Resume(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", exception_object); + _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", + static_cast<void *>(exception_object)); unw_context_t uc; unw_getcontext(&uc); @@ -781,8 +750,9 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { uintptr_t result = 0; if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) result = (uintptr_t)frameInfo.lsda; - _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p)" - "=> 0x%llx\n", context, (long long)result); + _LIBUNWIND_TRACE_API( + "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx\n", + static_cast<void *>(context), (long long)result); if (result != 0) { if (*((uint8_t *)result) != 0xFF) _LIBUNWIND_DEBUG_LOG("lsda at 0x%llx does not start with 0xFF\n", @@ -809,15 +779,14 @@ static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, return value; } -_Unwind_VRS_Result _Unwind_VRS_Set( - _Unwind_Context *context, - _Unwind_VRS_RegClass regclass, - uint32_t regno, - _Unwind_VRS_DataRepresentation representation, - void *valuep) { +_Unwind_VRS_Result +_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t regno, _Unwind_VRS_DataRepresentation representation, + void *valuep) { _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, " - "rep=%d, value=0x%llX)\n", context, regclass, - regno, representation, + "rep=%d, value=0x%llX)\n", + static_cast<void *>(context), regclass, regno, + representation, ValueAsBitPattern(representation, valuep)); unw_cursor_t *cursor = (unw_cursor_t *)context; switch (regclass) { @@ -859,14 +828,14 @@ _Unwind_VRS_Result _Unwind_VRS_Set( ? _UVRSR_OK : _UVRSR_FAILED; } + _LIBUNWIND_ABORT("unsupported register class"); } -static _Unwind_VRS_Result _Unwind_VRS_Get_Internal( - _Unwind_Context *context, - _Unwind_VRS_RegClass regclass, - uint32_t regno, - _Unwind_VRS_DataRepresentation representation, - void *valuep) { +static _Unwind_VRS_Result +_Unwind_VRS_Get_Internal(_Unwind_Context *context, + _Unwind_VRS_RegClass regclass, uint32_t regno, + _Unwind_VRS_DataRepresentation representation, + void *valuep) { unw_cursor_t *cursor = (unw_cursor_t *)context; switch (regclass) { case _UVRSC_CORE: @@ -907,6 +876,7 @@ static _Unwind_VRS_Result _Unwind_VRS_Get_Internal( ? _UVRSR_OK : _UVRSR_FAILED; } + _LIBUNWIND_ABORT("unsupported register class"); } _Unwind_VRS_Result _Unwind_VRS_Get( @@ -920,19 +890,20 @@ _Unwind_VRS_Result _Unwind_VRS_Get( valuep); _LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, " "rep=%d, value=0x%llX, result = %d)\n", - context, regclass, regno, representation, + static_cast<void *>(context), regclass, regno, + representation, ValueAsBitPattern(representation, valuep), result); return result; } -_Unwind_VRS_Result _Unwind_VRS_Pop( - _Unwind_Context *context, - _Unwind_VRS_RegClass regclass, - uint32_t discriminator, - _Unwind_VRS_DataRepresentation representation) { +_Unwind_VRS_Result +_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t discriminator, + _Unwind_VRS_DataRepresentation representation) { _LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, " "discriminator=%d, representation=%d)\n", - context, regclass, discriminator, representation); + static_cast<void *>(context), regclass, discriminator, + representation); switch (regclass) { case _UVRSC_CORE: case _UVRSC_WMMXC: { @@ -947,7 +918,7 @@ _Unwind_VRS_Result _Unwind_VRS_Pop( return _UVRSR_FAILED; } for (uint32_t i = 0; i < 16; ++i) { - if (!(discriminator & (1 << i))) + if (!(discriminator & static_cast<uint32_t>(1 << i))) continue; uint32_t value = *sp++; if (regclass == _UVRSC_CORE && i == 13) @@ -990,7 +961,8 @@ _Unwind_VRS_Result _Unwind_VRS_Pop( return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); } - }; + } + _LIBUNWIND_ABORT("unsupported register class"); } /// Called by personality handler during phase 2 to find the start of the @@ -1003,7 +975,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) { if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) result = (uintptr_t)frameInfo.start_ip; _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX\n", - context, (long long)result); + static_cast<void *>(context), (long long)result); return result; } @@ -1013,7 +985,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) { _LIBUNWIND_EXPORT void _Unwind_DeleteException(_Unwind_Exception *exception_object) { _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n", - exception_object); + static_cast<void *>(exception_object)); if (exception_object->exception_cleanup != NULL) (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object); diff --git a/src/Unwind/Unwind-EHABI.h b/src/Unwind/Unwind-EHABI.h new file mode 100644 index 0000000..ebd56a1 --- /dev/null +++ b/src/Unwind/Unwind-EHABI.h @@ -0,0 +1,51 @@ +//===------------------------- Unwind-EHABI.hpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +//===----------------------------------------------------------------------===// + +#ifndef __UNWIND_EHABI_H__ +#define __UNWIND_EHABI_H__ + +#include <__cxxabi_config.h> + +#if LIBCXXABI_ARM_EHABI + +#include <stdint.h> +#include <unwind.h> + +// Unable to unwind in the ARM index table (section 5 EHABI). +#define UNW_EXIDX_CANTUNWIND 0x1 + +static inline uint32_t signExtendPrel31(uint32_t data) { + return data | ((data & 0x40000000u) << 1); +} + +static inline uint32_t readPrel31(const uint32_t *data) { + return (((uint32_t)(uintptr_t)data) + signExtendPrel31(*data)); +} + +#if defined(__cplusplus) +extern "C" { +#endif + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // LIBCXXABI_ARM_EHABI + +#endif // __UNWIND_EHABI_H__ diff --git a/src/Unwind/UnwindCursor.hpp b/src/Unwind/UnwindCursor.hpp index 0350dfd..b4d413f 100644 --- a/src/Unwind/UnwindCursor.hpp +++ b/src/Unwind/UnwindCursor.hpp @@ -19,17 +19,20 @@ #include <pthread.h> #include <unwind.h> -#if __APPLE__ +#ifdef __APPLE__ #include <mach-o/dyld.h> #endif -#include "libunwind.h" +#include "config.h" #include "AddressSpace.hpp" -#include "Registers.hpp" -#include "DwarfInstructions.hpp" #include "CompactUnwinder.hpp" #include "config.h" +#include "DwarfInstructions.hpp" +#include "EHHeaderParser.hpp" +#include "libunwind.h" +#include "Registers.hpp" +#include "Unwind-EHABI.h" namespace libunwind { @@ -58,7 +61,7 @@ private: // These fields are all static to avoid needing an initializer. // There is only one instance of this class per process. static pthread_rwlock_t _lock; -#if __APPLE__ +#ifdef __APPLE__ static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); static bool _registeredForDyldUnloads; #endif @@ -87,7 +90,7 @@ typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64]; template <typename A> pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER; -#if __APPLE__ +#ifdef __APPLE__ template <typename A> bool DwarfFDECache<A>::_registeredForDyldUnloads = false; #endif @@ -129,7 +132,7 @@ void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, _bufferUsed->ip_end = ip_end; _bufferUsed->fde = fde; ++_bufferUsed; -#if __APPLE__ +#ifdef __APPLE__ if (!_registeredForDyldUnloads) { _dyld_register_func_for_remove_image(&dyldUnloadHook); _registeredForDyldUnloads = true; @@ -153,7 +156,7 @@ void DwarfFDECache<A>::removeAllIn(pint_t mh) { _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); } -#if __APPLE__ +#ifdef __APPLE__ template <typename A> void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) { removeAllIn((pint_t) mh); @@ -364,29 +367,49 @@ private: }; #endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND - class _LIBUNWIND_HIDDEN AbstractUnwindCursor { public: - virtual ~AbstractUnwindCursor() {} - virtual bool validReg(int) = 0; - virtual unw_word_t getReg(int) = 0; - virtual void setReg(int, unw_word_t) = 0; - virtual bool validFloatReg(int) = 0; - virtual unw_fpreg_t getFloatReg(int) = 0; - virtual void setFloatReg(int, unw_fpreg_t) = 0; - virtual int step() = 0; - virtual void getInfo(unw_proc_info_t *) = 0; - virtual void jumpto() = 0; - virtual bool isSignalFrame() = 0; - virtual bool getFunctionName(char *bf, size_t ln, unw_word_t *off) = 0; - virtual void setInfoBasedOnIPRegister(bool isReturnAddr = false) = 0; - virtual const char *getRegisterName(int num) = 0; -#if __arm__ - virtual void saveVFPAsX() = 0; + // NOTE: provide a class specific placement deallocation function (S5.3.4 p20) + // This avoids an unnecessary dependency to libc++abi. + void operator delete(void *, size_t) {} + + virtual ~AbstractUnwindCursor() {} + virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } + virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } + virtual void setReg(int, unw_word_t) { + _LIBUNWIND_ABORT("setReg not implemented"); + } + virtual bool validFloatReg(int) { + _LIBUNWIND_ABORT("validFloatReg not implemented"); + } + virtual unw_fpreg_t getFloatReg(int) { + _LIBUNWIND_ABORT("getFloatReg not implemented"); + } + virtual void setFloatReg(int, unw_fpreg_t) { + _LIBUNWIND_ABORT("setFloatReg not implemented"); + } + virtual int step() { _LIBUNWIND_ABORT("step not implemented"); } + virtual void getInfo(unw_proc_info_t *) { + _LIBUNWIND_ABORT("getInfo not implemented"); + } + virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } + virtual bool isSignalFrame() { + _LIBUNWIND_ABORT("isSignalFrame not implemented"); + } + virtual bool getFunctionName(char *, size_t, unw_word_t *) { + _LIBUNWIND_ABORT("getFunctionName not implemented"); + } + virtual void setInfoBasedOnIPRegister(bool = false) { + _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented"); + } + virtual const char *getRegisterName(int) { + _LIBUNWIND_ABORT("getRegisterName not implemented"); + } +#ifdef __arm__ + virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } #endif }; - /// UnwindCursor contains all state (including all register values) during /// an unwind. This is normally stack allocated inside a unw_cursor_t. template <typename A, typename R> @@ -409,12 +432,10 @@ public: virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); virtual const char *getRegisterName(int num); -#if __arm__ +#ifdef __arm__ virtual void saveVFPAsX(); #endif - void operator delete(void *, size_t) {} - private: #if LIBCXXABI_ARM_EHABI @@ -584,7 +605,7 @@ template <typename A, typename R> void UnwindCursor<A, R>::jumpto() { _registers.jumpto(); } -#if __arm__ +#ifdef __arm__ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() { _registers.saveVFPAsX(); } @@ -605,20 +626,6 @@ struct EHABIIndexEntry { uint32_t data; }; -// Unable to unwind in the ARM index table (section 5 EHABI). -#define UNW_EXIDX_CANTUNWIND 0x1 - -static inline uint32_t signExtendPrel31(uint32_t data) { - return data | ((data & 0x40000000u) << 1); -} - -extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr0( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); -extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr1( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); -extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr2( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); - template<typename A> struct EHABISectionIterator { typedef EHABISectionIterator _Self; @@ -730,8 +737,8 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( // in compact form (section 6.3 EHABI). if (exceptionTableData & 0x80000000) { // Grab the index of the personality routine from the compact form. - int choice = (exceptionTableData & 0x0f000000) >> 24; - int extraWords = 0; + uint32_t choice = (exceptionTableData & 0x0f000000) >> 24; + uint32_t extraWords = 0; switch (choice) { case 0: personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0; @@ -823,8 +830,9 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, } #if _LIBUNWIND_SUPPORT_DWARF_INDEX if (!foundFDE && (sects.dwarf_index_section != 0)) { - // Have eh_frame_hdr section which is index into dwarf section. - // TO DO: implement index search + foundFDE = EHHeaderParser<A>::findFDE( + _addressSpace, pc, sects.dwarf_index_section, + (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); } #endif if (!foundFDE) { @@ -1304,6 +1312,6 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen, buf, bufLen, offset); } -}; // namespace libunwind +} // namespace libunwind #endif // __UNWINDCURSOR_HPP__ diff --git a/src/Unwind/UnwindLevel1-gcc-ext.c b/src/Unwind/UnwindLevel1-gcc-ext.c index c119d57..b1e3f77 100644 --- a/src/Unwind/UnwindLevel1-gcc-ext.c +++ b/src/Unwind/UnwindLevel1-gcc-ext.c @@ -16,10 +16,11 @@ #include <stdio.h> #include <stdlib.h> +#include "config.h" +#include "libunwind_ext.h" #include "libunwind.h" +#include "Unwind-EHABI.h" #include "unwind.h" -#include "libunwind_ext.h" -#include "config.h" #if _LIBUNWIND_BUILD_ZERO_COST_APIS @@ -27,14 +28,12 @@ _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { #if LIBCXXABI_ARM_EHABI - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), " - "private_1=%ld\n", - exception_object, + _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", + (void *)exception_object, (long)exception_object->unwinder_cache.reserved1); #else - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), " - "private_1=%ld\n", - exception_object, + _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", + (void *)exception_object, (long)exception_object->private_1); #endif @@ -66,7 +65,7 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { _LIBUNWIND_EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) { (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)\n", context); + _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)\n", (void *)context); _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); } @@ -76,7 +75,7 @@ _Unwind_GetDataRelBase(struct _Unwind_Context *context) { _LIBUNWIND_EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) { (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", context); + _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", (void *)context); _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); } @@ -99,7 +98,6 @@ _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { return NULL; } - /// Walk every frame and call trace function at each one. If trace function /// returns anything other than _URC_NO_REASON, then walk is terminated. _LIBUNWIND_EXPORT _Unwind_Reason_Code @@ -109,7 +107,8 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { unw_getcontext(&uc); unw_init_local(&cursor, &uc); - _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)\n", callback); + _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)\n", + (void *)(uintptr_t)callback); // walk each frame while (true) { @@ -132,17 +131,39 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { } struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; - size_t off; - size_t len; const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info; - unwindInfo = decode_eht_entry(unwindInfo, &off, &len); - if (unwindInfo == NULL) { - return _URC_FAILURE; - } - - result = _Unwind_VRS_Interpret(context, unwindInfo, off, len); - if (result != _URC_CONTINUE_UNWIND) { - return _URC_END_OF_STACK; + if ((*unwindInfo & 0x80000000) == 0) { + // 6.2: Generic Model + // EHT entry is a prel31 pointing to the PR, followed by data understood + // only by the personality routine. Since EHABI doesn't guarantee the + // location or availability of the unwind opcodes in the generic model, + // we have to call personality functions with (_US_VIRTUAL_UNWIND_FRAME | + // _US_FORCE_UNWIND) state. + + // Create a mock exception object for force unwinding. + _Unwind_Exception ex; + ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0 + ex.pr_cache.fnstart = frameInfo.start_ip; + ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo; + ex.pr_cache.additional= frameInfo.flags; + + // Get and call the personality function to unwind the frame. + __personality_routine pr = (__personality_routine) readPrel31(unwindInfo); + if (pr(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) != + _URC_CONTINUE_UNWIND) { + return _URC_END_OF_STACK; + } + } else { + size_t off, len; + unwindInfo = decode_eht_entry(unwindInfo, &off, &len); + if (unwindInfo == NULL) { + return _URC_FAILURE; + } + + result = _Unwind_VRS_Interpret(context, unwindInfo, off, len); + if (result != _URC_CONTINUE_UNWIND) { + return _URC_END_OF_STACK; + } } #endif // LIBCXXABI_ARM_EHABI @@ -155,16 +176,15 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { unw_get_proc_info(&cursor, &frame); _LIBUNWIND_TRACE_UNWINDING( " _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p\n", - (long long)frame.start_ip, functionName, - (long long)frame.lsda, &cursor); + (long long)frame.start_ip, functionName, (long long)frame.lsda, + (void *)&cursor); } // call trace function with this frame result = (*callback)((struct _Unwind_Context *)(&cursor), ref); if (result != _URC_NO_REASON) { - _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because callback " - "returned %d\n", - result); + _LIBUNWIND_TRACE_UNWINDING( + " _backtrace: ended because callback returned %d\n", result); return result; } } @@ -197,8 +217,8 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_word_t result; unw_get_reg(cursor, UNW_REG_SP, &result); - _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIx64 "\n", context, - (uint64_t)result); + _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIx64 "\n", + (void *)context, (uint64_t)result); return (uintptr_t)result; } @@ -208,7 +228,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { /// site address. Normally IP is the return address. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *ipBefore) { - _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)\n", context); + _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)\n", (void *)context); *ipBefore = 0; return _Unwind_GetIP(context); } diff --git a/src/Unwind/UnwindLevel1.c b/src/Unwind/UnwindLevel1.c index 9dde70d..5b911de 100644 --- a/src/Unwind/UnwindLevel1.c +++ b/src/Unwind/UnwindLevel1.c @@ -38,13 +38,13 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { int stepResult = unw_step(&cursor1); if (stepResult == 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK\n", - exception_object); + "bottom => _URC_END_OF_STACK\n", + (void *)exception_object); return _URC_END_OF_STACK; } else if (stepResult < 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => " - "_URC_FATAL_PHASE1_ERROR\n", - exception_object); + "_URC_FATAL_PHASE1_ERROR\n", + (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; } @@ -53,25 +53,26 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { unw_word_t sp; if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR\n", - exception_object); + "failed => _URC_FATAL_PHASE1_ERROR\n", + (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { - char functionName[512]; + char functionBuf[512]; + const char *functionName = functionBuf; unw_word_t offset; - if ((unw_get_proc_name(&cursor1, functionName, 512, &offset) != - UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) - strcpy(functionName, ".anonymous."); + if ((unw_get_proc_name(&cursor1, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; unw_word_t pc; unw_get_reg(&cursor1, UNW_REG_IP, &pc); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64 - ", func=%s, " - "lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n", - exception_object, pc, frameInfo.start_ip, functionName, + ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n", + (void *)exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } @@ -82,7 +83,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { (__personality_routine)(long)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): calling personality function %p\n", - exception_object, p); + (void *)exception_object, (void *)(uintptr_t)p); _Unwind_Reason_Code personalityResult = (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(&cursor1)); @@ -93,15 +94,15 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { handlerNotFound = false; unw_get_reg(&cursor1, UNW_REG_SP, &sp); exception_object->private_2 = (uintptr_t)sp; - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " - "_URC_HANDLER_FOUND \n", - exception_object); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n", + (void *)exception_object); return _URC_NO_REASON; case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", - exception_object); + (void *)exception_object); // continue unwinding break; @@ -109,7 +110,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { // something went wrong _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", - exception_object); + (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; } } @@ -123,7 +124,8 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) { unw_cursor_t cursor2; unw_init_local(&cursor2, uc); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", + (void *)exception_object); // Walk each frame until we reach where search phase said to stop. while (true) { @@ -133,13 +135,13 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) { int stepResult = unw_step(&cursor2); if (stepResult == 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK\n", - exception_object); + "bottom => _URC_END_OF_STACK\n", + (void *)exception_object); return _URC_END_OF_STACK; } else if (stepResult < 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => " - "_URC_FATAL_PHASE1_ERROR\n", - exception_object); + "_URC_FATAL_PHASE1_ERROR\n", + (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } @@ -149,24 +151,26 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) { unw_get_reg(&cursor2, UNW_REG_SP, &sp); if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR\n", - exception_object); + "failed => _URC_FATAL_PHASE1_ERROR\n", + (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { - char functionName[512]; + char functionBuf[512]; + const char *functionName = functionBuf; unw_word_t offset; - if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) != - UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) - strcpy(functionName, ".anonymous."); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIx64 - ", func=%s, sp=0x%" PRIx64 ", " - "lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n", - exception_object, frameInfo.start_ip, functionName, sp, - frameInfo.lsda, frameInfo.handler); + if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIx64 + ", func=%s, sp=0x%" PRIx64 ", lsda=0x%" PRIx64 + ", personality=0x%" PRIx64 "\n", + (void *)exception_object, frameInfo.start_ip, + functionName, sp, frameInfo.lsda, + frameInfo.handler); } // If there is a personality routine, tell it we are unwinding. @@ -186,7 +190,7 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) { // Continue unwinding _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", - exception_object); + (void *)exception_object); if (sp == exception_object->private_2) { // Phase 1 said we would stop at this frame, but we did not... _LIBUNWIND_ABORT("during phase1 personality function said it would " @@ -196,17 +200,17 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) { case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", - exception_object); + (void *)exception_object); // Personality routine says to transfer control to landing pad. // We may get control back if landing pad calls _Unwind_Resume(). if (_LIBUNWIND_TRACING_UNWINDING) { unw_word_t pc; unw_get_reg(&cursor2, UNW_REG_IP, &pc); unw_get_reg(&cursor2, UNW_REG_SP, &sp); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " "user code with ip=0x%" PRIx64 ", sp=0x%" PRIx64 "\n", - exception_object, pc, sp); + (void *)exception_object, pc, sp); } unw_resume(&cursor2); // unw_resume() only returns if there was an error. @@ -214,7 +218,7 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) { default: // Personality routine returned an unknown result code. _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", - personalityResult); + personalityResult); return _URC_FATAL_PHASE2_ERROR; } } @@ -240,23 +244,24 @@ unwind_phase2_forced(unw_context_t *uc, if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step " "failed => _URC_END_OF_STACK\n", - exception_object); + (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { - char functionName[512]; + char functionBuf[512]; + const char *functionName = functionBuf; unw_word_t offset; - if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) != - UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) - strcpy(functionName, ".anonymous."); + if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): " - "start_ip=0x%" PRIx64 ", func=%s, lsda=0x%" PRIx64 ", " - " personality=0x%" PRIx64 "\n", - exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, - frameInfo.handler); + "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64 + ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n", + (void *)exception_object, frameInfo.start_ip, functionName, + frameInfo.lsda, frameInfo.handler); } // Call stop function at each frame. @@ -267,11 +272,11 @@ unwind_phase2_forced(unw_context_t *uc, (struct _Unwind_Context *)(&cursor2), stop_parameter); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", - exception_object, stopResult); + (void *)exception_object, stopResult); if (stopResult != _URC_NO_REASON) { _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", - exception_object); + (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } @@ -281,21 +286,23 @@ unwind_phase2_forced(unw_context_t *uc, (__personality_routine)(long)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", - exception_object, p); + (void *)exception_object, (void *)(uintptr_t)p); _Unwind_Reason_Code personalityResult = (*p)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(&cursor2)); switch (personalityResult) { case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned _URC_CONTINUE_UNWIND\n", - exception_object); + "personality returned " + "_URC_CONTINUE_UNWIND\n", + (void *)exception_object); // Destructors called, continue unwinding break; case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned _URC_INSTALL_CONTEXT\n", - exception_object); + "personality returned " + "_URC_INSTALL_CONTEXT\n", + (void *)exception_object); // We may get control back if landing pad calls _Unwind_Resume(). unw_resume(&cursor2); break; @@ -304,7 +311,7 @@ unwind_phase2_forced(unw_context_t *uc, _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " "personality returned %d, " "_URC_FATAL_PHASE2_ERROR\n", - exception_object, personalityResult); + (void *)exception_object, personalityResult); return _URC_FATAL_PHASE2_ERROR; } } @@ -313,8 +320,8 @@ unwind_phase2_forced(unw_context_t *uc, // Call stop function one last time and tell it we've reached the end // of the stack. _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " - "function with _UA_END_OF_STACK\n", - exception_object); + "function with _UA_END_OF_STACK\n", + (void *)exception_object); _Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); (*stop)(1, lastAction, exception_object->exception_class, exception_object, @@ -330,7 +337,7 @@ unwind_phase2_forced(unw_context_t *uc, _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object) { _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n", - exception_object); + (void *)exception_object); unw_context_t uc; unw_getcontext(&uc); @@ -363,7 +370,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) { /// in turn calls _Unwind_Resume_or_Rethrow(). _LIBUNWIND_EXPORT void _Unwind_Resume(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", exception_object); + _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object); unw_context_t uc; unw_getcontext(&uc); @@ -387,7 +394,7 @@ _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, void *stop_parameter) { _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n", - exception_object, stop); + (void *)exception_object, (void *)(uintptr_t)stop); unw_context_t uc; unw_getcontext(&uc); @@ -409,9 +416,9 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { uintptr_t result = 0; if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) result = (uintptr_t)frameInfo.lsda; - _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p)" - "=> 0x%" PRIxPTR "\n", - context, result); + _LIBUNWIND_TRACE_API( + "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR "\n", + (void *)context, result); if (result != 0) { if (*((uint8_t *)result) != 0xFF) _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF\n", @@ -421,80 +428,111 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { } +/// Called by personality handler during phase 2 to find the start of the +/// function. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetRegionStart(struct _Unwind_Context *context) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_proc_info_t frameInfo; + uintptr_t result = 0; + if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) + result = (uintptr_t)frameInfo.start_ip; + _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR "\n", + (void *)context, result); + return result; +} + + +/// Called by personality handler during phase 2 if a foreign exception +// is caught. +_LIBUNWIND_EXPORT void +_Unwind_DeleteException(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n", + (void *)exception_object); + if (exception_object->exception_cleanup != NULL) + (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, + exception_object); +} + +#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI + +#if LIBCXXABI_ARM_EHABI + +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetGR(struct _Unwind_Context *context, int index) { + uintptr_t value = 0; + _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); + _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n", + (void *)context, index, (uint64_t)value); + return value; +} + +_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uintptr_t value) { + _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0"PRIx64")\n", + (void *)context, index, (uint64_t)value); + _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); +} + +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { + // remove the thumb-bit before returning + uintptr_t value = _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1); + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n", + (void *)context, (uint64_t)value); + return value; +} + +_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, + uintptr_t value) { + _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")\n", + (void *)context, (uint64_t)value); + uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); + _Unwind_SetGR(context, 15, value | thumb_bit); +} + +#else /// Called by personality handler during phase 2 to get register values. -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, - int index) { +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetGR(struct _Unwind_Context *context, int index) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_word_t result; unw_get_reg(cursor, index, &result); _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n", - context, index, (uint64_t)result); + (void *)context, index, (uint64_t)result); return (uintptr_t)result; } - - /// Called by personality handler during phase 2 to alter register values. _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t new_value) { - _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, " - "value=0x%0" PRIx64 ")\n", - context, index, (uint64_t)new_value); + uintptr_t value) { + _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIx64 + ")\n", + (void *)context, index, (uint64_t)value); unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_set_reg(cursor, index, new_value); + unw_set_reg(cursor, index, value); } - - /// Called by personality handler during phase 2 to get instruction pointer. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_word_t result; unw_get_reg(cursor, UNW_REG_IP, &result); - _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n", context, - (uint64_t)result); + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n", + (void *)context, (uint64_t)result); return (uintptr_t)result; } - - /// Called by personality handler during phase 2 to alter instruction pointer, /// such as setting where the landing pad is, so _Unwind_Resume() will /// start executing in the landing pad. _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, - uintptr_t new_value) { + uintptr_t value) { _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")\n", - context, (uint64_t)new_value); - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_set_reg(cursor, UNW_REG_IP, new_value); -} - - -/// Called by personality handler during phase 2 to find the start of the -/// function. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetRegionStart(struct _Unwind_Context *context) { + (void *)context, (uint64_t)value); unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_proc_info_t frameInfo; - uintptr_t result = 0; - if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) - result = (uintptr_t)frameInfo.start_ip; - _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR "\n", - context, result); - return result; + unw_set_reg(cursor, UNW_REG_IP, value); } +#endif -/// Called by personality handler during phase 2 if a foreign exception -// is caught. -_LIBUNWIND_EXPORT void -_Unwind_DeleteException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n", - exception_object); - if (exception_object->exception_cleanup != NULL) - (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, - exception_object); -} - -#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI diff --git a/src/Unwind/UnwindRegistersRestore.S b/src/Unwind/UnwindRegistersRestore.S index 7dd3a11..00f2aeb 100644 --- a/src/Unwind/UnwindRegistersRestore.S +++ b/src/Unwind/UnwindRegistersRestore.S @@ -11,7 +11,7 @@ .text -#if __i386__ +#if defined(__i386__) DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) # # void libunwind::Registers_x86::jumpto() @@ -52,7 +52,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) # skip fs # skip gs -#elif __x86_64__ +#elif defined(__x86_64__) DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) # @@ -93,7 +93,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) ret # rip was saved here -#elif __ppc__ +#elif defined(__ppc__) DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) ; @@ -258,7 +258,7 @@ Lnovec: lwz r3,20(r3) ; do r3 last bctr -#elif __arm64__ +#elif defined(__arm64__) ; ; void libunwind::Registers_arm64::jumpto() @@ -308,7 +308,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) ldp x0, x1, [x0, #0x000] ; restore x0,x1 ret lr ; jump to pc -#elif __arm__ && !__APPLE__ +#elif defined(__arm__) && !defined(__APPLE__) #if !defined(__ARM_ARCH_ISA_ARM) .thumb @@ -347,8 +347,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJu @ values pointer is in r0 @ .p2align 2 + .fpu vfpv3-d16 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy) -#if defined(__ARM_FP) @ VFP and iwMMX instructions are only available when compiling with the flags @ that enable them. We do not want to do that in the library (because we do not @ want the compiler to generate instructions that access those) but this is @@ -356,12 +356,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL @ these registers implies they are, actually, available on the target, so @ it's ok to execute. @ So, generate the instruction using the corresponding coprocessor mnemonic. -#if __ARM_ARCH < 7 - ldc p11, cr0, [r0], {0x20} @ fldmiad r0, {d0-d15} -#else vldmia r0, {d0-d15} -#endif -#endif JMP(lr) @ @@ -371,14 +366,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL @ values pointer is in r0 @ .p2align 2 + .fpu vfpv3-d16 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy) -#if defined(__ARM_FP) -#if __ARM_ARCH < 7 - ldc p11, cr0, [r0], {0x21} @ fldmiax r0, {d0-d15} -#else vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia -#endif -#endif JMP(lr) @ @@ -388,14 +378,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL @ values pointer is in r0 @ .p2align 2 + .fpu vfpv3 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy) -#if defined(__ARM_FP) -#ifndef __ARM_NEON - ldcl p11, cr0, [r0], {0x20} @ vldm r0, {d16-d31} -#else vldmia r0, {d16-d31} -#endif -#endif JMP(lr) @ @@ -406,7 +391,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy) @ .p2align 2 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy) -#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || __ARM_WMMX +#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX) ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8 @@ -434,7 +419,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy) @ .p2align 2 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) -#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || __ARM_WMMX +#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX) ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4 diff --git a/src/Unwind/UnwindRegistersSave.S b/src/Unwind/UnwindRegistersSave.S index d6b9a41..8c886a8 100644 --- a/src/Unwind/UnwindRegistersSave.S +++ b/src/Unwind/UnwindRegistersSave.S @@ -11,7 +11,7 @@ .text -#if __i386__ +#if defined(__i386__) # # extern int unw_getcontext(unw_context_t* thread_state) @@ -52,7 +52,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) xorl %eax, %eax # return UNW_ESUCCESS ret -#elif __x86_64__ +#elif defined(__x86_64__) # # extern int unw_getcontext(unw_context_t* thread_state) @@ -87,7 +87,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) xorl %eax, %eax # return UNW_ESUCCESS ret -#elif __ppc__ +#elif defined(__ppc__) ; ; extern int unw_getcontext(unw_context_t* thread_state) @@ -230,7 +230,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) blr -#elif __arm64__ +#elif defined(__arm64__) ; ; extern int unw_getcontext(unw_context_t* thread_state) @@ -280,7 +280,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) ldr x0, #0 ; return UNW_ESUCCESS ret -#elif __arm__ && !__APPLE__ +#elif defined(__arm__) && !defined(__APPLE__) #if !defined(__ARM_ARCH_ISA_ARM) .thumb @@ -316,7 +316,14 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) str lr, [r0, #56] str lr, [r0, #60] @ store return address as pc #endif +#if __ARM_ARCH_ISA_THUMB == 1 + @ T1 does not have a non-cpsr-clobbering register-zeroing instruction. + @ It is safe to use here though because we are about to return, and cpsr is + @ not expected to be preserved. + movs r0, #0 @ return UNW_ESUCCESS +#else mov r0, #0 @ return UNW_ESUCCESS +#endif JMP(lr) @ @@ -326,14 +333,9 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) @ values pointer is in r0 @ .p2align 2 + .fpu vfpv3-d16 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy) -#if defined(__ARM_FP) -#if __ARM_ARCH < 7 - stc p11, cr0, [r0], {0x20} @ fstmiad r0, {d0-d15} -#else vstmia r0, {d0-d15} -#endif -#endif JMP(lr) @ @@ -343,14 +345,9 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMD @ values pointer is in r0 @ .p2align 2 + .fpu vfpv3-d16 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy) -#if defined(__ARM_FP) -#if __ARM_ARCH < 7 - stc p11, cr0, [r0], {0x21} @ fstmiax r0, {d0-d15} -#else vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia -#endif -#endif JMP(lr) @ @@ -360,8 +357,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMX @ values pointer is in r0 @ .p2align 2 + .fpu vfpv3 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy) -#if defined(__ARM_FP) @ VFP and iwMMX instructions are only available when compiling with the flags @ that enable them. We do not want to do that in the library (because we do not @ want the compiler to generate instructions that access those) but this is @@ -369,12 +366,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy) @ these registers implies they are, actually, available on the target, so @ it's ok to execute. @ So, generate the instructions using the corresponding coprocessor mnemonic. -#ifndef __ARM_NEON - stcl p11, cr0, [r0], {0x20} @ vstm r0, {d16-d31} -#else vstmia r0, {d16-d31} -#endif -#endif JMP(lr) @ @@ -385,7 +377,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy) @ .p2align 2 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy) -#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || __ARM_WMMX +#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX) stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8 stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8 stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8 @@ -413,7 +405,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy) @ .p2align 2 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj) -#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || __ARM_WMMX +#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX) stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4 stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4 stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4 diff --git a/src/Unwind/Unwind_AppleExtras.cpp b/src/Unwind/Unwind_AppleExtras.cpp index 6d02a66..b8baef5 100644 --- a/src/Unwind/Unwind_AppleExtras.cpp +++ b/src/Unwind/Unwind_AppleExtras.cpp @@ -41,7 +41,7 @@ struct libgcc_object_info { // static linker symbols to prevent wrong two level namespace for _Unwind symbols -#if __arm__ +#if defined(__arm__) #define NOT_HERE_BEFORE_5_0(sym) \ extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \ __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \ @@ -57,7 +57,7 @@ struct libgcc_object_info { __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \ extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \ __attribute__((visibility("default"))) const char sym##_tmp43 = 0; -#elif __arm64__ +#elif defined(__arm64__) #define NOT_HERE_BEFORE_10_6(sym) #define NEVER_HERE(sym) #else @@ -183,7 +183,7 @@ bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) { } -#if !FOR_DYLD && _LIBUNWIND_BUILD_SJLJ_APIS +#if !defined(FOR_DYLD) && _LIBUNWIND_BUILD_SJLJ_APIS #include <System/pthread_machdep.h> diff --git a/src/Unwind/assembly.h b/src/Unwind/assembly.h index b749d67..f46a24d 100644 --- a/src/Unwind/assembly.h +++ b/src/Unwind/assembly.h @@ -62,6 +62,10 @@ SYMBOL_NAME(name): #if defined(__arm__) +#if !defined(__ARM_ARCH) +#define __ARM_ARCH 4 +#endif + #if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5 #define ARM_HAS_BX #endif diff --git a/src/Unwind/config.h b/src/Unwind/config.h index 848d020..828b68e 100644 --- a/src/Unwind/config.h +++ b/src/Unwind/config.h @@ -28,7 +28,7 @@ #endif // Platform specific configuration defines. -#if __APPLE__ +#ifdef __APPLE__ #include <Availability.h> #ifdef __cplusplus extern "C" { @@ -39,15 +39,18 @@ } #endif - #define _LIBUNWIND_BUILD_ZERO_COST_APIS (__i386__ || __x86_64__ || __arm64__) - #define _LIBUNWIND_BUILD_SJLJ_APIS (__arm__) - #define _LIBUNWIND_SUPPORT_FRAME_APIS (__i386__ || __x86_64__) + #define _LIBUNWIND_BUILD_ZERO_COST_APIS (defined(__i386__) || \ + defined(__x86_64__) || \ + defined(__arm64__)) + #define _LIBUNWIND_BUILD_SJLJ_APIS defined(__arm__) + #define _LIBUNWIND_SUPPORT_FRAME_APIS (defined(__i386__) || \ + defined(__x86_64__)) #define _LIBUNWIND_EXPORT __attribute__((visibility("default"))) #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden"))) #define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libunwind: " msg, __VA_ARGS__) #define _LIBUNWIND_ABORT(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg) - #if FOR_DYLD + #if defined(FOR_DYLD) #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0 @@ -67,17 +70,22 @@ abort(); } - #define _LIBUNWIND_BUILD_ZERO_COST_APIS (__i386__ || __x86_64__ || __arm64__ || __arm__) + #define _LIBUNWIND_BUILD_ZERO_COST_APIS (defined(__i386__) || \ + defined(__x86_64__) || \ + defined(__arm64__) || \ + defined(__arm__)) #define _LIBUNWIND_BUILD_SJLJ_APIS 0 - #define _LIBUNWIND_SUPPORT_FRAME_APIS (__i386__ || __x86_64__) + #define _LIBUNWIND_SUPPORT_FRAME_APIS (defined(__i386__) || \ + defined(__x86_64__)) #define _LIBUNWIND_EXPORT __attribute__((visibility("default"))) #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden"))) #define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__) #define _LIBUNWIND_ABORT(msg) assert_rtn(__func__, __FILE__, __LINE__, msg) #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0 - #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0 - #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0 + #define _LIBUNWIND_SUPPORT_DWARF_UNWIND !defined(__arm__) || \ + defined(__ARM_DWARF_EH__) + #define _LIBUNWIND_SUPPORT_DWARF_INDEX _LIBUNWIND_SUPPORT_DWARF_UNWIND #endif diff --git a/src/Unwind/libunwind.cpp b/src/Unwind/libunwind.cpp index b80beaf..49f06cc 100644 --- a/src/Unwind/libunwind.cpp +++ b/src/Unwind/libunwind.cpp @@ -16,6 +16,9 @@ #include <cstdlib> // getenv #endif #include <new> +#include <tuple> +#include <memory> +#include <vector> #include "libunwind_ext.h" #include "config.h" @@ -32,6 +35,9 @@ using namespace libunwind; /// internal object to represent this processes address space LocalAddressSpace LocalAddressSpace::sThisAddressSpace; +_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space = + (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace; + /// record the registers and stack position of the caller extern int unw_getcontext(unw_context_t *); // note: unw_getcontext() implemented in assembly @@ -41,18 +47,19 @@ extern int unw_getcontext(unw_context_t *); _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, unw_context_t *context) { _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n", - cursor, context); + static_cast<void *>(cursor), + static_cast<void *>(context)); // Use "placement new" to allocate UnwindCursor in the cursor buffer. -#if __i386__ +#if defined(__i386__) new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86>( context, LocalAddressSpace::sThisAddressSpace); -#elif __x86_64__ +#elif defined(__x86_64__) new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>( context, LocalAddressSpace::sThisAddressSpace); -#elif __ppc__ +#elif defined(__ppc__) new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_ppc>( context, LocalAddressSpace::sThisAddressSpace); -#elif __arm64__ +#elif defined(__arm64__) new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>( context, LocalAddressSpace::sThisAddressSpace); #elif LIBCXXABI_ARM_EHABI @@ -65,17 +72,13 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, return UNW_ESUCCESS; } -#if UNW_REMOTE - -_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space = - (unw_addr_space_t) & sThisAddressSpace; - +#ifdef UNW_REMOTE /// Create a cursor into a thread in another process. _LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor, unw_addr_space_t as, void *arg) { // special case: unw_init_remote(xx, unw_local_addr_space, xx) - if (as == (unw_addr_space_t) & sThisAddressSpace) + if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace) return unw_init_local(cursor, NULL); //FIXME // use "placement new" to allocate UnwindCursor in the cursor buffer @@ -155,7 +158,8 @@ _LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) { _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_word_t *value) { _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n", - cursor, regNum, value); + static_cast<void *>(cursor), regNum, + static_cast<void *>(value)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { *value = co->getReg(regNum); @@ -169,7 +173,7 @@ _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_word_t value) { _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n", - cursor, regNum, (long long)value); + static_cast<void *>(cursor), regNum, (long long)value); typedef LocalAddressSpace::pint_t pint_t; AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { @@ -188,7 +192,8 @@ _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, _LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t *value) { _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n", - cursor, regNum, value); + static_cast<void *>(cursor), regNum, + static_cast<void *>(value)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validFloatReg(regNum)) { *value = co->getFloatReg(regNum); @@ -203,10 +208,10 @@ _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t value) { #if LIBCXXABI_ARM_EHABI _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)\n", - cursor, regNum, value); + static_cast<void *>(cursor), regNum, value); #else _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n", - cursor, regNum, value); + static_cast<void *>(cursor), regNum, value); #endif AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validFloatReg(regNum)) { @@ -219,7 +224,7 @@ _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, /// Move cursor to next frame. _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", cursor); + _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", static_cast<void *>(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->step(); } @@ -229,7 +234,7 @@ _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, unw_proc_info_t *info) { _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n", - cursor, info); + static_cast<void *>(cursor), static_cast<void *>(info)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->getInfo(info); if (info->end_ip == 0) @@ -241,7 +246,7 @@ _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, /// Resume execution at cursor position (aka longjump). _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", cursor); + _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", static_cast<void *>(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->jumpto(); return UNW_EUNSPEC; @@ -251,8 +256,9 @@ _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { /// Get name of function at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, size_t bufLen, unw_word_t *offset) { - _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p," - "bufLen=%zu)\n", cursor, buf, bufLen); + _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)\n", + static_cast<void *>(cursor), static_cast<void *>(buf), + static_cast<unsigned long>(bufLen)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->getFunctionName(buf, bufLen, offset)) return UNW_ESUCCESS; @@ -264,7 +270,7 @@ _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, /// Checks if a register is a floating-point register. _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n", - cursor, regNum); + static_cast<void *>(cursor), regNum); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->validFloatReg(regNum); } @@ -274,7 +280,7 @@ _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, unw_regnum_t regNum) { _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n", - cursor, regNum); + static_cast<void *>(cursor), regNum); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->getRegisterName(regNum); } @@ -282,15 +288,17 @@ _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, /// Checks if current frame is signal trampoline. _LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n", cursor); + _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n", + static_cast<void *>(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->isSignalFrame(); } -#if __arm__ +#ifdef __arm__ // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n", cursor); + _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n", + static_cast<void *>(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->saveVFPAsX(); } @@ -301,7 +309,8 @@ _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { /// SPI: walks cached dwarf entries _LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)( unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { - _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", func); + _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", + reinterpret_cast<void *>(func)); DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func); } diff --git a/src/abort_message.cpp b/src/abort_message.cpp index 7702904..5e25c0f 100644 --- a/src/abort_message.cpp +++ b/src/abort_message.cpp @@ -24,9 +24,9 @@ extern "C" void android_set_abort_message(const char* msg); #pragma GCC visibility push(hidden) -#if __APPLE__ +#ifdef __APPLE__ # if defined(__has_include) && __has_include(<CrashReporterClient.h>) -# define HAVE_CRASHREPORTERCLIENT_H 1 +# define HAVE_CRASHREPORTERCLIENT_H # include <CrashReporterClient.h> # endif #endif @@ -35,7 +35,7 @@ __attribute__((visibility("hidden"), noreturn)) void abort_message(const char* format, ...) { // write message to stderr -#if __APPLE__ +#ifdef __APPLE__ fprintf(stderr, "libc++abi.dylib: "); #endif va_list list; @@ -44,7 +44,7 @@ void abort_message(const char* format, ...) va_end(list); fprintf(stderr, "\n"); -#if __APPLE__ && HAVE_CRASHREPORTERCLIENT_H +#if defined(__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) // record message in crash report char* buffer; va_list list2; @@ -52,7 +52,7 @@ void abort_message(const char* format, ...) vasprintf(&buffer, format, list2); va_end(list2); CRSetCrashLogMessage(buffer); -#elif __BIONIC__ +#elif defined(__BIONIC__) char* buffer; va_list list2; va_start(list2, format); diff --git a/src/cxa_exception.cpp b/src/cxa_exception.cpp index e9f5e6e..b7a33d7 100644 --- a/src/cxa_exception.cpp +++ b/src/cxa_exception.cpp @@ -234,7 +234,7 @@ __cxa_throw(void* thrown_object, std::type_info* tinfo, void (*dest)(void*)) globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local exception_header->unwindHeader.exception_cleanup = exception_cleanup_func; -#if __USING_SJLJ_EXCEPTIONS__ +#ifdef __USING_SJLJ_EXCEPTIONS__ _Unwind_SjLj_RaiseException(&exception_header->unwindHeader); #else _Unwind_RaiseException(&exception_header->unwindHeader); @@ -258,12 +258,10 @@ __cxa_get_exception_ptr(void* unwind_exception) throw() { #if LIBCXXABI_ARM_EHABI return reinterpret_cast<void*>( - static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]); + static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]); #else - return cxa_exception_from_exception_unwind_exception - ( - static_cast<_Unwind_Exception*>(unwind_exception) - )->adjustedPtr; + return cxa_exception_from_exception_unwind_exception( + static_cast<_Unwind_Exception*>(unwind_exception))->adjustedPtr; #endif } @@ -571,7 +569,7 @@ __cxa_rethrow() // nothing globals->caughtExceptions = 0; } -#if __USING_SJLJ_EXCEPTIONS__ +#ifdef __USING_SJLJ_EXCEPTIONS__ _Unwind_SjLj_RaiseException(&exception_header->unwindHeader); #else _Unwind_RaiseException(&exception_header->unwindHeader); @@ -700,7 +698,7 @@ __cxa_rethrow_primary_exception(void* thrown_object) setDependentExceptionClass(&dep_exception_header->unwindHeader); __cxa_get_globals()->uncaughtExceptions += 1; dep_exception_header->unwindHeader.exception_cleanup = dependent_exception_cleanup; -#if __USING_SJLJ_EXCEPTIONS__ +#ifdef __USING_SJLJ_EXCEPTIONS__ _Unwind_SjLj_RaiseException(&dep_exception_header->unwindHeader); #else _Unwind_RaiseException(&dep_exception_header->unwindHeader); diff --git a/src/cxa_exception.hpp b/src/cxa_exception.hpp index 9b22ce3..6e68f98 100644 --- a/src/cxa_exception.hpp +++ b/src/cxa_exception.hpp @@ -24,20 +24,20 @@ namespace __cxxabiv1 { static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC++\0 static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1 -static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++ - -struct __cxa_exception { -#if __LP64__ || LIBCXXABI_ARM_EHABI +static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++ + +struct __cxa_exception { +#if defined(__LP64__) || LIBCXXABI_ARM_EHABI // This is a new field to support C++ 0x exception_ptr. // For binary compatibility it is at the start of this // struct which is prepended to the object thrown in // __cxa_allocate_exception. size_t referenceCount; #endif - + // Manage the exception object itself. std::type_info *exceptionType; - void (*exceptionDestructor)(void *); + void (*exceptionDestructor)(void *); std::unexpected_handler unexpectedHandler; std::terminate_handler terminateHandler; @@ -56,7 +56,7 @@ struct __cxa_exception { void *adjustedPtr; #endif -#if !__LP64__ && !LIBCXXABI_ARM_EHABI +#if !defined(__LP64__) && !LIBCXXABI_ARM_EHABI // This is a new field to support C++ 0x exception_ptr. // For binary compatibility it is placed where the compiler // previously adding padded to 64-bit align unwindHeader. @@ -70,19 +70,19 @@ struct __cxa_exception { // The layout of this structure MUST match the layout of __cxa_exception, with // primaryException instead of referenceCount. struct __cxa_dependent_exception { -#if __LP64__ || LIBCXXABI_ARM_EHABI +#if defined(__LP64__) || LIBCXXABI_ARM_EHABI void* primaryException; #endif - + std::type_info *exceptionType; - void (*exceptionDestructor)(void *); + void (*exceptionDestructor)(void *); std::unexpected_handler unexpectedHandler; std::terminate_handler terminateHandler; __cxa_exception *nextException; int handlerCount; - + #if LIBCXXABI_ARM_EHABI __cxa_exception* nextPropagatingException; int propagationCount; @@ -93,8 +93,8 @@ struct __cxa_dependent_exception { void * catchTemp; void *adjustedPtr; #endif - -#if !__LP64__ && !LIBCXXABI_ARM_EHABI + +#if !defined(__LP64__) && !LIBCXXABI_ARM_EHABI void* primaryException; #endif diff --git a/src/cxa_guard.cpp b/src/cxa_guard.cpp index 5372a5c..1b41917 100644 --- a/src/cxa_guard.cpp +++ b/src/cxa_guard.cpp @@ -31,7 +31,7 @@ namespace __cxxabiv1 namespace { -#if __arm__ +#ifdef __arm__ // A 32-bit, 4-byte-aligned static data value. The least significant 2 bits must // be statically initialized to 0. diff --git a/src/cxa_personality.cpp b/src/cxa_personality.cpp index 51f4a09..3ea8ca3 100644 --- a/src/cxa_personality.cpp +++ b/src/cxa_personality.cpp @@ -55,7 +55,7 @@ +------------------+--+-----+-----+------------------------+--------------------------+ | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table | +---------------------+-----------+---------------------------------------------------+ -#if !__USING_SJLJ_EXCEPTIONS__ +#ifndef __USING_SJLJ_EXCEPTIONS__ +---------------------+-----------+------------------------------------------------+ | Beginning of Call Site Table The current ip lies within the | | ... (start, length) range of one of these | @@ -595,7 +595,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Get beginning current frame's code (as defined by the // emitted dwarf code) uintptr_t funcStart = _Unwind_GetRegionStart(context); -#if __USING_SJLJ_EXCEPTIONS__ +#ifdef __USING_SJLJ_EXCEPTIONS__ if (ip == uintptr_t(-1)) { // no action @@ -628,7 +628,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Walk call-site table looking for range that // includes current PC. uint8_t callSiteEncoding = *lsda++; -#if __USING_SJLJ_EXCEPTIONS__ +#ifdef __USING_SJLJ_EXCEPTIONS__ (void)callSiteEncoding; // When using SjLj exceptions, callSiteEncoding is never used #endif uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda)); @@ -639,7 +639,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, while (callSitePtr < callSiteTableEnd) { // There is one entry per call site. -#if !__USING_SJLJ_EXCEPTIONS__ +#ifndef __USING_SJLJ_EXCEPTIONS__ // The call sites are non-overlapping in [start, start+length) // The call sites are ordered in increasing value of start uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); @@ -655,7 +655,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, #endif // __USING_SJLJ_EXCEPTIONS__ { // Found the call site containing ip. -#if !__USING_SJLJ_EXCEPTIONS__ +#ifndef __USING_SJLJ_EXCEPTIONS__ if (landingPad == 0) { // No handler here @@ -857,7 +857,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, action += actionOffset; } // there is no break out of this loop, only return } -#if !__USING_SJLJ_EXCEPTIONS__ +#ifndef __USING_SJLJ_EXCEPTIONS__ else if (ipOffset < start) { // There is no call site for this ip @@ -923,7 +923,7 @@ _UA_CLEANUP_PHASE #if !LIBCXXABI_ARM_EHABI _Unwind_Reason_Code -#if __USING_SJLJ_EXCEPTIONS__ +#ifdef __USING_SJLJ_EXCEPTIONS__ __gxx_personality_sj0 #else __gxx_personality_v0 @@ -1012,22 +1012,55 @@ __gxx_personality_v0 } #else +#if !LIBCXXABI_USE_LLVM_UNWINDER +extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*, _Unwind_Context*); +#endif + // Helper function to unwind one frame. // ARM EHABI 7.3 and 7.4: If the personality function returns _URC_CONTINUE_UNWIND, the // personality routine should update the virtual register set (VRS) according to the // corresponding frame unwinding instructions (ARM EHABI 9.3.) -static _Unwind_Reason_Code continue_unwind(_Unwind_Context* context, - uint32_t* unwind_opcodes, - size_t opcode_words) +static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception, + _Unwind_Context* context) { +#if LIBCXXABI_USE_LLVM_UNWINDER + // ARM EHABI # 6.2, # 9.2 + // + // +---- ehtp + // v + // +--------------------------------------+ + // | +--------+--------+--------+-------+ | + // | |0| prel31 to __gxx_personality_v0 | | + // | +--------+--------+--------+-------+ | + // | | N | unwind opcodes | | <-- unwind_opcodes + // | +--------+--------+--------+-------+ | + // | | Word 2 unwind opcodes | | + // | +--------+--------+--------+-------+ | + // | ... | + // | +--------+--------+--------+-------+ | + // | | Word N unwind opcodes | | + // | +--------+--------+--------+-------+ | + // | | LSDA | | <-- lsda + // | | ... | | + // | +--------+--------+--------+-------+ | + // +--------------------------------------+ + + uint32_t *unwind_opcodes = unwind_exception->pr_cache.ehtp + 1; + size_t opcode_words = ((*unwind_opcodes >> 24) & 0xff) + 1; if (_Unwind_VRS_Interpret(context, unwind_opcodes, 1, opcode_words * 4) != _URC_CONTINUE_UNWIND) return _URC_FAILURE; +#else + if (__gnu_unwind_frame(unwind_exception, context) != _URC_OK) + return _URC_FAILURE; +#endif return _URC_CONTINUE_UNWIND; } // ARM register names +#if !LIBCXXABI_USE_LLVM_UNWINDER static const uint32_t REG_UCB = 12; // Register to save _Unwind_Control_Block +#endif static const uint32_t REG_SP = 13; static void save_results_to_barrier_cache(_Unwind_Exception* unwind_exception, @@ -1061,42 +1094,23 @@ __gxx_personality_v0(_Unwind_State state, bool native_exception = (unwind_exception->exception_class & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language); -#if LIBCXXABI_ARM_EHABI - // ARM EHABI # 6.2, # 9.2 - // - // +---- ehtp - // v - // +--------------------------------------+ - // | +--------+--------+--------+-------+ | - // | |0| prel31 to __gxx_personality_v0 | | - // | +--------+--------+--------+-------+ | - // | | N | unwind opcodes | | <-- UnwindData - // | +--------+--------+--------+-------+ | - // | | Word 2 unwind opcodes | | - // | +--------+--------+--------+-------+ | - // | ... | - // | +--------+--------+--------+-------+ | - // | | Word N unwind opcodes | | - // | +--------+--------+--------+-------+ | - // | | LSDA | | <-- lsda - // | | ... | | - // | +--------+--------+--------+-------+ | - // +--------------------------------------+ - - uint32_t *UnwindData = unwind_exception->pr_cache.ehtp + 1; - uint32_t FirstDataWord = *UnwindData; - size_t N = ((FirstDataWord >> 24) & 0xff); - size_t NDataWords = N + 1; -#endif - +#if !LIBCXXABI_USE_LLVM_UNWINDER // Copy the address of _Unwind_Control_Block to r12 so that // _Unwind_GetLanguageSpecificData() and _Unwind_GetRegionStart() can // return correct address. _Unwind_SetGR(context, REG_UCB, reinterpret_cast<uint32_t>(unwind_exception)); +#endif + + // Check the undocumented force unwinding behavior + bool is_force_unwinding = state & _US_FORCE_UNWIND; + state &= ~_US_FORCE_UNWIND; scan_results results; switch (state) { case _US_VIRTUAL_UNWIND_FRAME: + if (is_force_unwinding) + return continue_unwind(unwind_exception, context); + // Phase 1 search: All we're looking for in phase 1 is a handler that halts unwinding scan_eh_tab(results, _UA_SEARCH_PHASE, native_exception, unwind_exception, context); if (results.reason == _URC_HANDLER_FOUND) @@ -1108,10 +1122,15 @@ __gxx_personality_v0(_Unwind_State state, } // Did not find the catch handler if (results.reason == _URC_CONTINUE_UNWIND) - return continue_unwind(context, UnwindData, NDataWords); + return continue_unwind(unwind_exception, context); return results.reason; case _US_UNWIND_FRAME_STARTING: + // TODO: Support force unwinding in the phase 2 search. + // NOTE: In order to call the cleanup functions, _Unwind_ForcedUnwind() + // will call this personality function with (_US_FORCE_UNWIND | + // _US_UNWIND_FRAME_STARTING). + // Phase 2 search if (unwind_exception->barrier_cache.sp == _Unwind_GetGR(context, REG_SP)) { @@ -1156,11 +1175,11 @@ __gxx_personality_v0(_Unwind_State state, // Did not find any handler if (results.reason == _URC_CONTINUE_UNWIND) - return continue_unwind(context, UnwindData, NDataWords); + return continue_unwind(unwind_exception, context); return results.reason; case _US_UNWIND_FRAME_RESUME: - return continue_unwind(context, UnwindData, NDataWords); + return continue_unwind(unwind_exception, context); } // We were called improperly: neither a phase 1 or phase 2 search diff --git a/src/private_typeinfo.cpp b/src/private_typeinfo.cpp index 38e70ab..821796f 100644 --- a/src/private_typeinfo.cpp +++ b/src/private_typeinfo.cpp @@ -34,7 +34,7 @@ // // _LIBCXX_DYNAMIC_FALLBACK is currently off by default. -#if _LIBCXX_DYNAMIC_FALLBACK +#ifdef _LIBCXX_DYNAMIC_FALLBACK #include "abort_message.h" #include <string.h> #include <sys/syslog.h> @@ -57,7 +57,7 @@ namespace __cxxabiv1 #pragma GCC visibility push(hidden) -#if _LIBCXX_DYNAMIC_FALLBACK +#ifdef _LIBCXX_DYNAMIC_FALLBACK inline bool @@ -515,7 +515,7 @@ __dynamic_cast(const void* static_ptr, info.number_of_dst_type = 1; // Do the search dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false); -#if _LIBCXX_DYNAMIC_FALLBACK +#ifdef _LIBCXX_DYNAMIC_FALLBACK // 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) @@ -539,7 +539,7 @@ __dynamic_cast(const void* static_ptr, { // Not using giant short cut. Do the search dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false); - #if _LIBCXX_DYNAMIC_FALLBACK + #ifdef _LIBCXX_DYNAMIC_FALLBACK // 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 && |