109467b48Spatrick //===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick 909467b48Spatrick #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 1009467b48Spatrick #include "llvm/ExecutionEngine/Orc/Layer.h" 1109467b48Spatrick #include "llvm/IR/Constants.h" 1209467b48Spatrick #include "llvm/IR/Function.h" 1309467b48Spatrick #include "llvm/IR/GlobalVariable.h" 1409467b48Spatrick #include "llvm/IR/Module.h" 15097a140dSpatrick #include "llvm/Object/MachOUniversal.h" 16097a140dSpatrick #include "llvm/Support/FormatVariadic.h" 1709467b48Spatrick #include "llvm/Support/TargetRegistry.h" 1809467b48Spatrick #include "llvm/Target/TargetMachine.h" 19*73471bf0Spatrick #include <string> 2009467b48Spatrick 2109467b48Spatrick namespace llvm { 2209467b48Spatrick namespace orc { 2309467b48Spatrick 2409467b48Spatrick CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End) 2509467b48Spatrick : InitList( 2609467b48Spatrick GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr), 2709467b48Spatrick I((InitList && End) ? InitList->getNumOperands() : 0) { 2809467b48Spatrick } 2909467b48Spatrick 3009467b48Spatrick bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const { 3109467b48Spatrick assert(InitList == Other.InitList && "Incomparable iterators."); 3209467b48Spatrick return I == Other.I; 3309467b48Spatrick } 3409467b48Spatrick 3509467b48Spatrick bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const { 3609467b48Spatrick return !(*this == Other); 3709467b48Spatrick } 3809467b48Spatrick 3909467b48Spatrick CtorDtorIterator& CtorDtorIterator::operator++() { 4009467b48Spatrick ++I; 4109467b48Spatrick return *this; 4209467b48Spatrick } 4309467b48Spatrick 4409467b48Spatrick CtorDtorIterator CtorDtorIterator::operator++(int) { 4509467b48Spatrick CtorDtorIterator Temp = *this; 4609467b48Spatrick ++I; 4709467b48Spatrick return Temp; 4809467b48Spatrick } 4909467b48Spatrick 5009467b48Spatrick CtorDtorIterator::Element CtorDtorIterator::operator*() const { 5109467b48Spatrick ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I)); 5209467b48Spatrick assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors"); 5309467b48Spatrick 5409467b48Spatrick Constant *FuncC = CS->getOperand(1); 5509467b48Spatrick Function *Func = nullptr; 5609467b48Spatrick 5709467b48Spatrick // Extract function pointer, pulling off any casts. 5809467b48Spatrick while (FuncC) { 5909467b48Spatrick if (Function *F = dyn_cast_or_null<Function>(FuncC)) { 6009467b48Spatrick Func = F; 6109467b48Spatrick break; 6209467b48Spatrick } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) { 6309467b48Spatrick if (CE->isCast()) 6409467b48Spatrick FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0)); 6509467b48Spatrick else 6609467b48Spatrick break; 6709467b48Spatrick } else { 6809467b48Spatrick // This isn't anything we recognize. Bail out with Func left set to null. 6909467b48Spatrick break; 7009467b48Spatrick } 7109467b48Spatrick } 7209467b48Spatrick 7309467b48Spatrick auto *Priority = cast<ConstantInt>(CS->getOperand(0)); 7409467b48Spatrick Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr; 7509467b48Spatrick if (Data && !isa<GlobalValue>(Data)) 7609467b48Spatrick Data = nullptr; 7709467b48Spatrick return Element(Priority->getZExtValue(), Func, Data); 7809467b48Spatrick } 7909467b48Spatrick 8009467b48Spatrick iterator_range<CtorDtorIterator> getConstructors(const Module &M) { 8109467b48Spatrick const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors"); 8209467b48Spatrick return make_range(CtorDtorIterator(CtorsList, false), 8309467b48Spatrick CtorDtorIterator(CtorsList, true)); 8409467b48Spatrick } 8509467b48Spatrick 8609467b48Spatrick iterator_range<CtorDtorIterator> getDestructors(const Module &M) { 8709467b48Spatrick const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors"); 8809467b48Spatrick return make_range(CtorDtorIterator(DtorsList, false), 8909467b48Spatrick CtorDtorIterator(DtorsList, true)); 9009467b48Spatrick } 9109467b48Spatrick 92097a140dSpatrick bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) { 93097a140dSpatrick if (GV.isDeclaration()) 94097a140dSpatrick return false; 95097a140dSpatrick 96097a140dSpatrick if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || 97097a140dSpatrick GV.getName() == "llvm.global_dtors")) 98097a140dSpatrick return true; 99097a140dSpatrick 100097a140dSpatrick if (ObjFmt == Triple::MachO) { 101097a140dSpatrick // FIXME: These section checks are too strict: We should match first and 102097a140dSpatrick // second word split by comma. 103097a140dSpatrick if (GV.hasSection() && 104097a140dSpatrick (GV.getSection().startswith("__DATA,__objc_classlist") || 105097a140dSpatrick GV.getSection().startswith("__DATA,__objc_selrefs"))) 106097a140dSpatrick return true; 107097a140dSpatrick } 108097a140dSpatrick 109097a140dSpatrick return false; 110097a140dSpatrick } 111097a140dSpatrick 11209467b48Spatrick void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) { 11309467b48Spatrick if (CtorDtors.empty()) 11409467b48Spatrick return; 11509467b48Spatrick 11609467b48Spatrick MangleAndInterner Mangle( 11709467b48Spatrick JD.getExecutionSession(), 11809467b48Spatrick (*CtorDtors.begin()).Func->getParent()->getDataLayout()); 11909467b48Spatrick 12009467b48Spatrick for (auto CtorDtor : CtorDtors) { 12109467b48Spatrick assert(CtorDtor.Func && CtorDtor.Func->hasName() && 12209467b48Spatrick "Ctor/Dtor function must be named to be runnable under the JIT"); 12309467b48Spatrick 12409467b48Spatrick // FIXME: Maybe use a symbol promoter here instead. 12509467b48Spatrick if (CtorDtor.Func->hasLocalLinkage()) { 12609467b48Spatrick CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage); 12709467b48Spatrick CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility); 12809467b48Spatrick } 12909467b48Spatrick 13009467b48Spatrick if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) { 13109467b48Spatrick dbgs() << " Skipping because why now?\n"; 13209467b48Spatrick continue; 13309467b48Spatrick } 13409467b48Spatrick 13509467b48Spatrick CtorDtorsByPriority[CtorDtor.Priority].push_back( 13609467b48Spatrick Mangle(CtorDtor.Func->getName())); 13709467b48Spatrick } 13809467b48Spatrick } 13909467b48Spatrick 14009467b48Spatrick Error CtorDtorRunner::run() { 14109467b48Spatrick using CtorDtorTy = void (*)(); 14209467b48Spatrick 14309467b48Spatrick SymbolLookupSet LookupSet; 14409467b48Spatrick for (auto &KV : CtorDtorsByPriority) 14509467b48Spatrick for (auto &Name : KV.second) 14609467b48Spatrick LookupSet.add(Name); 14709467b48Spatrick assert(!LookupSet.containsDuplicates() && 14809467b48Spatrick "Ctor/Dtor list contains duplicates"); 14909467b48Spatrick 15009467b48Spatrick auto &ES = JD.getExecutionSession(); 15109467b48Spatrick if (auto CtorDtorMap = ES.lookup( 15209467b48Spatrick makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), 15309467b48Spatrick std::move(LookupSet))) { 15409467b48Spatrick for (auto &KV : CtorDtorsByPriority) { 15509467b48Spatrick for (auto &Name : KV.second) { 15609467b48Spatrick assert(CtorDtorMap->count(Name) && "No entry for Name"); 15709467b48Spatrick auto CtorDtor = reinterpret_cast<CtorDtorTy>( 15809467b48Spatrick static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress())); 15909467b48Spatrick CtorDtor(); 16009467b48Spatrick } 16109467b48Spatrick } 16209467b48Spatrick CtorDtorsByPriority.clear(); 16309467b48Spatrick return Error::success(); 16409467b48Spatrick } else 16509467b48Spatrick return CtorDtorMap.takeError(); 16609467b48Spatrick } 16709467b48Spatrick 16809467b48Spatrick void LocalCXXRuntimeOverridesBase::runDestructors() { 16909467b48Spatrick auto& CXXDestructorDataPairs = DSOHandleOverride; 17009467b48Spatrick for (auto &P : CXXDestructorDataPairs) 17109467b48Spatrick P.first(P.second); 17209467b48Spatrick CXXDestructorDataPairs.clear(); 17309467b48Spatrick } 17409467b48Spatrick 17509467b48Spatrick int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor, 17609467b48Spatrick void *Arg, 17709467b48Spatrick void *DSOHandle) { 17809467b48Spatrick auto& CXXDestructorDataPairs = 17909467b48Spatrick *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle); 18009467b48Spatrick CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg)); 18109467b48Spatrick return 0; 18209467b48Spatrick } 18309467b48Spatrick 18409467b48Spatrick Error LocalCXXRuntimeOverrides::enable(JITDylib &JD, 18509467b48Spatrick MangleAndInterner &Mangle) { 18609467b48Spatrick SymbolMap RuntimeInterposes; 18709467b48Spatrick RuntimeInterposes[Mangle("__dso_handle")] = 18809467b48Spatrick JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride), 18909467b48Spatrick JITSymbolFlags::Exported); 19009467b48Spatrick RuntimeInterposes[Mangle("__cxa_atexit")] = 19109467b48Spatrick JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride), 19209467b48Spatrick JITSymbolFlags::Exported); 19309467b48Spatrick 19409467b48Spatrick return JD.define(absoluteSymbols(std::move(RuntimeInterposes))); 19509467b48Spatrick } 19609467b48Spatrick 197097a140dSpatrick void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx, 198097a140dSpatrick void *DSOHandle) { 199097a140dSpatrick std::lock_guard<std::mutex> Lock(AtExitsMutex); 200097a140dSpatrick AtExitRecords[DSOHandle].push_back({F, Ctx}); 201097a140dSpatrick } 202097a140dSpatrick 203097a140dSpatrick void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) { 204097a140dSpatrick std::vector<AtExitRecord> AtExitsToRun; 205097a140dSpatrick 206097a140dSpatrick { 207097a140dSpatrick std::lock_guard<std::mutex> Lock(AtExitsMutex); 208097a140dSpatrick auto I = AtExitRecords.find(DSOHandle); 209097a140dSpatrick if (I != AtExitRecords.end()) { 210097a140dSpatrick AtExitsToRun = std::move(I->second); 211097a140dSpatrick AtExitRecords.erase(I); 212097a140dSpatrick } 213097a140dSpatrick } 214097a140dSpatrick 215097a140dSpatrick while (!AtExitsToRun.empty()) { 216097a140dSpatrick AtExitsToRun.back().F(AtExitsToRun.back().Ctx); 217097a140dSpatrick AtExitsToRun.pop_back(); 218097a140dSpatrick } 219097a140dSpatrick } 220097a140dSpatrick 22109467b48Spatrick DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator( 22209467b48Spatrick sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow) 22309467b48Spatrick : Dylib(std::move(Dylib)), Allow(std::move(Allow)), 22409467b48Spatrick GlobalPrefix(GlobalPrefix) {} 22509467b48Spatrick 22609467b48Spatrick Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 22709467b48Spatrick DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, 22809467b48Spatrick SymbolPredicate Allow) { 22909467b48Spatrick std::string ErrMsg; 23009467b48Spatrick auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg); 23109467b48Spatrick if (!Lib.isValid()) 23209467b48Spatrick return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 23309467b48Spatrick return std::make_unique<DynamicLibrarySearchGenerator>( 23409467b48Spatrick std::move(Lib), GlobalPrefix, std::move(Allow)); 23509467b48Spatrick } 23609467b48Spatrick 23709467b48Spatrick Error DynamicLibrarySearchGenerator::tryToGenerate( 238*73471bf0Spatrick LookupState &LS, LookupKind K, JITDylib &JD, 239*73471bf0Spatrick JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 24009467b48Spatrick orc::SymbolMap NewSymbols; 24109467b48Spatrick 24209467b48Spatrick bool HasGlobalPrefix = (GlobalPrefix != '\0'); 24309467b48Spatrick 24409467b48Spatrick for (auto &KV : Symbols) { 24509467b48Spatrick auto &Name = KV.first; 24609467b48Spatrick 24709467b48Spatrick if ((*Name).empty()) 24809467b48Spatrick continue; 24909467b48Spatrick 25009467b48Spatrick if (Allow && !Allow(Name)) 25109467b48Spatrick continue; 25209467b48Spatrick 25309467b48Spatrick if (HasGlobalPrefix && (*Name).front() != GlobalPrefix) 25409467b48Spatrick continue; 25509467b48Spatrick 25609467b48Spatrick std::string Tmp((*Name).data() + HasGlobalPrefix, 25709467b48Spatrick (*Name).size() - HasGlobalPrefix); 25809467b48Spatrick if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) { 25909467b48Spatrick NewSymbols[Name] = JITEvaluatedSymbol( 26009467b48Spatrick static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)), 26109467b48Spatrick JITSymbolFlags::Exported); 26209467b48Spatrick } 26309467b48Spatrick } 26409467b48Spatrick 26509467b48Spatrick if (NewSymbols.empty()) 26609467b48Spatrick return Error::success(); 26709467b48Spatrick 26809467b48Spatrick return JD.define(absoluteSymbols(std::move(NewSymbols))); 26909467b48Spatrick } 27009467b48Spatrick 27109467b48Spatrick Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 27209467b48Spatrick StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) { 27309467b48Spatrick auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName)); 27409467b48Spatrick 27509467b48Spatrick if (!ArchiveBuffer) 27609467b48Spatrick return ArchiveBuffer.takeError(); 27709467b48Spatrick 27809467b48Spatrick return Create(L, std::move(*ArchiveBuffer)); 27909467b48Spatrick } 28009467b48Spatrick 28109467b48Spatrick Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 282097a140dSpatrick StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName, 283097a140dSpatrick const Triple &TT) { 284097a140dSpatrick auto B = object::createBinary(FileName); 285097a140dSpatrick if (!B) 286097a140dSpatrick return B.takeError(); 287097a140dSpatrick 288097a140dSpatrick // If this is a regular archive then create an instance from it. 289097a140dSpatrick if (isa<object::Archive>(B->getBinary())) 290097a140dSpatrick return Create(L, std::move(B->takeBinary().second)); 291097a140dSpatrick 292097a140dSpatrick // If this is a universal binary then search for a slice matching the given 293097a140dSpatrick // Triple. 294097a140dSpatrick if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) { 295097a140dSpatrick for (const auto &Obj : UB->objects()) { 296097a140dSpatrick auto ObjTT = Obj.getTriple(); 297097a140dSpatrick if (ObjTT.getArch() == TT.getArch() && 298097a140dSpatrick ObjTT.getSubArch() == TT.getSubArch() && 299*73471bf0Spatrick (TT.getVendor() == Triple::UnknownVendor || 300*73471bf0Spatrick ObjTT.getVendor() == TT.getVendor())) { 301097a140dSpatrick // We found a match. Create an instance from a buffer covering this 302097a140dSpatrick // slice. 303097a140dSpatrick auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(), 304097a140dSpatrick Obj.getOffset()); 305097a140dSpatrick if (!SliceBuffer) 306097a140dSpatrick return make_error<StringError>( 307097a140dSpatrick Twine("Could not create buffer for ") + TT.str() + " slice of " + 308097a140dSpatrick FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) + 309097a140dSpatrick " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) + 310097a140dSpatrick ": " + SliceBuffer.getError().message(), 311097a140dSpatrick SliceBuffer.getError()); 312097a140dSpatrick return Create(L, std::move(*SliceBuffer)); 313097a140dSpatrick } 314097a140dSpatrick } 315097a140dSpatrick 316097a140dSpatrick return make_error<StringError>(Twine("Universal binary ") + FileName + 317097a140dSpatrick " does not contain a slice for " + 318097a140dSpatrick TT.str(), 319097a140dSpatrick inconvertibleErrorCode()); 320097a140dSpatrick } 321097a140dSpatrick 322097a140dSpatrick return make_error<StringError>(Twine("Unrecognized file type for ") + 323097a140dSpatrick FileName, 324097a140dSpatrick inconvertibleErrorCode()); 325097a140dSpatrick } 326097a140dSpatrick 327097a140dSpatrick Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 32809467b48Spatrick StaticLibraryDefinitionGenerator::Create( 32909467b48Spatrick ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) { 33009467b48Spatrick Error Err = Error::success(); 33109467b48Spatrick 33209467b48Spatrick std::unique_ptr<StaticLibraryDefinitionGenerator> ADG( 33309467b48Spatrick new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err)); 33409467b48Spatrick 33509467b48Spatrick if (Err) 33609467b48Spatrick return std::move(Err); 33709467b48Spatrick 33809467b48Spatrick return std::move(ADG); 33909467b48Spatrick } 34009467b48Spatrick 34109467b48Spatrick Error StaticLibraryDefinitionGenerator::tryToGenerate( 342*73471bf0Spatrick LookupState &LS, LookupKind K, JITDylib &JD, 343*73471bf0Spatrick JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 34409467b48Spatrick 34509467b48Spatrick // Don't materialize symbols from static archives unless this is a static 34609467b48Spatrick // lookup. 34709467b48Spatrick if (K != LookupKind::Static) 34809467b48Spatrick return Error::success(); 34909467b48Spatrick 35009467b48Spatrick // Bail out early if we've already freed the archive. 35109467b48Spatrick if (!Archive) 35209467b48Spatrick return Error::success(); 35309467b48Spatrick 35409467b48Spatrick DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; 35509467b48Spatrick 35609467b48Spatrick for (const auto &KV : Symbols) { 35709467b48Spatrick const auto &Name = KV.first; 35809467b48Spatrick auto Child = Archive->findSym(*Name); 35909467b48Spatrick if (!Child) 36009467b48Spatrick return Child.takeError(); 36109467b48Spatrick if (*Child == None) 36209467b48Spatrick continue; 36309467b48Spatrick auto ChildBuffer = (*Child)->getMemoryBufferRef(); 36409467b48Spatrick if (!ChildBuffer) 36509467b48Spatrick return ChildBuffer.takeError(); 36609467b48Spatrick ChildBufferInfos.insert( 36709467b48Spatrick {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()}); 36809467b48Spatrick } 36909467b48Spatrick 37009467b48Spatrick for (auto ChildBufferInfo : ChildBufferInfos) { 37109467b48Spatrick MemoryBufferRef ChildBufferRef(ChildBufferInfo.first, 37209467b48Spatrick ChildBufferInfo.second); 37309467b48Spatrick 374*73471bf0Spatrick if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false))) 37509467b48Spatrick return Err; 37609467b48Spatrick } 37709467b48Spatrick 37809467b48Spatrick return Error::success(); 37909467b48Spatrick } 38009467b48Spatrick 38109467b48Spatrick StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( 38209467b48Spatrick ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err) 38309467b48Spatrick : L(L), ArchiveBuffer(std::move(ArchiveBuffer)), 38409467b48Spatrick Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {} 38509467b48Spatrick 38609467b48Spatrick } // End namespace orc. 38709467b48Spatrick } // End namespace llvm. 388