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