1 //===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===// 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 "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 10 #include "llvm/ExecutionEngine/JITLink/x86_64.h" 11 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h" 12 #include "llvm/ExecutionEngine/Orc/Layer.h" 13 #include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h" 14 #include "llvm/ExecutionEngine/Orc/MachO.h" 15 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 16 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" 17 #include "llvm/IR/Constants.h" 18 #include "llvm/IR/Function.h" 19 #include "llvm/IR/GlobalVariable.h" 20 #include "llvm/IR/Module.h" 21 #include "llvm/MC/TargetRegistry.h" 22 #include "llvm/Object/MachOUniversal.h" 23 #include "llvm/Support/StringSaver.h" 24 #include "llvm/Target/TargetMachine.h" 25 #include <string> 26 27 namespace llvm { 28 namespace orc { 29 30 CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End) 31 : InitList( 32 GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr), 33 I((InitList && End) ? InitList->getNumOperands() : 0) { 34 } 35 36 bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const { 37 assert(InitList == Other.InitList && "Incomparable iterators."); 38 return I == Other.I; 39 } 40 41 bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const { 42 return !(*this == Other); 43 } 44 45 CtorDtorIterator& CtorDtorIterator::operator++() { 46 ++I; 47 return *this; 48 } 49 50 CtorDtorIterator CtorDtorIterator::operator++(int) { 51 CtorDtorIterator Temp = *this; 52 ++I; 53 return Temp; 54 } 55 56 CtorDtorIterator::Element CtorDtorIterator::operator*() const { 57 ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I)); 58 assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors"); 59 60 Constant *FuncC = CS->getOperand(1); 61 Function *Func = nullptr; 62 63 // Extract function pointer, pulling off any casts. 64 while (FuncC) { 65 if (Function *F = dyn_cast_or_null<Function>(FuncC)) { 66 Func = F; 67 break; 68 } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) { 69 if (CE->isCast()) 70 FuncC = CE->getOperand(0); 71 else 72 break; 73 } else { 74 // This isn't anything we recognize. Bail out with Func left set to null. 75 break; 76 } 77 } 78 79 auto *Priority = cast<ConstantInt>(CS->getOperand(0)); 80 Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr; 81 if (Data && !isa<GlobalValue>(Data)) 82 Data = nullptr; 83 return Element(Priority->getZExtValue(), Func, Data); 84 } 85 86 iterator_range<CtorDtorIterator> getConstructors(const Module &M) { 87 const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors"); 88 return make_range(CtorDtorIterator(CtorsList, false), 89 CtorDtorIterator(CtorsList, true)); 90 } 91 92 iterator_range<CtorDtorIterator> getDestructors(const Module &M) { 93 const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors"); 94 return make_range(CtorDtorIterator(DtorsList, false), 95 CtorDtorIterator(DtorsList, true)); 96 } 97 98 bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) { 99 if (GV.isDeclaration()) 100 return false; 101 102 if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || 103 GV.getName() == "llvm.global_dtors")) 104 return true; 105 106 if (ObjFmt == Triple::MachO) { 107 // FIXME: These section checks are too strict: We should match first and 108 // second word split by comma. 109 if (GV.hasSection() && 110 (GV.getSection().starts_with("__DATA,__objc_classlist") || 111 GV.getSection().starts_with("__DATA,__objc_selrefs"))) 112 return true; 113 } 114 115 return false; 116 } 117 118 void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) { 119 if (CtorDtors.empty()) 120 return; 121 122 MangleAndInterner Mangle( 123 JD.getExecutionSession(), 124 (*CtorDtors.begin()).Func->getDataLayout()); 125 126 for (auto CtorDtor : CtorDtors) { 127 assert(CtorDtor.Func && CtorDtor.Func->hasName() && 128 "Ctor/Dtor function must be named to be runnable under the JIT"); 129 130 // FIXME: Maybe use a symbol promoter here instead. 131 if (CtorDtor.Func->hasLocalLinkage()) { 132 CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage); 133 CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility); 134 } 135 136 if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) { 137 dbgs() << " Skipping because why now?\n"; 138 continue; 139 } 140 141 CtorDtorsByPriority[CtorDtor.Priority].push_back( 142 Mangle(CtorDtor.Func->getName())); 143 } 144 } 145 146 Error CtorDtorRunner::run() { 147 using CtorDtorTy = void (*)(); 148 149 SymbolLookupSet LookupSet; 150 for (auto &KV : CtorDtorsByPriority) 151 for (auto &Name : KV.second) 152 LookupSet.add(Name); 153 assert(!LookupSet.containsDuplicates() && 154 "Ctor/Dtor list contains duplicates"); 155 156 auto &ES = JD.getExecutionSession(); 157 if (auto CtorDtorMap = ES.lookup( 158 makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), 159 std::move(LookupSet))) { 160 for (auto &KV : CtorDtorsByPriority) { 161 for (auto &Name : KV.second) { 162 assert(CtorDtorMap->count(Name) && "No entry for Name"); 163 auto CtorDtor = (*CtorDtorMap)[Name].getAddress().toPtr<CtorDtorTy>(); 164 CtorDtor(); 165 } 166 } 167 CtorDtorsByPriority.clear(); 168 return Error::success(); 169 } else 170 return CtorDtorMap.takeError(); 171 } 172 173 void LocalCXXRuntimeOverridesBase::runDestructors() { 174 auto& CXXDestructorDataPairs = DSOHandleOverride; 175 for (auto &P : CXXDestructorDataPairs) 176 P.first(P.second); 177 CXXDestructorDataPairs.clear(); 178 } 179 180 int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor, 181 void *Arg, 182 void *DSOHandle) { 183 auto& CXXDestructorDataPairs = 184 *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle); 185 CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg)); 186 return 0; 187 } 188 189 Error LocalCXXRuntimeOverrides::enable(JITDylib &JD, 190 MangleAndInterner &Mangle) { 191 SymbolMap RuntimeInterposes; 192 RuntimeInterposes[Mangle("__dso_handle")] = { 193 ExecutorAddr::fromPtr(&DSOHandleOverride), JITSymbolFlags::Exported}; 194 RuntimeInterposes[Mangle("__cxa_atexit")] = { 195 ExecutorAddr::fromPtr(&CXAAtExitOverride), JITSymbolFlags::Exported}; 196 197 return JD.define(absoluteSymbols(std::move(RuntimeInterposes))); 198 } 199 200 void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx, 201 void *DSOHandle) { 202 std::lock_guard<std::mutex> Lock(AtExitsMutex); 203 AtExitRecords[DSOHandle].push_back({F, Ctx}); 204 } 205 206 void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) { 207 std::vector<AtExitRecord> AtExitsToRun; 208 209 { 210 std::lock_guard<std::mutex> Lock(AtExitsMutex); 211 auto I = AtExitRecords.find(DSOHandle); 212 if (I != AtExitRecords.end()) { 213 AtExitsToRun = std::move(I->second); 214 AtExitRecords.erase(I); 215 } 216 } 217 218 while (!AtExitsToRun.empty()) { 219 AtExitsToRun.back().F(AtExitsToRun.back().Ctx); 220 AtExitsToRun.pop_back(); 221 } 222 } 223 224 DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator( 225 sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow, 226 AddAbsoluteSymbolsFn AddAbsoluteSymbols) 227 : Dylib(std::move(Dylib)), Allow(std::move(Allow)), 228 AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)), 229 GlobalPrefix(GlobalPrefix) {} 230 231 Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 232 DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, 233 SymbolPredicate Allow, 234 AddAbsoluteSymbolsFn AddAbsoluteSymbols) { 235 std::string ErrMsg; 236 auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg); 237 if (!Lib.isValid()) 238 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 239 return std::make_unique<DynamicLibrarySearchGenerator>( 240 std::move(Lib), GlobalPrefix, std::move(Allow), 241 std::move(AddAbsoluteSymbols)); 242 } 243 244 Error DynamicLibrarySearchGenerator::tryToGenerate( 245 LookupState &LS, LookupKind K, JITDylib &JD, 246 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 247 orc::SymbolMap NewSymbols; 248 249 bool HasGlobalPrefix = (GlobalPrefix != '\0'); 250 251 for (auto &KV : Symbols) { 252 auto &Name = KV.first; 253 254 if ((*Name).empty()) 255 continue; 256 257 if (Allow && !Allow(Name)) 258 continue; 259 260 if (HasGlobalPrefix && (*Name).front() != GlobalPrefix) 261 continue; 262 263 std::string Tmp((*Name).data() + HasGlobalPrefix, 264 (*Name).size() - HasGlobalPrefix); 265 if (void *P = Dylib.getAddressOfSymbol(Tmp.c_str())) 266 NewSymbols[Name] = {ExecutorAddr::fromPtr(P), JITSymbolFlags::Exported}; 267 } 268 269 if (NewSymbols.empty()) 270 return Error::success(); 271 272 if (AddAbsoluteSymbols) 273 return AddAbsoluteSymbols(JD, std::move(NewSymbols)); 274 return JD.define(absoluteSymbols(std::move(NewSymbols))); 275 } 276 277 StaticLibraryDefinitionGenerator::VisitMembersFunction 278 StaticLibraryDefinitionGenerator::loadAllObjectFileMembers(ObjectLayer &L, 279 JITDylib &JD) { 280 return [&](MemoryBufferRef Buf) -> Error { 281 switch (identify_magic(Buf.getBuffer())) { 282 case file_magic::elf_relocatable: 283 case file_magic::macho_object: 284 case file_magic::coff_object: 285 return L.add(JD, MemoryBuffer::getMemBuffer(Buf)); 286 default: 287 return Error::success(); 288 } 289 }; 290 } 291 292 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 293 StaticLibraryDefinitionGenerator::Load( 294 ObjectLayer &L, const char *FileName, VisitMembersFunction VisitMembers, 295 GetObjectFileInterface GetObjFileInterface) { 296 297 const auto &TT = L.getExecutionSession().getTargetTriple(); 298 auto Linkable = loadLinkableFile(FileName, TT, LoadArchives::Required); 299 if (!Linkable) 300 return Linkable.takeError(); 301 302 return Create(L, std::move(Linkable->first), std::move(VisitMembers), 303 std::move(GetObjFileInterface)); 304 } 305 306 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 307 StaticLibraryDefinitionGenerator::Create( 308 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 309 std::unique_ptr<object::Archive> Archive, VisitMembersFunction VisitMembers, 310 GetObjectFileInterface GetObjFileInterface) { 311 312 Error Err = Error::success(); 313 314 if (VisitMembers) { 315 for (auto Child : Archive->children(Err)) { 316 if (auto ChildBuf = Child.getMemoryBufferRef()) { 317 if (auto Err2 = VisitMembers(*ChildBuf)) 318 return std::move(Err2); 319 } else { 320 // We silently allow non-object archive members. This matches the 321 // behavior of ld. 322 consumeError(ChildBuf.takeError()); 323 } 324 } 325 if (Err) 326 return std::move(Err); 327 } 328 329 std::unique_ptr<StaticLibraryDefinitionGenerator> ADG( 330 new StaticLibraryDefinitionGenerator( 331 L, std::move(ArchiveBuffer), std::move(Archive), 332 std::move(GetObjFileInterface), Err)); 333 334 if (Err) 335 return std::move(Err); 336 337 return std::move(ADG); 338 } 339 340 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 341 StaticLibraryDefinitionGenerator::Create( 342 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 343 VisitMembersFunction VisitMembers, 344 GetObjectFileInterface GetObjFileInterface) { 345 346 auto B = object::createBinary(ArchiveBuffer->getMemBufferRef()); 347 if (!B) 348 return B.takeError(); 349 350 // If this is a regular archive then create an instance from it. 351 if (isa<object::Archive>(*B)) 352 return Create(L, std::move(ArchiveBuffer), 353 std::unique_ptr<object::Archive>( 354 static_cast<object::Archive *>(B->release())), 355 std::move(VisitMembers), std::move(GetObjFileInterface)); 356 357 // If this is a universal binary then search for a slice matching the given 358 // Triple. 359 if (auto *UB = dyn_cast<object::MachOUniversalBinary>(B->get())) { 360 361 const auto &TT = L.getExecutionSession().getTargetTriple(); 362 363 auto SliceRange = getMachOSliceRangeForTriple(*UB, TT); 364 if (!SliceRange) 365 return SliceRange.takeError(); 366 367 MemoryBufferRef SliceRef( 368 StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first, 369 SliceRange->second), 370 ArchiveBuffer->getBufferIdentifier()); 371 372 auto Archive = object::Archive::create(SliceRef); 373 if (!Archive) 374 return Archive.takeError(); 375 376 return Create(L, std::move(ArchiveBuffer), std::move(*Archive), 377 std::move(VisitMembers), std::move(GetObjFileInterface)); 378 } 379 380 return make_error<StringError>(Twine("Unrecognized file type for ") + 381 ArchiveBuffer->getBufferIdentifier(), 382 inconvertibleErrorCode()); 383 } 384 385 Error StaticLibraryDefinitionGenerator::tryToGenerate( 386 LookupState &LS, LookupKind K, JITDylib &JD, 387 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 388 // Don't materialize symbols from static archives unless this is a static 389 // lookup. 390 if (K != LookupKind::Static) 391 return Error::success(); 392 393 // Bail out early if we've already freed the archive. 394 if (!Archive) 395 return Error::success(); 396 397 DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; 398 399 for (const auto &KV : Symbols) { 400 const auto &Name = KV.first; 401 if (!ObjectFilesMap.count(Name)) 402 continue; 403 auto ChildBuffer = ObjectFilesMap[Name]; 404 ChildBufferInfos.insert( 405 {ChildBuffer.getBuffer(), ChildBuffer.getBufferIdentifier()}); 406 } 407 408 for (auto ChildBufferInfo : ChildBufferInfos) { 409 MemoryBufferRef ChildBufferRef(ChildBufferInfo.first, 410 ChildBufferInfo.second); 411 412 auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef); 413 if (!I) 414 return I.takeError(); 415 416 if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false), 417 std::move(*I))) 418 return Err; 419 } 420 421 return Error::success(); 422 } 423 424 Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() { 425 DenseMap<uint64_t, MemoryBufferRef> MemoryBuffers; 426 DenseSet<uint64_t> Visited; 427 DenseSet<uint64_t> Excluded; 428 StringSaver FileNames(ObjFileNameStorage); 429 for (auto &S : Archive->symbols()) { 430 StringRef SymName = S.getName(); 431 auto Member = S.getMember(); 432 if (!Member) 433 return Member.takeError(); 434 auto DataOffset = Member->getDataOffset(); 435 if (!Visited.count(DataOffset)) { 436 Visited.insert(DataOffset); 437 auto Child = Member->getAsBinary(); 438 if (!Child) 439 return Child.takeError(); 440 if ((*Child)->isCOFFImportFile()) { 441 ImportedDynamicLibraries.insert((*Child)->getFileName().str()); 442 Excluded.insert(DataOffset); 443 continue; 444 } 445 446 // Give members of the archive a name that contains the archive path so 447 // that they can be differentiated from a member with the same name in a 448 // different archive. This also ensure initializer symbols names will be 449 // unique within a JITDylib. 450 StringRef FullName = FileNames.save(Archive->getFileName() + "(" + 451 (*Child)->getFileName() + ")"); 452 MemoryBufferRef MemBuffer((*Child)->getMemoryBufferRef().getBuffer(), 453 FullName); 454 455 MemoryBuffers[DataOffset] = MemBuffer; 456 } 457 if (!Excluded.count(DataOffset)) 458 ObjectFilesMap[L.getExecutionSession().intern(SymName)] = 459 MemoryBuffers[DataOffset]; 460 } 461 462 return Error::success(); 463 } 464 465 StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( 466 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 467 std::unique_ptr<object::Archive> Archive, 468 GetObjectFileInterface GetObjFileInterface, Error &Err) 469 : L(L), GetObjFileInterface(std::move(GetObjFileInterface)), 470 ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)) { 471 ErrorAsOutParameter _(Err); 472 if (!this->GetObjFileInterface) 473 this->GetObjFileInterface = getObjectFileInterface; 474 if (!Err) 475 Err = buildObjectFilesMap(); 476 } 477 478 std::unique_ptr<DLLImportDefinitionGenerator> 479 DLLImportDefinitionGenerator::Create(ExecutionSession &ES, 480 ObjectLinkingLayer &L) { 481 return std::unique_ptr<DLLImportDefinitionGenerator>( 482 new DLLImportDefinitionGenerator(ES, L)); 483 } 484 485 Error DLLImportDefinitionGenerator::tryToGenerate( 486 LookupState &LS, LookupKind K, JITDylib &JD, 487 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 488 JITDylibSearchOrder LinkOrder; 489 JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) { 490 LinkOrder.reserve(LO.size()); 491 for (auto &KV : LO) { 492 if (KV.first == &JD) 493 continue; 494 LinkOrder.push_back(KV); 495 } 496 }); 497 498 // FIXME: if regular symbol name start with __imp_ we have to issue lookup of 499 // both __imp_ and stripped name and use the lookup information to resolve the 500 // real symbol name. 501 SymbolLookupSet LookupSet; 502 DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols; 503 for (auto &KV : Symbols) { 504 StringRef Deinterned = *KV.first; 505 if (Deinterned.starts_with(getImpPrefix())) 506 Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size()); 507 // Don't degrade the required state 508 if (ToLookUpSymbols.count(Deinterned) && 509 ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol) 510 continue; 511 ToLookUpSymbols[Deinterned] = KV.second; 512 } 513 514 for (auto &KV : ToLookUpSymbols) 515 LookupSet.add(ES.intern(KV.first), KV.second); 516 517 auto Resolved = 518 ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved); 519 if (!Resolved) 520 return Resolved.takeError(); 521 522 auto G = createStubsGraph(*Resolved); 523 if (!G) 524 return G.takeError(); 525 return L.add(JD, std::move(*G)); 526 } 527 528 Expected<std::unique_ptr<jitlink::LinkGraph>> 529 DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) { 530 auto G = std::make_unique<jitlink::LinkGraph>( 531 "<DLLIMPORT_STUBS>", ES.getSymbolStringPool(), ES.getTargetTriple(), 532 SubtargetFeatures(), jitlink::getGenericEdgeKindName); 533 jitlink::Section &Sec = 534 G->createSection(getSectionName(), MemProt::Read | MemProt::Exec); 535 536 for (auto &KV : Resolved) { 537 jitlink::Symbol &Target = G->addAbsoluteSymbol( 538 *KV.first, KV.second.getAddress(), G->getPointerSize(), 539 jitlink::Linkage::Strong, jitlink::Scope::Local, false); 540 541 // Create __imp_ symbol 542 jitlink::Symbol &Ptr = 543 jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target); 544 Ptr.setName(G->intern((Twine(getImpPrefix()) + *KV.first).str())); 545 Ptr.setLinkage(jitlink::Linkage::Strong); 546 Ptr.setScope(jitlink::Scope::Default); 547 548 // Create PLT stub 549 // FIXME: check PLT stub of data symbol is not accessed 550 jitlink::Block &StubBlock = 551 jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr); 552 G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(), 553 jitlink::Linkage::Strong, jitlink::Scope::Default, true, 554 false); 555 } 556 557 return std::move(G); 558 } 559 560 } // End namespace orc. 561 } // End namespace llvm. 562