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