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