1e8d8bef9SDimitry Andric //===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // The LLVM Compiler Infrastructure 4e8d8bef9SDimitry Andric // 5e8d8bef9SDimitry Andric // This file is distributed under the University of Illinois Open Source 6e8d8bef9SDimitry Andric // License. See LICENSE.TXT for details. 7e8d8bef9SDimitry Andric // 8e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 9e8d8bef9SDimitry Andric 10e8d8bef9SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" 11e8d8bef9SDimitry Andric 12e8d8bef9SDimitry Andric #include "llvm/Config/config.h" 13e8d8bef9SDimitry Andric #include "llvm/ExecutionEngine/JITSymbol.h" 14e8d8bef9SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 15e8d8bef9SDimitry Andric #include "llvm/Support/Compiler.h" 16e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h" 17e8d8bef9SDimitry Andric #include "llvm/Support/DynamicLibrary.h" 18e8d8bef9SDimitry Andric #include "llvm/Support/raw_ostream.h" 19e8d8bef9SDimitry Andric 20e8d8bef9SDimitry Andric #include "llvm/Support/FormatVariadic.h" 21e8d8bef9SDimitry Andric 22e8d8bef9SDimitry Andric #define DEBUG_TYPE "orc" 23e8d8bef9SDimitry Andric 24e8d8bef9SDimitry Andric using namespace llvm; 25e8d8bef9SDimitry Andric using namespace llvm::orc; 26*fe6060f1SDimitry Andric using namespace llvm::orc::shared; 27e8d8bef9SDimitry Andric 28e8d8bef9SDimitry Andric namespace llvm { 29e8d8bef9SDimitry Andric namespace orc { 30e8d8bef9SDimitry Andric 31e8d8bef9SDimitry Andric #if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \ 32e8d8bef9SDimitry Andric !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) 33e8d8bef9SDimitry Andric 34e8d8bef9SDimitry Andric extern "C" void __register_frame(const void *); 35e8d8bef9SDimitry Andric extern "C" void __deregister_frame(const void *); 36e8d8bef9SDimitry Andric 37e8d8bef9SDimitry Andric Error registerFrameWrapper(const void *P) { 38e8d8bef9SDimitry Andric __register_frame(P); 39e8d8bef9SDimitry Andric return Error::success(); 40e8d8bef9SDimitry Andric } 41e8d8bef9SDimitry Andric 42e8d8bef9SDimitry Andric Error deregisterFrameWrapper(const void *P) { 43e8d8bef9SDimitry Andric __deregister_frame(P); 44e8d8bef9SDimitry Andric return Error::success(); 45e8d8bef9SDimitry Andric } 46e8d8bef9SDimitry Andric 47e8d8bef9SDimitry Andric #else 48e8d8bef9SDimitry Andric 49e8d8bef9SDimitry Andric // The building compiler does not have __(de)register_frame but 50e8d8bef9SDimitry Andric // it may be found at runtime in a dynamically-loaded library. 51e8d8bef9SDimitry Andric // For example, this happens when building LLVM with Visual C++ 52e8d8bef9SDimitry Andric // but using the MingW runtime. 53e8d8bef9SDimitry Andric static Error registerFrameWrapper(const void *P) { 54e8d8bef9SDimitry Andric static void((*RegisterFrame)(const void *)) = 0; 55e8d8bef9SDimitry Andric 56e8d8bef9SDimitry Andric if (!RegisterFrame) 57e8d8bef9SDimitry Andric *(void **)&RegisterFrame = 58e8d8bef9SDimitry Andric llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame"); 59e8d8bef9SDimitry Andric 60e8d8bef9SDimitry Andric if (RegisterFrame) { 61e8d8bef9SDimitry Andric RegisterFrame(P); 62e8d8bef9SDimitry Andric return Error::success(); 63e8d8bef9SDimitry Andric } 64e8d8bef9SDimitry Andric 65e8d8bef9SDimitry Andric return make_error<StringError>("could not register eh-frame: " 66e8d8bef9SDimitry Andric "__register_frame function not found", 67e8d8bef9SDimitry Andric inconvertibleErrorCode()); 68e8d8bef9SDimitry Andric } 69e8d8bef9SDimitry Andric 70e8d8bef9SDimitry Andric static Error deregisterFrameWrapper(const void *P) { 71e8d8bef9SDimitry Andric static void((*DeregisterFrame)(const void *)) = 0; 72e8d8bef9SDimitry Andric 73e8d8bef9SDimitry Andric if (!DeregisterFrame) 74e8d8bef9SDimitry Andric *(void **)&DeregisterFrame = 75e8d8bef9SDimitry Andric llvm::sys::DynamicLibrary::SearchForAddressOfSymbol( 76e8d8bef9SDimitry Andric "__deregister_frame"); 77e8d8bef9SDimitry Andric 78e8d8bef9SDimitry Andric if (DeregisterFrame) { 79e8d8bef9SDimitry Andric DeregisterFrame(P); 80e8d8bef9SDimitry Andric return Error::success(); 81e8d8bef9SDimitry Andric } 82e8d8bef9SDimitry Andric 83e8d8bef9SDimitry Andric return make_error<StringError>("could not deregister eh-frame: " 84e8d8bef9SDimitry Andric "__deregister_frame function not found", 85e8d8bef9SDimitry Andric inconvertibleErrorCode()); 86e8d8bef9SDimitry Andric } 87e8d8bef9SDimitry Andric #endif 88e8d8bef9SDimitry Andric 89e8d8bef9SDimitry Andric #ifdef __APPLE__ 90e8d8bef9SDimitry Andric 91e8d8bef9SDimitry Andric template <typename HandleFDEFn> 92e8d8bef9SDimitry Andric Error walkAppleEHFrameSection(const char *const SectionStart, 93e8d8bef9SDimitry Andric size_t SectionSize, HandleFDEFn HandleFDE) { 94e8d8bef9SDimitry Andric const char *CurCFIRecord = SectionStart; 95e8d8bef9SDimitry Andric const char *End = SectionStart + SectionSize; 96e8d8bef9SDimitry Andric uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); 97e8d8bef9SDimitry Andric 98e8d8bef9SDimitry Andric while (CurCFIRecord != End && Size != 0) { 99e8d8bef9SDimitry Andric const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4); 100e8d8bef9SDimitry Andric if (Size == 0xffffffff) 101e8d8bef9SDimitry Andric Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12; 102e8d8bef9SDimitry Andric else 103e8d8bef9SDimitry Andric Size += 4; 104e8d8bef9SDimitry Andric uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField); 105e8d8bef9SDimitry Andric 106e8d8bef9SDimitry Andric LLVM_DEBUG({ 107e8d8bef9SDimitry Andric dbgs() << "Registering eh-frame section:\n"; 108e8d8bef9SDimitry Andric dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @" 109e8d8bef9SDimitry Andric << (void *)CurCFIRecord << ": ["; 110e8d8bef9SDimitry Andric for (unsigned I = 0; I < Size; ++I) 111e8d8bef9SDimitry Andric dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I)); 112e8d8bef9SDimitry Andric dbgs() << " ]\n"; 113e8d8bef9SDimitry Andric }); 114e8d8bef9SDimitry Andric 115e8d8bef9SDimitry Andric if (Offset != 0) 116e8d8bef9SDimitry Andric if (auto Err = HandleFDE(CurCFIRecord)) 117e8d8bef9SDimitry Andric return Err; 118e8d8bef9SDimitry Andric 119e8d8bef9SDimitry Andric CurCFIRecord += Size; 120e8d8bef9SDimitry Andric 121e8d8bef9SDimitry Andric Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); 122e8d8bef9SDimitry Andric } 123e8d8bef9SDimitry Andric 124e8d8bef9SDimitry Andric return Error::success(); 125e8d8bef9SDimitry Andric } 126e8d8bef9SDimitry Andric 127e8d8bef9SDimitry Andric #endif // __APPLE__ 128e8d8bef9SDimitry Andric 129e8d8bef9SDimitry Andric Error registerEHFrameSection(const void *EHFrameSectionAddr, 130e8d8bef9SDimitry Andric size_t EHFrameSectionSize) { 131e8d8bef9SDimitry Andric #ifdef __APPLE__ 132e8d8bef9SDimitry Andric // On Darwin __register_frame has to be called for each FDE entry. 133e8d8bef9SDimitry Andric return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr), 134e8d8bef9SDimitry Andric EHFrameSectionSize, registerFrameWrapper); 135e8d8bef9SDimitry Andric #else 136e8d8bef9SDimitry Andric // On Linux __register_frame takes a single argument: 137e8d8bef9SDimitry Andric // a pointer to the start of the .eh_frame section. 138e8d8bef9SDimitry Andric 139e8d8bef9SDimitry Andric // How can it find the end? Because crtendS.o is linked 140e8d8bef9SDimitry Andric // in and it has an .eh_frame section with four zero chars. 141e8d8bef9SDimitry Andric return registerFrameWrapper(EHFrameSectionAddr); 142e8d8bef9SDimitry Andric #endif 143e8d8bef9SDimitry Andric } 144e8d8bef9SDimitry Andric 145e8d8bef9SDimitry Andric Error deregisterEHFrameSection(const void *EHFrameSectionAddr, 146e8d8bef9SDimitry Andric size_t EHFrameSectionSize) { 147e8d8bef9SDimitry Andric #ifdef __APPLE__ 148e8d8bef9SDimitry Andric return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr), 149e8d8bef9SDimitry Andric EHFrameSectionSize, deregisterFrameWrapper); 150e8d8bef9SDimitry Andric #else 151e8d8bef9SDimitry Andric return deregisterFrameWrapper(EHFrameSectionAddr); 152e8d8bef9SDimitry Andric #endif 153e8d8bef9SDimitry Andric } 154e8d8bef9SDimitry Andric 155e8d8bef9SDimitry Andric } // end namespace orc 156e8d8bef9SDimitry Andric } // end namespace llvm 157e8d8bef9SDimitry Andric 158*fe6060f1SDimitry Andric static Error registerEHFrameWrapper(JITTargetAddress Addr, uint64_t Size) { 159*fe6060f1SDimitry Andric return llvm::orc::registerEHFrameSection( 160*fe6060f1SDimitry Andric jitTargetAddressToPointer<const void *>(Addr), Size); 161*fe6060f1SDimitry Andric } 162*fe6060f1SDimitry Andric 163*fe6060f1SDimitry Andric static Error deregisterEHFrameWrapper(JITTargetAddress Addr, uint64_t Size) { 164*fe6060f1SDimitry Andric return llvm::orc::deregisterEHFrameSection( 165*fe6060f1SDimitry Andric jitTargetAddressToPointer<const void *>(Addr), Size); 166*fe6060f1SDimitry Andric } 167*fe6060f1SDimitry Andric 168*fe6060f1SDimitry Andric extern "C" orc::shared::detail::CWrapperFunctionResult 169*fe6060f1SDimitry Andric llvm_orc_registerEHFrameSectionWrapper(const char *Data, uint64_t Size) { 170*fe6060f1SDimitry Andric return WrapperFunction<SPSError(SPSExecutorAddress, uint64_t)>::handle( 171*fe6060f1SDimitry Andric Data, Size, registerEHFrameWrapper) 172e8d8bef9SDimitry Andric .release(); 173e8d8bef9SDimitry Andric } 174e8d8bef9SDimitry Andric 175*fe6060f1SDimitry Andric extern "C" orc::shared::detail::CWrapperFunctionResult 176*fe6060f1SDimitry Andric llvm_orc_deregisterEHFrameSectionWrapper(const char *Data, uint64_t Size) { 177*fe6060f1SDimitry Andric return WrapperFunction<SPSError(SPSExecutorAddress, uint64_t)>::handle( 178*fe6060f1SDimitry Andric Data, Size, deregisterEHFrameWrapper) 179e8d8bef9SDimitry Andric .release(); 180e8d8bef9SDimitry Andric } 181