1 //===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <memory> 10 11 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 12 #include "llvm/Object/COFF.h" 13 14 namespace { 15 16 using namespace llvm; 17 using namespace llvm::orc; 18 19 class JITDylibSearchOrderResolver : public JITSymbolResolver { 20 public: 21 JITDylibSearchOrderResolver(MaterializationResponsibility &MR, 22 SymbolDependenceMap &Deps) 23 : MR(MR), Deps(Deps) {} 24 25 void lookup(const LookupSet &Symbols, 26 OnResolvedFunction OnResolved) override { 27 auto &ES = MR.getTargetJITDylib().getExecutionSession(); 28 SymbolLookupSet InternedSymbols; 29 30 // Intern the requested symbols: lookup takes interned strings. 31 for (auto &S : Symbols) 32 InternedSymbols.add(ES.intern(S)); 33 34 // Build an OnResolve callback to unwrap the interned strings and pass them 35 // to the OnResolved callback. 36 auto OnResolvedWithUnwrap = 37 [OnResolved = std::move(OnResolved)]( 38 Expected<SymbolMap> InternedResult) mutable { 39 if (!InternedResult) { 40 OnResolved(InternedResult.takeError()); 41 return; 42 } 43 44 LookupResult Result; 45 for (auto &KV : *InternedResult) 46 Result[*KV.first] = {KV.second.getAddress().getValue(), 47 KV.second.getFlags()}; 48 OnResolved(Result); 49 }; 50 51 JITDylibSearchOrder LinkOrder; 52 MR.getTargetJITDylib().withLinkOrderDo( 53 [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 54 ES.lookup( 55 LookupKind::Static, LinkOrder, InternedSymbols, SymbolState::Resolved, 56 std::move(OnResolvedWithUnwrap), 57 [this](const SymbolDependenceMap &LookupDeps) { Deps = LookupDeps; }); 58 } 59 60 Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override { 61 LookupSet Result; 62 63 for (auto &KV : MR.getSymbols()) { 64 if (Symbols.count(*KV.first)) 65 Result.insert(*KV.first); 66 } 67 68 return Result; 69 } 70 71 private: 72 MaterializationResponsibility &MR; 73 SymbolDependenceMap &Deps; 74 }; 75 76 } // end anonymous namespace 77 78 namespace llvm { 79 namespace orc { 80 81 char RTDyldObjectLinkingLayer::ID; 82 83 using BaseT = RTTIExtends<RTDyldObjectLinkingLayer, ObjectLayer>; 84 85 RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer( 86 ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager) 87 : BaseT(ES), GetMemoryManager(std::move(GetMemoryManager)) { 88 ES.registerResourceManager(*this); 89 } 90 91 RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() { 92 assert(MemMgrs.empty() && 93 "Layer destroyed with resources still attached" 94 "(ExecutionSession::endSession() must be called prior to " 95 "destruction)"); 96 } 97 98 void RTDyldObjectLinkingLayer::emit( 99 std::unique_ptr<MaterializationResponsibility> R, 100 std::unique_ptr<MemoryBuffer> O) { 101 assert(O && "Object must not be null"); 102 103 auto &ES = getExecutionSession(); 104 105 auto Obj = object::ObjectFile::createObjectFile(*O); 106 107 if (!Obj) { 108 getExecutionSession().reportError(Obj.takeError()); 109 R->failMaterialization(); 110 return; 111 } 112 113 // Collect the internal symbols from the object file: We will need to 114 // filter these later. 115 auto InternalSymbols = std::make_shared<std::set<StringRef>>(); 116 { 117 SymbolFlagsMap ExtraSymbolsToClaim; 118 for (auto &Sym : (*Obj)->symbols()) { 119 120 // Skip file symbols. 121 if (auto SymType = Sym.getType()) { 122 if (*SymType == object::SymbolRef::ST_File) 123 continue; 124 } else { 125 ES.reportError(SymType.takeError()); 126 R->failMaterialization(); 127 return; 128 } 129 130 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 131 if (!SymFlagsOrErr) { 132 // TODO: Test this error. 133 ES.reportError(SymFlagsOrErr.takeError()); 134 R->failMaterialization(); 135 return; 136 } 137 138 // Try to claim responsibility of weak symbols 139 // if AutoClaimObjectSymbols flag is set. 140 if (AutoClaimObjectSymbols && 141 (*SymFlagsOrErr & object::BasicSymbolRef::SF_Weak)) { 142 auto SymName = Sym.getName(); 143 if (!SymName) { 144 ES.reportError(SymName.takeError()); 145 R->failMaterialization(); 146 return; 147 } 148 149 // Already included in responsibility set, skip it 150 SymbolStringPtr SymbolName = ES.intern(*SymName); 151 if (R->getSymbols().count(SymbolName)) 152 continue; 153 154 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 155 if (!SymFlags) { 156 ES.reportError(SymFlags.takeError()); 157 R->failMaterialization(); 158 return; 159 } 160 161 ExtraSymbolsToClaim[SymbolName] = *SymFlags; 162 continue; 163 } 164 165 // Don't include symbols that aren't global. 166 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) { 167 if (auto SymName = Sym.getName()) 168 InternalSymbols->insert(*SymName); 169 else { 170 ES.reportError(SymName.takeError()); 171 R->failMaterialization(); 172 return; 173 } 174 } 175 } 176 177 if (!ExtraSymbolsToClaim.empty()) { 178 if (auto Err = R->defineMaterializing(ExtraSymbolsToClaim)) { 179 ES.reportError(std::move(Err)); 180 R->failMaterialization(); 181 } 182 } 183 } 184 185 auto MemMgr = GetMemoryManager(*O); 186 auto &MemMgrRef = *MemMgr; 187 188 // Switch to shared ownership of MR so that it can be captured by both 189 // lambdas below. 190 std::shared_ptr<MaterializationResponsibility> SharedR(std::move(R)); 191 auto Deps = std::make_unique<SymbolDependenceMap>(); 192 193 auto Resolver = 194 std::make_unique<JITDylibSearchOrderResolver>(*SharedR, *Deps); 195 auto *ResolverPtr = Resolver.get(); 196 197 jitLinkForORC( 198 object::OwningBinary<object::ObjectFile>(std::move(*Obj), std::move(O)), 199 MemMgrRef, *ResolverPtr, ProcessAllSections, 200 [this, SharedR, &MemMgrRef, InternalSymbols]( 201 const object::ObjectFile &Obj, 202 RuntimeDyld::LoadedObjectInfo &LoadedObjInfo, 203 std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) { 204 return onObjLoad(*SharedR, Obj, MemMgrRef, LoadedObjInfo, 205 ResolvedSymbols, *InternalSymbols); 206 }, 207 [this, SharedR, MemMgr = std::move(MemMgr), Deps = std::move(Deps), 208 Resolver = std::move(Resolver)]( 209 object::OwningBinary<object::ObjectFile> Obj, 210 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, 211 Error Err) mutable { 212 onObjEmit(*SharedR, std::move(Obj), std::move(MemMgr), 213 std::move(LoadedObjInfo), std::move(Deps), std::move(Err)); 214 }); 215 } 216 217 void RTDyldObjectLinkingLayer::registerJITEventListener(JITEventListener &L) { 218 std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); 219 assert(!llvm::is_contained(EventListeners, &L) && 220 "Listener has already been registered"); 221 EventListeners.push_back(&L); 222 } 223 224 void RTDyldObjectLinkingLayer::unregisterJITEventListener(JITEventListener &L) { 225 std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); 226 auto I = llvm::find(EventListeners, &L); 227 assert(I != EventListeners.end() && "Listener not registered"); 228 EventListeners.erase(I); 229 } 230 231 Error RTDyldObjectLinkingLayer::onObjLoad( 232 MaterializationResponsibility &R, const object::ObjectFile &Obj, 233 RuntimeDyld::MemoryManager &MemMgr, 234 RuntimeDyld::LoadedObjectInfo &LoadedObjInfo, 235 std::map<StringRef, JITEvaluatedSymbol> Resolved, 236 std::set<StringRef> &InternalSymbols) { 237 SymbolFlagsMap ExtraSymbolsToClaim; 238 SymbolMap Symbols; 239 240 // Hack to support COFF constant pool comdats introduced during compilation: 241 // (See http://llvm.org/PR40074) 242 if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Obj)) { 243 auto &ES = getExecutionSession(); 244 245 // For all resolved symbols that are not already in the responsibility set: 246 // check whether the symbol is in a comdat section and if so mark it as 247 // weak. 248 for (auto &Sym : COFFObj->symbols()) { 249 // getFlags() on COFF symbols can't fail. 250 uint32_t SymFlags = cantFail(Sym.getFlags()); 251 if (SymFlags & object::BasicSymbolRef::SF_Undefined) 252 continue; 253 auto Name = Sym.getName(); 254 if (!Name) 255 return Name.takeError(); 256 auto I = Resolved.find(*Name); 257 258 // Skip unresolved symbols, internal symbols, and symbols that are 259 // already in the responsibility set. 260 if (I == Resolved.end() || InternalSymbols.count(*Name) || 261 R.getSymbols().count(ES.intern(*Name))) 262 continue; 263 auto Sec = Sym.getSection(); 264 if (!Sec) 265 return Sec.takeError(); 266 if (*Sec == COFFObj->section_end()) 267 continue; 268 auto &COFFSec = *COFFObj->getCOFFSection(**Sec); 269 if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) 270 I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak); 271 } 272 273 // Handle any aliases. 274 for (auto &Sym : COFFObj->symbols()) { 275 uint32_t SymFlags = cantFail(Sym.getFlags()); 276 if (SymFlags & object::BasicSymbolRef::SF_Undefined) 277 continue; 278 auto Name = Sym.getName(); 279 if (!Name) 280 return Name.takeError(); 281 auto I = Resolved.find(*Name); 282 283 // Skip already-resolved symbols, and symbols that we're not responsible 284 // for. 285 if (I != Resolved.end() || !R.getSymbols().count(ES.intern(*Name))) 286 continue; 287 288 // Skip anything other than weak externals. 289 auto COFFSym = COFFObj->getCOFFSymbol(Sym); 290 if (!COFFSym.isWeakExternal()) 291 continue; 292 auto *WeakExternal = COFFSym.getAux<object::coff_aux_weak_external>(); 293 if (WeakExternal->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS) 294 continue; 295 296 // We found an alias. Reuse the resolution of the alias target for the 297 // alias itself. 298 Expected<object::COFFSymbolRef> TargetSymbol = 299 COFFObj->getSymbol(WeakExternal->TagIndex); 300 if (!TargetSymbol) 301 return TargetSymbol.takeError(); 302 Expected<StringRef> TargetName = COFFObj->getSymbolName(*TargetSymbol); 303 if (!TargetName) 304 return TargetName.takeError(); 305 auto J = Resolved.find(*TargetName); 306 if (J == Resolved.end()) 307 return make_error<StringError>("Could alias target " + *TargetName + 308 " not resolved", 309 inconvertibleErrorCode()); 310 Resolved[*Name] = J->second; 311 } 312 } 313 314 for (auto &KV : Resolved) { 315 // Scan the symbols and add them to the Symbols map for resolution. 316 317 // We never claim internal symbols. 318 if (InternalSymbols.count(KV.first)) 319 continue; 320 321 auto InternedName = getExecutionSession().intern(KV.first); 322 auto Flags = KV.second.getFlags(); 323 auto I = R.getSymbols().find(InternedName); 324 if (I != R.getSymbols().end()) { 325 // Override object flags and claim responsibility for symbols if 326 // requested. 327 if (OverrideObjectFlags) 328 Flags = I->second; 329 else { 330 // RuntimeDyld/MCJIT's weak tracking isn't compatible with ORC's. Even 331 // if we're not overriding flags in general we should set the weak flag 332 // according to the MaterializationResponsibility object symbol table. 333 if (I->second.isWeak()) 334 Flags |= JITSymbolFlags::Weak; 335 } 336 } else if (AutoClaimObjectSymbols) 337 ExtraSymbolsToClaim[InternedName] = Flags; 338 339 Symbols[InternedName] = {ExecutorAddr(KV.second.getAddress()), Flags}; 340 } 341 342 if (!ExtraSymbolsToClaim.empty()) { 343 if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim)) 344 return Err; 345 346 // If we claimed responsibility for any weak symbols but were rejected then 347 // we need to remove them from the resolved set. 348 for (auto &KV : ExtraSymbolsToClaim) 349 if (KV.second.isWeak() && !R.getSymbols().count(KV.first)) 350 Symbols.erase(KV.first); 351 } 352 353 if (auto Err = R.notifyResolved(Symbols)) { 354 R.failMaterialization(); 355 return Err; 356 } 357 358 if (NotifyLoaded) 359 NotifyLoaded(R, Obj, LoadedObjInfo); 360 361 return Error::success(); 362 } 363 364 void RTDyldObjectLinkingLayer::onObjEmit( 365 MaterializationResponsibility &R, 366 object::OwningBinary<object::ObjectFile> O, 367 std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr, 368 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, 369 std::unique_ptr<SymbolDependenceMap> Deps, Error Err) { 370 if (Err) { 371 getExecutionSession().reportError(std::move(Err)); 372 R.failMaterialization(); 373 return; 374 } 375 376 SymbolDependenceGroup SDG; 377 for (auto &[Sym, Flags] : R.getSymbols()) 378 SDG.Symbols.insert(Sym); 379 SDG.Dependencies = std::move(*Deps); 380 381 if (auto Err = R.notifyEmitted(SDG)) { 382 getExecutionSession().reportError(std::move(Err)); 383 R.failMaterialization(); 384 return; 385 } 386 387 std::unique_ptr<object::ObjectFile> Obj; 388 std::unique_ptr<MemoryBuffer> ObjBuffer; 389 std::tie(Obj, ObjBuffer) = O.takeBinary(); 390 391 // Run EventListener notifyLoaded callbacks. 392 { 393 std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); 394 for (auto *L : EventListeners) 395 L->notifyObjectLoaded(pointerToJITTargetAddress(MemMgr.get()), *Obj, 396 *LoadedObjInfo); 397 } 398 399 if (NotifyEmitted) 400 NotifyEmitted(R, std::move(ObjBuffer)); 401 402 if (auto Err = R.withResourceKeyDo( 403 [&](ResourceKey K) { MemMgrs[K].push_back(std::move(MemMgr)); })) { 404 getExecutionSession().reportError(std::move(Err)); 405 R.failMaterialization(); 406 } 407 } 408 409 Error RTDyldObjectLinkingLayer::handleRemoveResources(JITDylib &JD, 410 ResourceKey K) { 411 412 std::vector<MemoryManagerUP> MemMgrsToRemove; 413 414 getExecutionSession().runSessionLocked([&] { 415 auto I = MemMgrs.find(K); 416 if (I != MemMgrs.end()) { 417 std::swap(MemMgrsToRemove, I->second); 418 MemMgrs.erase(I); 419 } 420 }); 421 422 { 423 std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); 424 for (auto &MemMgr : MemMgrsToRemove) { 425 for (auto *L : EventListeners) 426 L->notifyFreeingObject(pointerToJITTargetAddress(MemMgr.get())); 427 MemMgr->deregisterEHFrames(); 428 } 429 } 430 431 return Error::success(); 432 } 433 434 void RTDyldObjectLinkingLayer::handleTransferResources(JITDylib &JD, 435 ResourceKey DstKey, 436 ResourceKey SrcKey) { 437 if (MemMgrs.contains(SrcKey)) { 438 // DstKey may not be in the DenseMap yet, so the following line may resize 439 // the container and invalidate iterators and value references. 440 auto &DstMemMgrs = MemMgrs[DstKey]; 441 auto &SrcMemMgrs = MemMgrs[SrcKey]; 442 DstMemMgrs.reserve(DstMemMgrs.size() + SrcMemMgrs.size()); 443 for (auto &MemMgr : SrcMemMgrs) 444 DstMemMgrs.push_back(std::move(MemMgr)); 445 446 MemMgrs.erase(SrcKey); 447 } 448 } 449 450 } // End namespace orc. 451 } // End namespace llvm. 452