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" 20*0fca6ea1SDimitry Andric #include "llvm/Support/StringSaver.h" 210b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 22fe6060f1SDimitry Andric #include <string> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric namespace orc { 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End) 280b57cec5SDimitry Andric : InitList( 290b57cec5SDimitry Andric GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr), 300b57cec5SDimitry Andric I((InitList && End) ? InitList->getNumOperands() : 0) { 310b57cec5SDimitry Andric } 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const { 340b57cec5SDimitry Andric assert(InitList == Other.InitList && "Incomparable iterators."); 350b57cec5SDimitry Andric return I == Other.I; 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const { 390b57cec5SDimitry Andric return !(*this == Other); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric CtorDtorIterator& CtorDtorIterator::operator++() { 430b57cec5SDimitry Andric ++I; 440b57cec5SDimitry Andric return *this; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric CtorDtorIterator CtorDtorIterator::operator++(int) { 480b57cec5SDimitry Andric CtorDtorIterator Temp = *this; 490b57cec5SDimitry Andric ++I; 500b57cec5SDimitry Andric return Temp; 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric CtorDtorIterator::Element CtorDtorIterator::operator*() const { 540b57cec5SDimitry Andric ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I)); 550b57cec5SDimitry Andric assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors"); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric Constant *FuncC = CS->getOperand(1); 580b57cec5SDimitry Andric Function *Func = nullptr; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // Extract function pointer, pulling off any casts. 610b57cec5SDimitry Andric while (FuncC) { 620b57cec5SDimitry Andric if (Function *F = dyn_cast_or_null<Function>(FuncC)) { 630b57cec5SDimitry Andric Func = F; 640b57cec5SDimitry Andric break; 650b57cec5SDimitry Andric } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) { 660b57cec5SDimitry Andric if (CE->isCast()) 6781ad6265SDimitry Andric FuncC = CE->getOperand(0); 680b57cec5SDimitry Andric else 690b57cec5SDimitry Andric break; 700b57cec5SDimitry Andric } else { 710b57cec5SDimitry Andric // This isn't anything we recognize. Bail out with Func left set to null. 720b57cec5SDimitry Andric break; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 768bcb0991SDimitry Andric auto *Priority = cast<ConstantInt>(CS->getOperand(0)); 770b57cec5SDimitry Andric Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr; 780b57cec5SDimitry Andric if (Data && !isa<GlobalValue>(Data)) 790b57cec5SDimitry Andric Data = nullptr; 800b57cec5SDimitry Andric return Element(Priority->getZExtValue(), Func, Data); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getConstructors(const Module &M) { 840b57cec5SDimitry Andric const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors"); 850b57cec5SDimitry Andric return make_range(CtorDtorIterator(CtorsList, false), 860b57cec5SDimitry Andric CtorDtorIterator(CtorsList, true)); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getDestructors(const Module &M) { 900b57cec5SDimitry Andric const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors"); 910b57cec5SDimitry Andric return make_range(CtorDtorIterator(DtorsList, false), 920b57cec5SDimitry Andric CtorDtorIterator(DtorsList, true)); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 955ffd83dbSDimitry Andric bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) { 965ffd83dbSDimitry Andric if (GV.isDeclaration()) 975ffd83dbSDimitry Andric return false; 985ffd83dbSDimitry Andric 995ffd83dbSDimitry Andric if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || 1005ffd83dbSDimitry Andric GV.getName() == "llvm.global_dtors")) 1015ffd83dbSDimitry Andric return true; 1025ffd83dbSDimitry Andric 1035ffd83dbSDimitry Andric if (ObjFmt == Triple::MachO) { 1045ffd83dbSDimitry Andric // FIXME: These section checks are too strict: We should match first and 1055ffd83dbSDimitry Andric // second word split by comma. 1065ffd83dbSDimitry Andric if (GV.hasSection() && 1075f757f3fSDimitry Andric (GV.getSection().starts_with("__DATA,__objc_classlist") || 1085f757f3fSDimitry Andric GV.getSection().starts_with("__DATA,__objc_selrefs"))) 1095ffd83dbSDimitry Andric return true; 1105ffd83dbSDimitry Andric } 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric return false; 1135ffd83dbSDimitry Andric } 1145ffd83dbSDimitry Andric 1150b57cec5SDimitry Andric void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) { 1168bcb0991SDimitry Andric if (CtorDtors.empty()) 1170b57cec5SDimitry Andric return; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric MangleAndInterner Mangle( 1200b57cec5SDimitry Andric JD.getExecutionSession(), 121*0fca6ea1SDimitry Andric (*CtorDtors.begin()).Func->getDataLayout()); 1220b57cec5SDimitry Andric 123480093f4SDimitry Andric for (auto CtorDtor : CtorDtors) { 1240b57cec5SDimitry Andric assert(CtorDtor.Func && CtorDtor.Func->hasName() && 1250b57cec5SDimitry Andric "Ctor/Dtor function must be named to be runnable under the JIT"); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric // FIXME: Maybe use a symbol promoter here instead. 1280b57cec5SDimitry Andric if (CtorDtor.Func->hasLocalLinkage()) { 1290b57cec5SDimitry Andric CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage); 1300b57cec5SDimitry Andric CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) { 1340b57cec5SDimitry Andric dbgs() << " Skipping because why now?\n"; 1350b57cec5SDimitry Andric continue; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric CtorDtorsByPriority[CtorDtor.Priority].push_back( 1390b57cec5SDimitry Andric Mangle(CtorDtor.Func->getName())); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric Error CtorDtorRunner::run() { 1440b57cec5SDimitry Andric using CtorDtorTy = void (*)(); 1450b57cec5SDimitry Andric 146480093f4SDimitry Andric SymbolLookupSet LookupSet; 147480093f4SDimitry Andric for (auto &KV : CtorDtorsByPriority) 148480093f4SDimitry Andric for (auto &Name : KV.second) 149480093f4SDimitry Andric LookupSet.add(Name); 150480093f4SDimitry Andric assert(!LookupSet.containsDuplicates() && 151480093f4SDimitry Andric "Ctor/Dtor list contains duplicates"); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric auto &ES = JD.getExecutionSession(); 154480093f4SDimitry Andric if (auto CtorDtorMap = ES.lookup( 155480093f4SDimitry Andric makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), 156480093f4SDimitry Andric std::move(LookupSet))) { 1570b57cec5SDimitry Andric for (auto &KV : CtorDtorsByPriority) { 1580b57cec5SDimitry Andric for (auto &Name : KV.second) { 1590b57cec5SDimitry Andric assert(CtorDtorMap->count(Name) && "No entry for Name"); 16006c3fb27SDimitry Andric auto CtorDtor = (*CtorDtorMap)[Name].getAddress().toPtr<CtorDtorTy>(); 1610b57cec5SDimitry Andric CtorDtor(); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric CtorDtorsByPriority.clear(); 1650b57cec5SDimitry Andric return Error::success(); 1660b57cec5SDimitry Andric } else 1670b57cec5SDimitry Andric return CtorDtorMap.takeError(); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric void LocalCXXRuntimeOverridesBase::runDestructors() { 1710b57cec5SDimitry Andric auto& CXXDestructorDataPairs = DSOHandleOverride; 1720b57cec5SDimitry Andric for (auto &P : CXXDestructorDataPairs) 1730b57cec5SDimitry Andric P.first(P.second); 1740b57cec5SDimitry Andric CXXDestructorDataPairs.clear(); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor, 1780b57cec5SDimitry Andric void *Arg, 1790b57cec5SDimitry Andric void *DSOHandle) { 1800b57cec5SDimitry Andric auto& CXXDestructorDataPairs = 1810b57cec5SDimitry Andric *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle); 1820b57cec5SDimitry Andric CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg)); 1830b57cec5SDimitry Andric return 0; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric Error LocalCXXRuntimeOverrides::enable(JITDylib &JD, 1870b57cec5SDimitry Andric MangleAndInterner &Mangle) { 1880b57cec5SDimitry Andric SymbolMap RuntimeInterposes; 18906c3fb27SDimitry Andric RuntimeInterposes[Mangle("__dso_handle")] = { 19006c3fb27SDimitry Andric ExecutorAddr::fromPtr(&DSOHandleOverride), JITSymbolFlags::Exported}; 19106c3fb27SDimitry Andric RuntimeInterposes[Mangle("__cxa_atexit")] = { 19206c3fb27SDimitry Andric ExecutorAddr::fromPtr(&CXAAtExitOverride), JITSymbolFlags::Exported}; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric return JD.define(absoluteSymbols(std::move(RuntimeInterposes))); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1975ffd83dbSDimitry Andric void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx, 1985ffd83dbSDimitry Andric void *DSOHandle) { 1995ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(AtExitsMutex); 2005ffd83dbSDimitry Andric AtExitRecords[DSOHandle].push_back({F, Ctx}); 2015ffd83dbSDimitry Andric } 2025ffd83dbSDimitry Andric 2035ffd83dbSDimitry Andric void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) { 2045ffd83dbSDimitry Andric std::vector<AtExitRecord> AtExitsToRun; 2055ffd83dbSDimitry Andric 2065ffd83dbSDimitry Andric { 2075ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(AtExitsMutex); 2085ffd83dbSDimitry Andric auto I = AtExitRecords.find(DSOHandle); 2095ffd83dbSDimitry Andric if (I != AtExitRecords.end()) { 2105ffd83dbSDimitry Andric AtExitsToRun = std::move(I->second); 2115ffd83dbSDimitry Andric AtExitRecords.erase(I); 2125ffd83dbSDimitry Andric } 2135ffd83dbSDimitry Andric } 2145ffd83dbSDimitry Andric 2155ffd83dbSDimitry Andric while (!AtExitsToRun.empty()) { 2165ffd83dbSDimitry Andric AtExitsToRun.back().F(AtExitsToRun.back().Ctx); 2175ffd83dbSDimitry Andric AtExitsToRun.pop_back(); 2185ffd83dbSDimitry Andric } 2195ffd83dbSDimitry Andric } 2205ffd83dbSDimitry Andric 2210b57cec5SDimitry Andric DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator( 2221db9f3b2SDimitry Andric sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow, 2231db9f3b2SDimitry Andric AddAbsoluteSymbolsFn AddAbsoluteSymbols) 2240b57cec5SDimitry Andric : Dylib(std::move(Dylib)), Allow(std::move(Allow)), 2251db9f3b2SDimitry Andric AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)), 2260b57cec5SDimitry Andric GlobalPrefix(GlobalPrefix) {} 2270b57cec5SDimitry Andric 2288bcb0991SDimitry Andric Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 2290b57cec5SDimitry Andric DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, 2301db9f3b2SDimitry Andric SymbolPredicate Allow, 2311db9f3b2SDimitry Andric AddAbsoluteSymbolsFn AddAbsoluteSymbols) { 2320b57cec5SDimitry Andric std::string ErrMsg; 2330b57cec5SDimitry Andric auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg); 2340b57cec5SDimitry Andric if (!Lib.isValid()) 2350b57cec5SDimitry Andric return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 2368bcb0991SDimitry Andric return std::make_unique<DynamicLibrarySearchGenerator>( 2371db9f3b2SDimitry Andric std::move(Lib), GlobalPrefix, std::move(Allow), 2381db9f3b2SDimitry Andric std::move(AddAbsoluteSymbols)); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric 241480093f4SDimitry Andric Error DynamicLibrarySearchGenerator::tryToGenerate( 242e8d8bef9SDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 243e8d8bef9SDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 2440b57cec5SDimitry Andric orc::SymbolMap NewSymbols; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric bool HasGlobalPrefix = (GlobalPrefix != '\0'); 2470b57cec5SDimitry Andric 248480093f4SDimitry Andric for (auto &KV : Symbols) { 249480093f4SDimitry Andric auto &Name = KV.first; 250480093f4SDimitry Andric 2510b57cec5SDimitry Andric if ((*Name).empty()) 2520b57cec5SDimitry Andric continue; 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric if (Allow && !Allow(Name)) 2550b57cec5SDimitry Andric continue; 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric if (HasGlobalPrefix && (*Name).front() != GlobalPrefix) 2580b57cec5SDimitry Andric continue; 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric std::string Tmp((*Name).data() + HasGlobalPrefix, 2610b57cec5SDimitry Andric (*Name).size() - HasGlobalPrefix); 26206c3fb27SDimitry Andric if (void *P = Dylib.getAddressOfSymbol(Tmp.c_str())) 26306c3fb27SDimitry Andric NewSymbols[Name] = {ExecutorAddr::fromPtr(P), JITSymbolFlags::Exported}; 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 266480093f4SDimitry Andric if (NewSymbols.empty()) 267480093f4SDimitry Andric return Error::success(); 2680b57cec5SDimitry Andric 2691db9f3b2SDimitry Andric if (AddAbsoluteSymbols) 2701db9f3b2SDimitry Andric return AddAbsoluteSymbols(JD, std::move(NewSymbols)); 271480093f4SDimitry Andric return JD.define(absoluteSymbols(std::move(NewSymbols))); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2748bcb0991SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 2750eae32dcSDimitry Andric StaticLibraryDefinitionGenerator::Load( 2760eae32dcSDimitry Andric ObjectLayer &L, const char *FileName, 2770eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface) { 2780eae32dcSDimitry Andric 2795ffd83dbSDimitry Andric auto B = object::createBinary(FileName); 2805ffd83dbSDimitry Andric if (!B) 28181ad6265SDimitry Andric return createFileError(FileName, B.takeError()); 2825ffd83dbSDimitry Andric 2835ffd83dbSDimitry Andric // If this is a regular archive then create an instance from it. 28406c3fb27SDimitry Andric if (isa<object::Archive>(B->getBinary())) { 28506c3fb27SDimitry Andric auto [Archive, ArchiveBuffer] = B->takeBinary(); 28606c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), 28706c3fb27SDimitry Andric std::unique_ptr<object::Archive>( 28806c3fb27SDimitry Andric static_cast<object::Archive *>(Archive.release())), 2890eae32dcSDimitry Andric std::move(GetObjFileInterface)); 29006c3fb27SDimitry Andric } 2915ffd83dbSDimitry Andric 2925ffd83dbSDimitry Andric // If this is a universal binary then search for a slice matching the given 2935ffd83dbSDimitry Andric // Triple. 2945f757f3fSDimitry Andric if (auto *UB = dyn_cast<object::MachOUniversalBinary>(B->getBinary())) { 29506c3fb27SDimitry Andric 29606c3fb27SDimitry Andric const auto &TT = L.getExecutionSession().getTargetTriple(); 29706c3fb27SDimitry Andric 29806c3fb27SDimitry Andric auto SliceRange = getSliceRangeForArch(*UB, TT); 29906c3fb27SDimitry Andric if (!SliceRange) 30006c3fb27SDimitry Andric return SliceRange.takeError(); 30106c3fb27SDimitry Andric 30206c3fb27SDimitry Andric auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, SliceRange->second, 30306c3fb27SDimitry Andric SliceRange->first); 3045ffd83dbSDimitry Andric if (!SliceBuffer) 3055ffd83dbSDimitry Andric return make_error<StringError>( 3065ffd83dbSDimitry Andric Twine("Could not create buffer for ") + TT.str() + " slice of " + 30706c3fb27SDimitry Andric FileName + ": [ " + formatv("{0:x}", SliceRange->first) + " .. " + 30806c3fb27SDimitry Andric formatv("{0:x}", SliceRange->first + SliceRange->second) + ": " + 30906c3fb27SDimitry Andric SliceBuffer.getError().message(), 3105ffd83dbSDimitry Andric SliceBuffer.getError()); 3115ffd83dbSDimitry Andric 31206c3fb27SDimitry Andric return Create(L, std::move(*SliceBuffer), std::move(GetObjFileInterface)); 3135ffd83dbSDimitry Andric } 3145ffd83dbSDimitry Andric 3155ffd83dbSDimitry Andric return make_error<StringError>(Twine("Unrecognized file type for ") + 3165ffd83dbSDimitry Andric FileName, 3175ffd83dbSDimitry Andric inconvertibleErrorCode()); 3185ffd83dbSDimitry Andric } 3195ffd83dbSDimitry Andric 3205ffd83dbSDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 3218bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::Create( 3220eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 32306c3fb27SDimitry Andric std::unique_ptr<object::Archive> Archive, 3240eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface) { 32506c3fb27SDimitry Andric 3268bcb0991SDimitry Andric Error Err = Error::success(); 3278bcb0991SDimitry Andric 3288bcb0991SDimitry Andric std::unique_ptr<StaticLibraryDefinitionGenerator> ADG( 3290eae32dcSDimitry Andric new StaticLibraryDefinitionGenerator( 33006c3fb27SDimitry Andric L, std::move(ArchiveBuffer), std::move(Archive), 33106c3fb27SDimitry Andric std::move(GetObjFileInterface), Err)); 3328bcb0991SDimitry Andric 3338bcb0991SDimitry Andric if (Err) 3348bcb0991SDimitry Andric return std::move(Err); 3358bcb0991SDimitry Andric 3368bcb0991SDimitry Andric return std::move(ADG); 3378bcb0991SDimitry Andric } 3388bcb0991SDimitry Andric 33906c3fb27SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 34006c3fb27SDimitry Andric StaticLibraryDefinitionGenerator::Create( 34106c3fb27SDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 34206c3fb27SDimitry Andric GetObjectFileInterface GetObjFileInterface) { 34306c3fb27SDimitry Andric 34406c3fb27SDimitry Andric auto B = object::createBinary(ArchiveBuffer->getMemBufferRef()); 34506c3fb27SDimitry Andric if (!B) 34606c3fb27SDimitry Andric return B.takeError(); 34706c3fb27SDimitry Andric 34806c3fb27SDimitry Andric // If this is a regular archive then create an instance from it. 34906c3fb27SDimitry Andric if (isa<object::Archive>(*B)) 35006c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), 35106c3fb27SDimitry Andric std::unique_ptr<object::Archive>( 35206c3fb27SDimitry Andric static_cast<object::Archive *>(B->release())), 35306c3fb27SDimitry Andric std::move(GetObjFileInterface)); 35406c3fb27SDimitry Andric 35506c3fb27SDimitry Andric // If this is a universal binary then search for a slice matching the given 35606c3fb27SDimitry Andric // Triple. 3575f757f3fSDimitry Andric if (auto *UB = dyn_cast<object::MachOUniversalBinary>(B->get())) { 35806c3fb27SDimitry Andric 35906c3fb27SDimitry Andric const auto &TT = L.getExecutionSession().getTargetTriple(); 36006c3fb27SDimitry Andric 36106c3fb27SDimitry Andric auto SliceRange = getSliceRangeForArch(*UB, TT); 36206c3fb27SDimitry Andric if (!SliceRange) 36306c3fb27SDimitry Andric return SliceRange.takeError(); 36406c3fb27SDimitry Andric 36506c3fb27SDimitry Andric MemoryBufferRef SliceRef( 36606c3fb27SDimitry Andric StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first, 36706c3fb27SDimitry Andric SliceRange->second), 36806c3fb27SDimitry Andric ArchiveBuffer->getBufferIdentifier()); 36906c3fb27SDimitry Andric 37006c3fb27SDimitry Andric auto Archive = object::Archive::create(SliceRef); 37106c3fb27SDimitry Andric if (!Archive) 37206c3fb27SDimitry Andric return Archive.takeError(); 37306c3fb27SDimitry Andric 37406c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), std::move(*Archive), 37506c3fb27SDimitry Andric std::move(GetObjFileInterface)); 37606c3fb27SDimitry Andric } 37706c3fb27SDimitry Andric 37806c3fb27SDimitry Andric return make_error<StringError>(Twine("Unrecognized file type for ") + 37906c3fb27SDimitry Andric ArchiveBuffer->getBufferIdentifier(), 38006c3fb27SDimitry Andric inconvertibleErrorCode()); 38106c3fb27SDimitry Andric } 38206c3fb27SDimitry Andric 383480093f4SDimitry Andric Error StaticLibraryDefinitionGenerator::tryToGenerate( 384e8d8bef9SDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 385e8d8bef9SDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 386480093f4SDimitry Andric // Don't materialize symbols from static archives unless this is a static 387480093f4SDimitry Andric // lookup. 388480093f4SDimitry Andric if (K != LookupKind::Static) 389480093f4SDimitry Andric return Error::success(); 390480093f4SDimitry Andric 391480093f4SDimitry Andric // Bail out early if we've already freed the archive. 392480093f4SDimitry Andric if (!Archive) 393480093f4SDimitry Andric return Error::success(); 3948bcb0991SDimitry Andric 3958bcb0991SDimitry Andric DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; 3968bcb0991SDimitry Andric 397480093f4SDimitry Andric for (const auto &KV : Symbols) { 398480093f4SDimitry Andric const auto &Name = KV.first; 399bdd1243dSDimitry Andric if (!ObjectFilesMap.count(Name)) 4008bcb0991SDimitry Andric continue; 401bdd1243dSDimitry Andric auto ChildBuffer = ObjectFilesMap[Name]; 4028bcb0991SDimitry Andric ChildBufferInfos.insert( 403bdd1243dSDimitry Andric {ChildBuffer.getBuffer(), ChildBuffer.getBufferIdentifier()}); 4048bcb0991SDimitry Andric } 4058bcb0991SDimitry Andric 4068bcb0991SDimitry Andric for (auto ChildBufferInfo : ChildBufferInfos) { 4078bcb0991SDimitry Andric MemoryBufferRef ChildBufferRef(ChildBufferInfo.first, 4088bcb0991SDimitry Andric ChildBufferInfo.second); 4098bcb0991SDimitry Andric 4100eae32dcSDimitry Andric auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef); 4110eae32dcSDimitry Andric if (!I) 4120eae32dcSDimitry Andric return I.takeError(); 4130eae32dcSDimitry Andric 4140eae32dcSDimitry Andric if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false), 4150eae32dcSDimitry Andric std::move(*I))) 416480093f4SDimitry Andric return Err; 4178bcb0991SDimitry Andric } 4188bcb0991SDimitry Andric 419480093f4SDimitry Andric return Error::success(); 4208bcb0991SDimitry Andric } 4218bcb0991SDimitry Andric 422bdd1243dSDimitry Andric Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() { 423bdd1243dSDimitry Andric DenseMap<uint64_t, MemoryBufferRef> MemoryBuffers; 424bdd1243dSDimitry Andric DenseSet<uint64_t> Visited; 425bdd1243dSDimitry Andric DenseSet<uint64_t> Excluded; 426*0fca6ea1SDimitry Andric StringSaver FileNames(ObjFileNameStorage); 427bdd1243dSDimitry Andric for (auto &S : Archive->symbols()) { 428bdd1243dSDimitry Andric StringRef SymName = S.getName(); 429bdd1243dSDimitry Andric auto Member = S.getMember(); 430bdd1243dSDimitry Andric if (!Member) 431bdd1243dSDimitry Andric return Member.takeError(); 432bdd1243dSDimitry Andric auto DataOffset = Member->getDataOffset(); 433bdd1243dSDimitry Andric if (!Visited.count(DataOffset)) { 434bdd1243dSDimitry Andric Visited.insert(DataOffset); 435bdd1243dSDimitry Andric auto Child = Member->getAsBinary(); 436bdd1243dSDimitry Andric if (!Child) 437bdd1243dSDimitry Andric return Child.takeError(); 438bdd1243dSDimitry Andric if ((*Child)->isCOFFImportFile()) { 439bdd1243dSDimitry Andric ImportedDynamicLibraries.insert((*Child)->getFileName().str()); 440bdd1243dSDimitry Andric Excluded.insert(DataOffset); 441bdd1243dSDimitry Andric continue; 442bdd1243dSDimitry Andric } 443*0fca6ea1SDimitry Andric 444*0fca6ea1SDimitry Andric // Give members of the archive a name that contains the archive path so 445*0fca6ea1SDimitry Andric // that they can be differentiated from a member with the same name in a 446*0fca6ea1SDimitry Andric // different archive. This also ensure initializer symbols names will be 447*0fca6ea1SDimitry Andric // unique within a JITDylib. 448*0fca6ea1SDimitry Andric StringRef FullName = FileNames.save(Archive->getFileName() + "(" + 449*0fca6ea1SDimitry Andric (*Child)->getFileName() + ")"); 450*0fca6ea1SDimitry Andric MemoryBufferRef MemBuffer((*Child)->getMemoryBufferRef().getBuffer(), 451*0fca6ea1SDimitry Andric FullName); 452*0fca6ea1SDimitry Andric 453*0fca6ea1SDimitry Andric MemoryBuffers[DataOffset] = MemBuffer; 454bdd1243dSDimitry Andric } 455bdd1243dSDimitry Andric if (!Excluded.count(DataOffset)) 456bdd1243dSDimitry Andric ObjectFilesMap[L.getExecutionSession().intern(SymName)] = 457bdd1243dSDimitry Andric MemoryBuffers[DataOffset]; 458bdd1243dSDimitry Andric } 459bdd1243dSDimitry Andric 460bdd1243dSDimitry Andric return Error::success(); 461bdd1243dSDimitry Andric } 462bdd1243dSDimitry Andric 46306c3fb27SDimitry Andric Expected<std::pair<size_t, size_t>> 46406c3fb27SDimitry Andric StaticLibraryDefinitionGenerator::getSliceRangeForArch( 46506c3fb27SDimitry Andric object::MachOUniversalBinary &UB, const Triple &TT) { 46606c3fb27SDimitry Andric 46706c3fb27SDimitry Andric for (const auto &Obj : UB.objects()) { 46806c3fb27SDimitry Andric auto ObjTT = Obj.getTriple(); 46906c3fb27SDimitry Andric if (ObjTT.getArch() == TT.getArch() && 47006c3fb27SDimitry Andric ObjTT.getSubArch() == TT.getSubArch() && 47106c3fb27SDimitry Andric (TT.getVendor() == Triple::UnknownVendor || 47206c3fb27SDimitry Andric ObjTT.getVendor() == TT.getVendor())) { 47306c3fb27SDimitry Andric // We found a match. Return the range for the slice. 47406c3fb27SDimitry Andric return std::make_pair(Obj.getOffset(), Obj.getSize()); 47506c3fb27SDimitry Andric } 47606c3fb27SDimitry Andric } 47706c3fb27SDimitry Andric 47806c3fb27SDimitry Andric return make_error<StringError>(Twine("Universal binary ") + UB.getFileName() + 47906c3fb27SDimitry Andric " does not contain a slice for " + 48006c3fb27SDimitry Andric TT.str(), 48106c3fb27SDimitry Andric inconvertibleErrorCode()); 48206c3fb27SDimitry Andric } 48306c3fb27SDimitry Andric 4848bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( 4850eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 48606c3fb27SDimitry Andric std::unique_ptr<object::Archive> Archive, 4870eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface, Error &Err) 4880eae32dcSDimitry Andric : L(L), GetObjFileInterface(std::move(GetObjFileInterface)), 48906c3fb27SDimitry Andric ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)) { 490bdd1243dSDimitry Andric ErrorAsOutParameter _(&Err); 4910eae32dcSDimitry Andric if (!this->GetObjFileInterface) 4920eae32dcSDimitry Andric this->GetObjFileInterface = getObjectFileInterface; 493bdd1243dSDimitry Andric if (!Err) 494bdd1243dSDimitry Andric Err = buildObjectFilesMap(); 495bdd1243dSDimitry Andric } 496bdd1243dSDimitry Andric 497bdd1243dSDimitry Andric std::unique_ptr<DLLImportDefinitionGenerator> 498bdd1243dSDimitry Andric DLLImportDefinitionGenerator::Create(ExecutionSession &ES, 499bdd1243dSDimitry Andric ObjectLinkingLayer &L) { 500bdd1243dSDimitry Andric return std::unique_ptr<DLLImportDefinitionGenerator>( 501bdd1243dSDimitry Andric new DLLImportDefinitionGenerator(ES, L)); 502bdd1243dSDimitry Andric } 503bdd1243dSDimitry Andric 504bdd1243dSDimitry Andric Error DLLImportDefinitionGenerator::tryToGenerate( 505bdd1243dSDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 506bdd1243dSDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 507bdd1243dSDimitry Andric JITDylibSearchOrder LinkOrder; 508bdd1243dSDimitry Andric JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) { 509bdd1243dSDimitry Andric LinkOrder.reserve(LO.size()); 510bdd1243dSDimitry Andric for (auto &KV : LO) { 511bdd1243dSDimitry Andric if (KV.first == &JD) 512bdd1243dSDimitry Andric continue; 513bdd1243dSDimitry Andric LinkOrder.push_back(KV); 514bdd1243dSDimitry Andric } 515bdd1243dSDimitry Andric }); 516bdd1243dSDimitry Andric 517bdd1243dSDimitry Andric // FIXME: if regular symbol name start with __imp_ we have to issue lookup of 518bdd1243dSDimitry Andric // both __imp_ and stripped name and use the lookup information to resolve the 519bdd1243dSDimitry Andric // real symbol name. 520bdd1243dSDimitry Andric SymbolLookupSet LookupSet; 521bdd1243dSDimitry Andric DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols; 522bdd1243dSDimitry Andric for (auto &KV : Symbols) { 523bdd1243dSDimitry Andric StringRef Deinterned = *KV.first; 5245f757f3fSDimitry Andric if (Deinterned.starts_with(getImpPrefix())) 525bdd1243dSDimitry Andric Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size()); 526bdd1243dSDimitry Andric // Don't degrade the required state 527bdd1243dSDimitry Andric if (ToLookUpSymbols.count(Deinterned) && 528bdd1243dSDimitry Andric ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol) 529bdd1243dSDimitry Andric continue; 530bdd1243dSDimitry Andric ToLookUpSymbols[Deinterned] = KV.second; 531bdd1243dSDimitry Andric } 532bdd1243dSDimitry Andric 533bdd1243dSDimitry Andric for (auto &KV : ToLookUpSymbols) 534bdd1243dSDimitry Andric LookupSet.add(ES.intern(KV.first), KV.second); 535bdd1243dSDimitry Andric 536bdd1243dSDimitry Andric auto Resolved = 537bdd1243dSDimitry Andric ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved); 538bdd1243dSDimitry Andric if (!Resolved) 539bdd1243dSDimitry Andric return Resolved.takeError(); 540bdd1243dSDimitry Andric 541bdd1243dSDimitry Andric auto G = createStubsGraph(*Resolved); 542bdd1243dSDimitry Andric if (!G) 543bdd1243dSDimitry Andric return G.takeError(); 544bdd1243dSDimitry Andric return L.add(JD, std::move(*G)); 545bdd1243dSDimitry Andric } 546bdd1243dSDimitry Andric 547bdd1243dSDimitry Andric Expected<unsigned> 548bdd1243dSDimitry Andric DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) { 549bdd1243dSDimitry Andric switch (TT.getArch()) { 550bdd1243dSDimitry Andric case Triple::x86_64: 551bdd1243dSDimitry Andric return 8; 552bdd1243dSDimitry Andric default: 553bdd1243dSDimitry Andric return make_error<StringError>( 554bdd1243dSDimitry Andric "architecture unsupported by DLLImportDefinitionGenerator", 555bdd1243dSDimitry Andric inconvertibleErrorCode()); 556bdd1243dSDimitry Andric } 557bdd1243dSDimitry Andric } 558bdd1243dSDimitry Andric 5595f757f3fSDimitry Andric Expected<llvm::endianness> 560*0fca6ea1SDimitry Andric DLLImportDefinitionGenerator::getEndianness(const Triple &TT) { 561bdd1243dSDimitry Andric switch (TT.getArch()) { 562bdd1243dSDimitry Andric case Triple::x86_64: 5635f757f3fSDimitry Andric return llvm::endianness::little; 564bdd1243dSDimitry Andric default: 565bdd1243dSDimitry Andric return make_error<StringError>( 566bdd1243dSDimitry Andric "architecture unsupported by DLLImportDefinitionGenerator", 567bdd1243dSDimitry Andric inconvertibleErrorCode()); 568bdd1243dSDimitry Andric } 569bdd1243dSDimitry Andric } 570bdd1243dSDimitry Andric 571bdd1243dSDimitry Andric Expected<std::unique_ptr<jitlink::LinkGraph>> 572bdd1243dSDimitry Andric DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) { 57306c3fb27SDimitry Andric Triple TT = ES.getTargetTriple(); 5745f757f3fSDimitry Andric auto PointerSize = getTargetPointerSize(TT); 575bdd1243dSDimitry Andric if (!PointerSize) 576bdd1243dSDimitry Andric return PointerSize.takeError(); 577*0fca6ea1SDimitry Andric auto Endianness = getEndianness(TT); 578bdd1243dSDimitry Andric if (!Endianness) 579bdd1243dSDimitry Andric return Endianness.takeError(); 580bdd1243dSDimitry Andric 581bdd1243dSDimitry Andric auto G = std::make_unique<jitlink::LinkGraph>( 582bdd1243dSDimitry Andric "<DLLIMPORT_STUBS>", TT, *PointerSize, *Endianness, 583bdd1243dSDimitry Andric jitlink::getGenericEdgeKindName); 584bdd1243dSDimitry Andric jitlink::Section &Sec = 585bdd1243dSDimitry Andric G->createSection(getSectionName(), MemProt::Read | MemProt::Exec); 586bdd1243dSDimitry Andric 587bdd1243dSDimitry Andric for (auto &KV : Resolved) { 588bdd1243dSDimitry Andric jitlink::Symbol &Target = G->addAbsoluteSymbol( 58906c3fb27SDimitry Andric *KV.first, KV.second.getAddress(), *PointerSize, 590bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Local, false); 591bdd1243dSDimitry Andric 592bdd1243dSDimitry Andric // Create __imp_ symbol 593bdd1243dSDimitry Andric jitlink::Symbol &Ptr = 594bdd1243dSDimitry Andric jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target); 59506c3fb27SDimitry Andric auto NameCopy = G->allocateContent(Twine(getImpPrefix()) + *KV.first); 596bdd1243dSDimitry Andric StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size()); 597bdd1243dSDimitry Andric Ptr.setName(NameCopyRef); 598bdd1243dSDimitry Andric Ptr.setLinkage(jitlink::Linkage::Strong); 599bdd1243dSDimitry Andric Ptr.setScope(jitlink::Scope::Default); 600bdd1243dSDimitry Andric 601bdd1243dSDimitry Andric // Create PLT stub 602bdd1243dSDimitry Andric // FIXME: check PLT stub of data symbol is not accessed 603bdd1243dSDimitry Andric jitlink::Block &StubBlock = 604bdd1243dSDimitry Andric jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr); 605bdd1243dSDimitry Andric G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(), 606bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, true, 607bdd1243dSDimitry Andric false); 608bdd1243dSDimitry Andric } 609bdd1243dSDimitry Andric 610bdd1243dSDimitry Andric return std::move(G); 6110eae32dcSDimitry Andric } 6128bcb0991SDimitry Andric 6130b57cec5SDimitry Andric } // End namespace orc. 6140b57cec5SDimitry Andric } // End namespace llvm. 615