10b57cec5SDimitry Andric //===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 10bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h" 118bcb0991SDimitry Andric #include "llvm/ExecutionEngine/Orc/Layer.h" 120eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 130b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 140b57cec5SDimitry Andric #include "llvm/IR/Function.h" 150b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 160b57cec5SDimitry Andric #include "llvm/IR/Module.h" 17349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 185ffd83dbSDimitry Andric #include "llvm/Object/MachOUniversal.h" 195ffd83dbSDimitry Andric #include "llvm/Support/FormatVariadic.h" 200b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 21fe6060f1SDimitry Andric #include <string> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace llvm { 240b57cec5SDimitry Andric namespace orc { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End) 270b57cec5SDimitry Andric : InitList( 280b57cec5SDimitry Andric GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr), 290b57cec5SDimitry Andric I((InitList && End) ? InitList->getNumOperands() : 0) { 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const { 330b57cec5SDimitry Andric assert(InitList == Other.InitList && "Incomparable iterators."); 340b57cec5SDimitry Andric return I == Other.I; 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const { 380b57cec5SDimitry Andric return !(*this == Other); 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric CtorDtorIterator& CtorDtorIterator::operator++() { 420b57cec5SDimitry Andric ++I; 430b57cec5SDimitry Andric return *this; 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric CtorDtorIterator CtorDtorIterator::operator++(int) { 470b57cec5SDimitry Andric CtorDtorIterator Temp = *this; 480b57cec5SDimitry Andric ++I; 490b57cec5SDimitry Andric return Temp; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric CtorDtorIterator::Element CtorDtorIterator::operator*() const { 530b57cec5SDimitry Andric ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I)); 540b57cec5SDimitry Andric assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors"); 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric Constant *FuncC = CS->getOperand(1); 570b57cec5SDimitry Andric Function *Func = nullptr; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Extract function pointer, pulling off any casts. 600b57cec5SDimitry Andric while (FuncC) { 610b57cec5SDimitry Andric if (Function *F = dyn_cast_or_null<Function>(FuncC)) { 620b57cec5SDimitry Andric Func = F; 630b57cec5SDimitry Andric break; 640b57cec5SDimitry Andric } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) { 650b57cec5SDimitry Andric if (CE->isCast()) 6681ad6265SDimitry Andric FuncC = CE->getOperand(0); 670b57cec5SDimitry Andric else 680b57cec5SDimitry Andric break; 690b57cec5SDimitry Andric } else { 700b57cec5SDimitry Andric // This isn't anything we recognize. Bail out with Func left set to null. 710b57cec5SDimitry Andric break; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 758bcb0991SDimitry Andric auto *Priority = cast<ConstantInt>(CS->getOperand(0)); 760b57cec5SDimitry Andric Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr; 770b57cec5SDimitry Andric if (Data && !isa<GlobalValue>(Data)) 780b57cec5SDimitry Andric Data = nullptr; 790b57cec5SDimitry Andric return Element(Priority->getZExtValue(), Func, Data); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getConstructors(const Module &M) { 830b57cec5SDimitry Andric const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors"); 840b57cec5SDimitry Andric return make_range(CtorDtorIterator(CtorsList, false), 850b57cec5SDimitry Andric CtorDtorIterator(CtorsList, true)); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getDestructors(const Module &M) { 890b57cec5SDimitry Andric const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors"); 900b57cec5SDimitry Andric return make_range(CtorDtorIterator(DtorsList, false), 910b57cec5SDimitry Andric CtorDtorIterator(DtorsList, true)); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 945ffd83dbSDimitry Andric bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) { 955ffd83dbSDimitry Andric if (GV.isDeclaration()) 965ffd83dbSDimitry Andric return false; 975ffd83dbSDimitry Andric 985ffd83dbSDimitry Andric if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || 995ffd83dbSDimitry Andric GV.getName() == "llvm.global_dtors")) 1005ffd83dbSDimitry Andric return true; 1015ffd83dbSDimitry Andric 1025ffd83dbSDimitry Andric if (ObjFmt == Triple::MachO) { 1035ffd83dbSDimitry Andric // FIXME: These section checks are too strict: We should match first and 1045ffd83dbSDimitry Andric // second word split by comma. 1055ffd83dbSDimitry Andric if (GV.hasSection() && 1065f757f3fSDimitry Andric (GV.getSection().starts_with("__DATA,__objc_classlist") || 1075f757f3fSDimitry Andric GV.getSection().starts_with("__DATA,__objc_selrefs"))) 1085ffd83dbSDimitry Andric return true; 1095ffd83dbSDimitry Andric } 1105ffd83dbSDimitry Andric 1115ffd83dbSDimitry Andric return false; 1125ffd83dbSDimitry Andric } 1135ffd83dbSDimitry Andric 1140b57cec5SDimitry Andric void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) { 1158bcb0991SDimitry Andric if (CtorDtors.empty()) 1160b57cec5SDimitry Andric return; 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric MangleAndInterner Mangle( 1190b57cec5SDimitry Andric JD.getExecutionSession(), 1200b57cec5SDimitry Andric (*CtorDtors.begin()).Func->getParent()->getDataLayout()); 1210b57cec5SDimitry Andric 122480093f4SDimitry Andric for (auto CtorDtor : CtorDtors) { 1230b57cec5SDimitry Andric assert(CtorDtor.Func && CtorDtor.Func->hasName() && 1240b57cec5SDimitry Andric "Ctor/Dtor function must be named to be runnable under the JIT"); 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric // FIXME: Maybe use a symbol promoter here instead. 1270b57cec5SDimitry Andric if (CtorDtor.Func->hasLocalLinkage()) { 1280b57cec5SDimitry Andric CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage); 1290b57cec5SDimitry Andric CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) { 1330b57cec5SDimitry Andric dbgs() << " Skipping because why now?\n"; 1340b57cec5SDimitry Andric continue; 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric CtorDtorsByPriority[CtorDtor.Priority].push_back( 1380b57cec5SDimitry Andric Mangle(CtorDtor.Func->getName())); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric Error CtorDtorRunner::run() { 1430b57cec5SDimitry Andric using CtorDtorTy = void (*)(); 1440b57cec5SDimitry Andric 145480093f4SDimitry Andric SymbolLookupSet LookupSet; 146480093f4SDimitry Andric for (auto &KV : CtorDtorsByPriority) 147480093f4SDimitry Andric for (auto &Name : KV.second) 148480093f4SDimitry Andric LookupSet.add(Name); 149480093f4SDimitry Andric assert(!LookupSet.containsDuplicates() && 150480093f4SDimitry Andric "Ctor/Dtor list contains duplicates"); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric auto &ES = JD.getExecutionSession(); 153480093f4SDimitry Andric if (auto CtorDtorMap = ES.lookup( 154480093f4SDimitry Andric makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), 155480093f4SDimitry Andric std::move(LookupSet))) { 1560b57cec5SDimitry Andric for (auto &KV : CtorDtorsByPriority) { 1570b57cec5SDimitry Andric for (auto &Name : KV.second) { 1580b57cec5SDimitry Andric assert(CtorDtorMap->count(Name) && "No entry for Name"); 15906c3fb27SDimitry Andric auto CtorDtor = (*CtorDtorMap)[Name].getAddress().toPtr<CtorDtorTy>(); 1600b57cec5SDimitry Andric CtorDtor(); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric CtorDtorsByPriority.clear(); 1640b57cec5SDimitry Andric return Error::success(); 1650b57cec5SDimitry Andric } else 1660b57cec5SDimitry Andric return CtorDtorMap.takeError(); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric void LocalCXXRuntimeOverridesBase::runDestructors() { 1700b57cec5SDimitry Andric auto& CXXDestructorDataPairs = DSOHandleOverride; 1710b57cec5SDimitry Andric for (auto &P : CXXDestructorDataPairs) 1720b57cec5SDimitry Andric P.first(P.second); 1730b57cec5SDimitry Andric CXXDestructorDataPairs.clear(); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor, 1770b57cec5SDimitry Andric void *Arg, 1780b57cec5SDimitry Andric void *DSOHandle) { 1790b57cec5SDimitry Andric auto& CXXDestructorDataPairs = 1800b57cec5SDimitry Andric *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle); 1810b57cec5SDimitry Andric CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg)); 1820b57cec5SDimitry Andric return 0; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric Error LocalCXXRuntimeOverrides::enable(JITDylib &JD, 1860b57cec5SDimitry Andric MangleAndInterner &Mangle) { 1870b57cec5SDimitry Andric SymbolMap RuntimeInterposes; 18806c3fb27SDimitry Andric RuntimeInterposes[Mangle("__dso_handle")] = { 18906c3fb27SDimitry Andric ExecutorAddr::fromPtr(&DSOHandleOverride), JITSymbolFlags::Exported}; 19006c3fb27SDimitry Andric RuntimeInterposes[Mangle("__cxa_atexit")] = { 19106c3fb27SDimitry Andric ExecutorAddr::fromPtr(&CXAAtExitOverride), JITSymbolFlags::Exported}; 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric return JD.define(absoluteSymbols(std::move(RuntimeInterposes))); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1965ffd83dbSDimitry Andric void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx, 1975ffd83dbSDimitry Andric void *DSOHandle) { 1985ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(AtExitsMutex); 1995ffd83dbSDimitry Andric AtExitRecords[DSOHandle].push_back({F, Ctx}); 2005ffd83dbSDimitry Andric } 2015ffd83dbSDimitry Andric 2025ffd83dbSDimitry Andric void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) { 2035ffd83dbSDimitry Andric std::vector<AtExitRecord> AtExitsToRun; 2045ffd83dbSDimitry Andric 2055ffd83dbSDimitry Andric { 2065ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(AtExitsMutex); 2075ffd83dbSDimitry Andric auto I = AtExitRecords.find(DSOHandle); 2085ffd83dbSDimitry Andric if (I != AtExitRecords.end()) { 2095ffd83dbSDimitry Andric AtExitsToRun = std::move(I->second); 2105ffd83dbSDimitry Andric AtExitRecords.erase(I); 2115ffd83dbSDimitry Andric } 2125ffd83dbSDimitry Andric } 2135ffd83dbSDimitry Andric 2145ffd83dbSDimitry Andric while (!AtExitsToRun.empty()) { 2155ffd83dbSDimitry Andric AtExitsToRun.back().F(AtExitsToRun.back().Ctx); 2165ffd83dbSDimitry Andric AtExitsToRun.pop_back(); 2175ffd83dbSDimitry Andric } 2185ffd83dbSDimitry Andric } 2195ffd83dbSDimitry Andric 2200b57cec5SDimitry Andric DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator( 221*1db9f3b2SDimitry Andric sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow, 222*1db9f3b2SDimitry Andric AddAbsoluteSymbolsFn AddAbsoluteSymbols) 2230b57cec5SDimitry Andric : Dylib(std::move(Dylib)), Allow(std::move(Allow)), 224*1db9f3b2SDimitry Andric AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)), 2250b57cec5SDimitry Andric GlobalPrefix(GlobalPrefix) {} 2260b57cec5SDimitry Andric 2278bcb0991SDimitry Andric Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 2280b57cec5SDimitry Andric DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, 229*1db9f3b2SDimitry Andric SymbolPredicate Allow, 230*1db9f3b2SDimitry Andric AddAbsoluteSymbolsFn AddAbsoluteSymbols) { 2310b57cec5SDimitry Andric std::string ErrMsg; 2320b57cec5SDimitry Andric auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg); 2330b57cec5SDimitry Andric if (!Lib.isValid()) 2340b57cec5SDimitry Andric return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 2358bcb0991SDimitry Andric return std::make_unique<DynamicLibrarySearchGenerator>( 236*1db9f3b2SDimitry Andric std::move(Lib), GlobalPrefix, std::move(Allow), 237*1db9f3b2SDimitry Andric std::move(AddAbsoluteSymbols)); 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 240480093f4SDimitry Andric Error DynamicLibrarySearchGenerator::tryToGenerate( 241e8d8bef9SDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 242e8d8bef9SDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 2430b57cec5SDimitry Andric orc::SymbolMap NewSymbols; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric bool HasGlobalPrefix = (GlobalPrefix != '\0'); 2460b57cec5SDimitry Andric 247480093f4SDimitry Andric for (auto &KV : Symbols) { 248480093f4SDimitry Andric auto &Name = KV.first; 249480093f4SDimitry Andric 2500b57cec5SDimitry Andric if ((*Name).empty()) 2510b57cec5SDimitry Andric continue; 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric if (Allow && !Allow(Name)) 2540b57cec5SDimitry Andric continue; 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric if (HasGlobalPrefix && (*Name).front() != GlobalPrefix) 2570b57cec5SDimitry Andric continue; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric std::string Tmp((*Name).data() + HasGlobalPrefix, 2600b57cec5SDimitry Andric (*Name).size() - HasGlobalPrefix); 26106c3fb27SDimitry Andric if (void *P = Dylib.getAddressOfSymbol(Tmp.c_str())) 26206c3fb27SDimitry Andric NewSymbols[Name] = {ExecutorAddr::fromPtr(P), JITSymbolFlags::Exported}; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 265480093f4SDimitry Andric if (NewSymbols.empty()) 266480093f4SDimitry Andric return Error::success(); 2670b57cec5SDimitry Andric 268*1db9f3b2SDimitry Andric if (AddAbsoluteSymbols) 269*1db9f3b2SDimitry Andric return AddAbsoluteSymbols(JD, std::move(NewSymbols)); 270480093f4SDimitry Andric return JD.define(absoluteSymbols(std::move(NewSymbols))); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2738bcb0991SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 2740eae32dcSDimitry Andric StaticLibraryDefinitionGenerator::Load( 2750eae32dcSDimitry Andric ObjectLayer &L, const char *FileName, 2760eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface) { 2770eae32dcSDimitry Andric 2785ffd83dbSDimitry Andric auto B = object::createBinary(FileName); 2795ffd83dbSDimitry Andric if (!B) 28081ad6265SDimitry Andric return createFileError(FileName, B.takeError()); 2815ffd83dbSDimitry Andric 2825ffd83dbSDimitry Andric // If this is a regular archive then create an instance from it. 28306c3fb27SDimitry Andric if (isa<object::Archive>(B->getBinary())) { 28406c3fb27SDimitry Andric auto [Archive, ArchiveBuffer] = B->takeBinary(); 28506c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), 28606c3fb27SDimitry Andric std::unique_ptr<object::Archive>( 28706c3fb27SDimitry Andric static_cast<object::Archive *>(Archive.release())), 2880eae32dcSDimitry Andric std::move(GetObjFileInterface)); 28906c3fb27SDimitry Andric } 2905ffd83dbSDimitry Andric 2915ffd83dbSDimitry Andric // If this is a universal binary then search for a slice matching the given 2925ffd83dbSDimitry Andric // Triple. 2935f757f3fSDimitry Andric if (auto *UB = dyn_cast<object::MachOUniversalBinary>(B->getBinary())) { 29406c3fb27SDimitry Andric 29506c3fb27SDimitry Andric const auto &TT = L.getExecutionSession().getTargetTriple(); 29606c3fb27SDimitry Andric 29706c3fb27SDimitry Andric auto SliceRange = getSliceRangeForArch(*UB, TT); 29806c3fb27SDimitry Andric if (!SliceRange) 29906c3fb27SDimitry Andric return SliceRange.takeError(); 30006c3fb27SDimitry Andric 30106c3fb27SDimitry Andric auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, SliceRange->second, 30206c3fb27SDimitry Andric SliceRange->first); 3035ffd83dbSDimitry Andric if (!SliceBuffer) 3045ffd83dbSDimitry Andric return make_error<StringError>( 3055ffd83dbSDimitry Andric Twine("Could not create buffer for ") + TT.str() + " slice of " + 30606c3fb27SDimitry Andric FileName + ": [ " + formatv("{0:x}", SliceRange->first) + " .. " + 30706c3fb27SDimitry Andric formatv("{0:x}", SliceRange->first + SliceRange->second) + ": " + 30806c3fb27SDimitry Andric SliceBuffer.getError().message(), 3095ffd83dbSDimitry Andric SliceBuffer.getError()); 3105ffd83dbSDimitry Andric 31106c3fb27SDimitry Andric return Create(L, std::move(*SliceBuffer), std::move(GetObjFileInterface)); 3125ffd83dbSDimitry Andric } 3135ffd83dbSDimitry Andric 3145ffd83dbSDimitry Andric return make_error<StringError>(Twine("Unrecognized file type for ") + 3155ffd83dbSDimitry Andric FileName, 3165ffd83dbSDimitry Andric inconvertibleErrorCode()); 3175ffd83dbSDimitry Andric } 3185ffd83dbSDimitry Andric 3195ffd83dbSDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 3208bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::Create( 3210eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 32206c3fb27SDimitry Andric std::unique_ptr<object::Archive> Archive, 3230eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface) { 32406c3fb27SDimitry Andric 3258bcb0991SDimitry Andric Error Err = Error::success(); 3268bcb0991SDimitry Andric 3278bcb0991SDimitry Andric std::unique_ptr<StaticLibraryDefinitionGenerator> ADG( 3280eae32dcSDimitry Andric new StaticLibraryDefinitionGenerator( 32906c3fb27SDimitry Andric L, std::move(ArchiveBuffer), std::move(Archive), 33006c3fb27SDimitry Andric std::move(GetObjFileInterface), Err)); 3318bcb0991SDimitry Andric 3328bcb0991SDimitry Andric if (Err) 3338bcb0991SDimitry Andric return std::move(Err); 3348bcb0991SDimitry Andric 3358bcb0991SDimitry Andric return std::move(ADG); 3368bcb0991SDimitry Andric } 3378bcb0991SDimitry Andric 33806c3fb27SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 33906c3fb27SDimitry Andric StaticLibraryDefinitionGenerator::Create( 34006c3fb27SDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 34106c3fb27SDimitry Andric GetObjectFileInterface GetObjFileInterface) { 34206c3fb27SDimitry Andric 34306c3fb27SDimitry Andric auto B = object::createBinary(ArchiveBuffer->getMemBufferRef()); 34406c3fb27SDimitry Andric if (!B) 34506c3fb27SDimitry Andric return B.takeError(); 34606c3fb27SDimitry Andric 34706c3fb27SDimitry Andric // If this is a regular archive then create an instance from it. 34806c3fb27SDimitry Andric if (isa<object::Archive>(*B)) 34906c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), 35006c3fb27SDimitry Andric std::unique_ptr<object::Archive>( 35106c3fb27SDimitry Andric static_cast<object::Archive *>(B->release())), 35206c3fb27SDimitry Andric std::move(GetObjFileInterface)); 35306c3fb27SDimitry Andric 35406c3fb27SDimitry Andric // If this is a universal binary then search for a slice matching the given 35506c3fb27SDimitry Andric // Triple. 3565f757f3fSDimitry Andric if (auto *UB = dyn_cast<object::MachOUniversalBinary>(B->get())) { 35706c3fb27SDimitry Andric 35806c3fb27SDimitry Andric const auto &TT = L.getExecutionSession().getTargetTriple(); 35906c3fb27SDimitry Andric 36006c3fb27SDimitry Andric auto SliceRange = getSliceRangeForArch(*UB, TT); 36106c3fb27SDimitry Andric if (!SliceRange) 36206c3fb27SDimitry Andric return SliceRange.takeError(); 36306c3fb27SDimitry Andric 36406c3fb27SDimitry Andric MemoryBufferRef SliceRef( 36506c3fb27SDimitry Andric StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first, 36606c3fb27SDimitry Andric SliceRange->second), 36706c3fb27SDimitry Andric ArchiveBuffer->getBufferIdentifier()); 36806c3fb27SDimitry Andric 36906c3fb27SDimitry Andric auto Archive = object::Archive::create(SliceRef); 37006c3fb27SDimitry Andric if (!Archive) 37106c3fb27SDimitry Andric return Archive.takeError(); 37206c3fb27SDimitry Andric 37306c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), std::move(*Archive), 37406c3fb27SDimitry Andric std::move(GetObjFileInterface)); 37506c3fb27SDimitry Andric } 37606c3fb27SDimitry Andric 37706c3fb27SDimitry Andric return make_error<StringError>(Twine("Unrecognized file type for ") + 37806c3fb27SDimitry Andric ArchiveBuffer->getBufferIdentifier(), 37906c3fb27SDimitry Andric inconvertibleErrorCode()); 38006c3fb27SDimitry Andric } 38106c3fb27SDimitry Andric 382480093f4SDimitry Andric Error StaticLibraryDefinitionGenerator::tryToGenerate( 383e8d8bef9SDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 384e8d8bef9SDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 385480093f4SDimitry Andric // Don't materialize symbols from static archives unless this is a static 386480093f4SDimitry Andric // lookup. 387480093f4SDimitry Andric if (K != LookupKind::Static) 388480093f4SDimitry Andric return Error::success(); 389480093f4SDimitry Andric 390480093f4SDimitry Andric // Bail out early if we've already freed the archive. 391480093f4SDimitry Andric if (!Archive) 392480093f4SDimitry Andric return Error::success(); 3938bcb0991SDimitry Andric 3948bcb0991SDimitry Andric DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; 3958bcb0991SDimitry Andric 396480093f4SDimitry Andric for (const auto &KV : Symbols) { 397480093f4SDimitry Andric const auto &Name = KV.first; 398bdd1243dSDimitry Andric if (!ObjectFilesMap.count(Name)) 3998bcb0991SDimitry Andric continue; 400bdd1243dSDimitry Andric auto ChildBuffer = ObjectFilesMap[Name]; 4018bcb0991SDimitry Andric ChildBufferInfos.insert( 402bdd1243dSDimitry Andric {ChildBuffer.getBuffer(), ChildBuffer.getBufferIdentifier()}); 4038bcb0991SDimitry Andric } 4048bcb0991SDimitry Andric 4058bcb0991SDimitry Andric for (auto ChildBufferInfo : ChildBufferInfos) { 4068bcb0991SDimitry Andric MemoryBufferRef ChildBufferRef(ChildBufferInfo.first, 4078bcb0991SDimitry Andric ChildBufferInfo.second); 4088bcb0991SDimitry Andric 4090eae32dcSDimitry Andric auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef); 4100eae32dcSDimitry Andric if (!I) 4110eae32dcSDimitry Andric return I.takeError(); 4120eae32dcSDimitry Andric 4130eae32dcSDimitry Andric if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false), 4140eae32dcSDimitry Andric std::move(*I))) 415480093f4SDimitry Andric return Err; 4168bcb0991SDimitry Andric } 4178bcb0991SDimitry Andric 418480093f4SDimitry Andric return Error::success(); 4198bcb0991SDimitry Andric } 4208bcb0991SDimitry Andric 421bdd1243dSDimitry Andric Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() { 422bdd1243dSDimitry Andric DenseMap<uint64_t, MemoryBufferRef> MemoryBuffers; 423bdd1243dSDimitry Andric DenseSet<uint64_t> Visited; 424bdd1243dSDimitry Andric DenseSet<uint64_t> Excluded; 425bdd1243dSDimitry Andric for (auto &S : Archive->symbols()) { 426bdd1243dSDimitry Andric StringRef SymName = S.getName(); 427bdd1243dSDimitry Andric auto Member = S.getMember(); 428bdd1243dSDimitry Andric if (!Member) 429bdd1243dSDimitry Andric return Member.takeError(); 430bdd1243dSDimitry Andric auto DataOffset = Member->getDataOffset(); 431bdd1243dSDimitry Andric if (!Visited.count(DataOffset)) { 432bdd1243dSDimitry Andric Visited.insert(DataOffset); 433bdd1243dSDimitry Andric auto Child = Member->getAsBinary(); 434bdd1243dSDimitry Andric if (!Child) 435bdd1243dSDimitry Andric return Child.takeError(); 436bdd1243dSDimitry Andric if ((*Child)->isCOFFImportFile()) { 437bdd1243dSDimitry Andric ImportedDynamicLibraries.insert((*Child)->getFileName().str()); 438bdd1243dSDimitry Andric Excluded.insert(DataOffset); 439bdd1243dSDimitry Andric continue; 440bdd1243dSDimitry Andric } 441bdd1243dSDimitry Andric MemoryBuffers[DataOffset] = (*Child)->getMemoryBufferRef(); 442bdd1243dSDimitry Andric } 443bdd1243dSDimitry Andric if (!Excluded.count(DataOffset)) 444bdd1243dSDimitry Andric ObjectFilesMap[L.getExecutionSession().intern(SymName)] = 445bdd1243dSDimitry Andric MemoryBuffers[DataOffset]; 446bdd1243dSDimitry Andric } 447bdd1243dSDimitry Andric 448bdd1243dSDimitry Andric return Error::success(); 449bdd1243dSDimitry Andric } 450bdd1243dSDimitry Andric 45106c3fb27SDimitry Andric Expected<std::pair<size_t, size_t>> 45206c3fb27SDimitry Andric StaticLibraryDefinitionGenerator::getSliceRangeForArch( 45306c3fb27SDimitry Andric object::MachOUniversalBinary &UB, const Triple &TT) { 45406c3fb27SDimitry Andric 45506c3fb27SDimitry Andric for (const auto &Obj : UB.objects()) { 45606c3fb27SDimitry Andric auto ObjTT = Obj.getTriple(); 45706c3fb27SDimitry Andric if (ObjTT.getArch() == TT.getArch() && 45806c3fb27SDimitry Andric ObjTT.getSubArch() == TT.getSubArch() && 45906c3fb27SDimitry Andric (TT.getVendor() == Triple::UnknownVendor || 46006c3fb27SDimitry Andric ObjTT.getVendor() == TT.getVendor())) { 46106c3fb27SDimitry Andric // We found a match. Return the range for the slice. 46206c3fb27SDimitry Andric return std::make_pair(Obj.getOffset(), Obj.getSize()); 46306c3fb27SDimitry Andric } 46406c3fb27SDimitry Andric } 46506c3fb27SDimitry Andric 46606c3fb27SDimitry Andric return make_error<StringError>(Twine("Universal binary ") + UB.getFileName() + 46706c3fb27SDimitry Andric " does not contain a slice for " + 46806c3fb27SDimitry Andric TT.str(), 46906c3fb27SDimitry Andric inconvertibleErrorCode()); 47006c3fb27SDimitry Andric } 47106c3fb27SDimitry Andric 4728bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( 4730eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 47406c3fb27SDimitry Andric std::unique_ptr<object::Archive> Archive, 4750eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface, Error &Err) 4760eae32dcSDimitry Andric : L(L), GetObjFileInterface(std::move(GetObjFileInterface)), 47706c3fb27SDimitry Andric ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)) { 478bdd1243dSDimitry Andric ErrorAsOutParameter _(&Err); 4790eae32dcSDimitry Andric if (!this->GetObjFileInterface) 4800eae32dcSDimitry Andric this->GetObjFileInterface = getObjectFileInterface; 481bdd1243dSDimitry Andric if (!Err) 482bdd1243dSDimitry Andric Err = buildObjectFilesMap(); 483bdd1243dSDimitry Andric } 484bdd1243dSDimitry Andric 485bdd1243dSDimitry Andric std::unique_ptr<DLLImportDefinitionGenerator> 486bdd1243dSDimitry Andric DLLImportDefinitionGenerator::Create(ExecutionSession &ES, 487bdd1243dSDimitry Andric ObjectLinkingLayer &L) { 488bdd1243dSDimitry Andric return std::unique_ptr<DLLImportDefinitionGenerator>( 489bdd1243dSDimitry Andric new DLLImportDefinitionGenerator(ES, L)); 490bdd1243dSDimitry Andric } 491bdd1243dSDimitry Andric 492bdd1243dSDimitry Andric Error DLLImportDefinitionGenerator::tryToGenerate( 493bdd1243dSDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 494bdd1243dSDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 495bdd1243dSDimitry Andric JITDylibSearchOrder LinkOrder; 496bdd1243dSDimitry Andric JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) { 497bdd1243dSDimitry Andric LinkOrder.reserve(LO.size()); 498bdd1243dSDimitry Andric for (auto &KV : LO) { 499bdd1243dSDimitry Andric if (KV.first == &JD) 500bdd1243dSDimitry Andric continue; 501bdd1243dSDimitry Andric LinkOrder.push_back(KV); 502bdd1243dSDimitry Andric } 503bdd1243dSDimitry Andric }); 504bdd1243dSDimitry Andric 505bdd1243dSDimitry Andric // FIXME: if regular symbol name start with __imp_ we have to issue lookup of 506bdd1243dSDimitry Andric // both __imp_ and stripped name and use the lookup information to resolve the 507bdd1243dSDimitry Andric // real symbol name. 508bdd1243dSDimitry Andric SymbolLookupSet LookupSet; 509bdd1243dSDimitry Andric DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols; 510bdd1243dSDimitry Andric for (auto &KV : Symbols) { 511bdd1243dSDimitry Andric StringRef Deinterned = *KV.first; 5125f757f3fSDimitry Andric if (Deinterned.starts_with(getImpPrefix())) 513bdd1243dSDimitry Andric Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size()); 514bdd1243dSDimitry Andric // Don't degrade the required state 515bdd1243dSDimitry Andric if (ToLookUpSymbols.count(Deinterned) && 516bdd1243dSDimitry Andric ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol) 517bdd1243dSDimitry Andric continue; 518bdd1243dSDimitry Andric ToLookUpSymbols[Deinterned] = KV.second; 519bdd1243dSDimitry Andric } 520bdd1243dSDimitry Andric 521bdd1243dSDimitry Andric for (auto &KV : ToLookUpSymbols) 522bdd1243dSDimitry Andric LookupSet.add(ES.intern(KV.first), KV.second); 523bdd1243dSDimitry Andric 524bdd1243dSDimitry Andric auto Resolved = 525bdd1243dSDimitry Andric ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved); 526bdd1243dSDimitry Andric if (!Resolved) 527bdd1243dSDimitry Andric return Resolved.takeError(); 528bdd1243dSDimitry Andric 529bdd1243dSDimitry Andric auto G = createStubsGraph(*Resolved); 530bdd1243dSDimitry Andric if (!G) 531bdd1243dSDimitry Andric return G.takeError(); 532bdd1243dSDimitry Andric return L.add(JD, std::move(*G)); 533bdd1243dSDimitry Andric } 534bdd1243dSDimitry Andric 535bdd1243dSDimitry Andric Expected<unsigned> 536bdd1243dSDimitry Andric DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) { 537bdd1243dSDimitry Andric switch (TT.getArch()) { 538bdd1243dSDimitry Andric case Triple::x86_64: 539bdd1243dSDimitry Andric return 8; 540bdd1243dSDimitry Andric default: 541bdd1243dSDimitry Andric return make_error<StringError>( 542bdd1243dSDimitry Andric "architecture unsupported by DLLImportDefinitionGenerator", 543bdd1243dSDimitry Andric inconvertibleErrorCode()); 544bdd1243dSDimitry Andric } 545bdd1243dSDimitry Andric } 546bdd1243dSDimitry Andric 5475f757f3fSDimitry Andric Expected<llvm::endianness> 548bdd1243dSDimitry Andric DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) { 549bdd1243dSDimitry Andric switch (TT.getArch()) { 550bdd1243dSDimitry Andric case Triple::x86_64: 5515f757f3fSDimitry Andric return llvm::endianness::little; 552bdd1243dSDimitry Andric default: 553bdd1243dSDimitry Andric return make_error<StringError>( 554bdd1243dSDimitry Andric "architecture unsupported by DLLImportDefinitionGenerator", 555bdd1243dSDimitry Andric inconvertibleErrorCode()); 556bdd1243dSDimitry Andric } 557bdd1243dSDimitry Andric } 558bdd1243dSDimitry Andric 559bdd1243dSDimitry Andric Expected<std::unique_ptr<jitlink::LinkGraph>> 560bdd1243dSDimitry Andric DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) { 56106c3fb27SDimitry Andric Triple TT = ES.getTargetTriple(); 5625f757f3fSDimitry Andric auto PointerSize = getTargetPointerSize(TT); 563bdd1243dSDimitry Andric if (!PointerSize) 564bdd1243dSDimitry Andric return PointerSize.takeError(); 565bdd1243dSDimitry Andric auto Endianness = getTargetEndianness(TT); 566bdd1243dSDimitry Andric if (!Endianness) 567bdd1243dSDimitry Andric return Endianness.takeError(); 568bdd1243dSDimitry Andric 569bdd1243dSDimitry Andric auto G = std::make_unique<jitlink::LinkGraph>( 570bdd1243dSDimitry Andric "<DLLIMPORT_STUBS>", TT, *PointerSize, *Endianness, 571bdd1243dSDimitry Andric jitlink::getGenericEdgeKindName); 572bdd1243dSDimitry Andric jitlink::Section &Sec = 573bdd1243dSDimitry Andric G->createSection(getSectionName(), MemProt::Read | MemProt::Exec); 574bdd1243dSDimitry Andric 575bdd1243dSDimitry Andric for (auto &KV : Resolved) { 576bdd1243dSDimitry Andric jitlink::Symbol &Target = G->addAbsoluteSymbol( 57706c3fb27SDimitry Andric *KV.first, KV.second.getAddress(), *PointerSize, 578bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Local, false); 579bdd1243dSDimitry Andric 580bdd1243dSDimitry Andric // Create __imp_ symbol 581bdd1243dSDimitry Andric jitlink::Symbol &Ptr = 582bdd1243dSDimitry Andric jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target); 58306c3fb27SDimitry Andric auto NameCopy = G->allocateContent(Twine(getImpPrefix()) + *KV.first); 584bdd1243dSDimitry Andric StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size()); 585bdd1243dSDimitry Andric Ptr.setName(NameCopyRef); 586bdd1243dSDimitry Andric Ptr.setLinkage(jitlink::Linkage::Strong); 587bdd1243dSDimitry Andric Ptr.setScope(jitlink::Scope::Default); 588bdd1243dSDimitry Andric 589bdd1243dSDimitry Andric // Create PLT stub 590bdd1243dSDimitry Andric // FIXME: check PLT stub of data symbol is not accessed 591bdd1243dSDimitry Andric jitlink::Block &StubBlock = 592bdd1243dSDimitry Andric jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr); 593bdd1243dSDimitry Andric G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(), 594bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, true, 595bdd1243dSDimitry Andric false); 596bdd1243dSDimitry Andric } 597bdd1243dSDimitry Andric 598bdd1243dSDimitry Andric return std::move(G); 5990eae32dcSDimitry Andric } 6008bcb0991SDimitry Andric 6010b57cec5SDimitry Andric } // End namespace orc. 6020b57cec5SDimitry Andric } // End namespace llvm. 603