Index: src/Unwind/AddressSpace.hpp =================================================================== --- src/Unwind/AddressSpace.hpp +++ src/Unwind/AddressSpace.hpp @@ -17,7 +17,10 @@ #include #include #include + +#if !_LIBUNWIND_IS_BAREMETAL #include +#endif #if __APPLE__ #include @@ -40,9 +43,19 @@ // Emulate the BSD dl_unwind_find_exidx API when on a GNU libdl system. #define dl_unwind_find_exidx __gnu_Unwind_Find_exidx -#else +#elif !_LIBUNWIND_IS_BAREMETAL #include -#endif +#else // _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 { + uint32_t functionOffset; + uint32_t unwindOpcodes; +}; +extern EHTEntry __exidx_start; +extern EHTEntry __exidx_end; +#endif // !_LIBUNWIND_IS_BAREMETAL + #endif // LIBCXXABI_ARM_EHABI namespace libunwind { @@ -326,10 +339,16 @@ return true; } #elif LIBCXXABI_ARM_EHABI + #if _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); + #else int length = 0; info.arm_section = (uintptr_t) dl_unwind_find_exidx( (_Unwind_Ptr) targetAddr, &length); info.arm_section_length = (uintptr_t)length; + #endif _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x\n", info.arm_section, info.arm_section_length); if (info.arm_section && info.arm_section_length) @@ -354,6 +373,7 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset) { +#if !_LIBUNWIND_IS_BAREMETAL Dl_info dyldInfo; if (dladdr((void *)addr, &dyldInfo)) { if (dyldInfo.dli_sname != NULL) { @@ -362,6 +382,7 @@ return true; } } +#endif return false; } Index: src/config.h =================================================================== --- src/config.h +++ src/config.h @@ -22,4 +22,11 @@ # define LIBCXXABI_SINGLE_THREADED 1 #endif +// Set this in the CXXFLAGS when you need it, because otherwise we'd have to +// #if !defined(__linux__) && !defined(__APPLE__) && ... +// and so-on for *every* platform. +#ifndef LIBCXXABI_BAREMETAL +# define LIBCXXABI_BAREMETAL 0 +#endif + #endif // LIBCXXABI_CONFIG_H Index: src/cxa_personality.cpp =================================================================== --- src/cxa_personality.cpp +++ src/cxa_personality.cpp @@ -314,8 +314,18 @@ uintptr_t offset = *reinterpret_cast(ptr); if (!offset) return 0; + // "ARM EABI provides a TARGET2 relocation to describe these typeinfo + // pointers. The reason being it allows their precise semantics to be + // deferred to the linker. For bare-metal they turn into absolute + // relocations. For linux they turn into GOT-REL relocations." + // https://gcc.gnu.org/ml/gcc-patches/2009-08/msg00264.html +#if LIBCXXABI_BAREMETAL + return reinterpret_cast(reinterpret_cast(ptr) + + offset); +#else return *reinterpret_cast(reinterpret_cast(ptr) + offset); +#endif } static const __shim_type_info*