1 //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===// 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/LazyReexports.h" 11 12 #include "llvm/ADT/Triple.h" 13 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h" 14 15 #define DEBUG_TYPE "orc" 16 17 namespace llvm { 18 namespace orc { 19 20 void LazyCallThroughManager::NotifyResolvedFunction::anchor() {} 21 22 LazyCallThroughManager::LazyCallThroughManager( 23 ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, 24 std::unique_ptr<TrampolinePool> TP) 25 : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {} 26 27 Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline( 28 JITDylib &SourceJD, SymbolStringPtr SymbolName, 29 std::shared_ptr<NotifyResolvedFunction> NotifyResolved) { 30 std::lock_guard<std::mutex> Lock(LCTMMutex); 31 auto Trampoline = TP->getTrampoline(); 32 33 if (!Trampoline) 34 return Trampoline.takeError(); 35 36 Reexports[*Trampoline] = std::make_pair(&SourceJD, std::move(SymbolName)); 37 Notifiers[*Trampoline] = std::move(NotifyResolved); 38 return *Trampoline; 39 } 40 41 JITTargetAddress 42 LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) { 43 JITDylib *SourceJD = nullptr; 44 SymbolStringPtr SymbolName; 45 46 { 47 std::lock_guard<std::mutex> Lock(LCTMMutex); 48 auto I = Reexports.find(TrampolineAddr); 49 if (I == Reexports.end()) 50 return ErrorHandlerAddr; 51 SourceJD = I->second.first; 52 SymbolName = I->second.second; 53 } 54 55 auto LookupResult = ES.lookup(JITDylibSearchList({{SourceJD, true}}), 56 {SymbolName}, NoDependenciesToRegister, true); 57 58 if (!LookupResult) { 59 ES.reportError(LookupResult.takeError()); 60 return ErrorHandlerAddr; 61 } 62 63 assert(LookupResult->size() == 1 && "Unexpected number of results"); 64 assert(LookupResult->count(SymbolName) && "Unexpected result"); 65 66 auto ResolvedAddr = LookupResult->begin()->second.getAddress(); 67 68 std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr; 69 { 70 std::lock_guard<std::mutex> Lock(LCTMMutex); 71 auto I = Notifiers.find(TrampolineAddr); 72 if (I != Notifiers.end()) { 73 NotifyResolved = I->second; 74 Notifiers.erase(I); 75 } 76 } 77 78 if (NotifyResolved) { 79 if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) { 80 ES.reportError(std::move(Err)); 81 return ErrorHandlerAddr; 82 } 83 } 84 85 return ResolvedAddr; 86 } 87 88 Expected<std::unique_ptr<LazyCallThroughManager>> 89 createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES, 90 JITTargetAddress ErrorHandlerAddr) { 91 switch (T.getArch()) { 92 default: 93 return make_error<StringError>( 94 std::string("No callback manager available for ") + T.str(), 95 inconvertibleErrorCode()); 96 97 case Triple::aarch64: 98 return LocalLazyCallThroughManager::Create<OrcAArch64>(ES, 99 ErrorHandlerAddr); 100 101 case Triple::x86: 102 return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr); 103 104 case Triple::mips: 105 return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES, 106 ErrorHandlerAddr); 107 108 case Triple::mipsel: 109 return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES, 110 ErrorHandlerAddr); 111 112 case Triple::mips64: 113 case Triple::mips64el: 114 return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr); 115 116 case Triple::x86_64: 117 if (T.getOS() == Triple::OSType::Win32) 118 return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>( 119 ES, ErrorHandlerAddr); 120 else 121 return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>( 122 ES, ErrorHandlerAddr); 123 } 124 } 125 126 LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit( 127 LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, 128 JITDylib &SourceJD, SymbolAliasMap CallableAliases, VModuleKey K) 129 : MaterializationUnit(extractFlags(CallableAliases), std::move(K)), 130 LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD), 131 CallableAliases(std::move(CallableAliases)), 132 NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction( 133 [&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName, 134 JITTargetAddress ResolvedAddr) { 135 return ISManager.updatePointer(*SymbolName, ResolvedAddr); 136 })) {} 137 138 StringRef LazyReexportsMaterializationUnit::getName() const { 139 return "<Lazy Reexports>"; 140 } 141 142 void LazyReexportsMaterializationUnit::materialize( 143 MaterializationResponsibility R) { 144 auto RequestedSymbols = R.getRequestedSymbols(); 145 146 SymbolAliasMap RequestedAliases; 147 for (auto &RequestedSymbol : RequestedSymbols) { 148 auto I = CallableAliases.find(RequestedSymbol); 149 assert(I != CallableAliases.end() && "Symbol not found in alias map?"); 150 RequestedAliases[I->first] = std::move(I->second); 151 CallableAliases.erase(I); 152 } 153 154 if (!CallableAliases.empty()) 155 R.replace(lazyReexports(LCTManager, ISManager, SourceJD, 156 std::move(CallableAliases))); 157 158 IndirectStubsManager::StubInitsMap StubInits; 159 for (auto &Alias : RequestedAliases) { 160 161 auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline( 162 SourceJD, Alias.second.Aliasee, NotifyResolved); 163 164 if (!CallThroughTrampoline) { 165 SourceJD.getExecutionSession().reportError( 166 CallThroughTrampoline.takeError()); 167 R.failMaterialization(); 168 return; 169 } 170 171 StubInits[*Alias.first] = 172 std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags); 173 } 174 175 if (auto Err = ISManager.createStubs(StubInits)) { 176 SourceJD.getExecutionSession().reportError(std::move(Err)); 177 R.failMaterialization(); 178 return; 179 } 180 181 SymbolMap Stubs; 182 for (auto &Alias : RequestedAliases) 183 Stubs[Alias.first] = ISManager.findStub(*Alias.first, false); 184 185 R.resolve(Stubs); 186 R.emit(); 187 } 188 189 void LazyReexportsMaterializationUnit::discard(const JITDylib &JD, 190 const SymbolStringPtr &Name) { 191 assert(CallableAliases.count(Name) && 192 "Symbol not covered by this MaterializationUnit"); 193 CallableAliases.erase(Name); 194 } 195 196 SymbolFlagsMap 197 LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) { 198 SymbolFlagsMap SymbolFlags; 199 for (auto &KV : Aliases) { 200 assert(KV.second.AliasFlags.isCallable() && 201 "Lazy re-exports must be callable symbols"); 202 SymbolFlags[KV.first] = KV.second.AliasFlags; 203 } 204 return SymbolFlags; 205 } 206 207 } // End namespace orc. 208 } // End namespace llvm. 209