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() && 1065ffd83dbSDimitry Andric (GV.getSection().startswith("__DATA,__objc_classlist") || 1075ffd83dbSDimitry Andric GV.getSection().startswith("__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"); 159*06c3fb27SDimitry 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; 188*06c3fb27SDimitry Andric RuntimeInterposes[Mangle("__dso_handle")] = { 189*06c3fb27SDimitry Andric ExecutorAddr::fromPtr(&DSOHandleOverride), JITSymbolFlags::Exported}; 190*06c3fb27SDimitry Andric RuntimeInterposes[Mangle("__cxa_atexit")] = { 191*06c3fb27SDimitry 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( 2210b57cec5SDimitry Andric sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow) 2220b57cec5SDimitry Andric : Dylib(std::move(Dylib)), Allow(std::move(Allow)), 2230b57cec5SDimitry Andric GlobalPrefix(GlobalPrefix) {} 2240b57cec5SDimitry Andric 2258bcb0991SDimitry Andric Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 2260b57cec5SDimitry Andric DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, 2270b57cec5SDimitry Andric SymbolPredicate Allow) { 2280b57cec5SDimitry Andric std::string ErrMsg; 2290b57cec5SDimitry Andric auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg); 2300b57cec5SDimitry Andric if (!Lib.isValid()) 2310b57cec5SDimitry Andric return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 2328bcb0991SDimitry Andric return std::make_unique<DynamicLibrarySearchGenerator>( 2338bcb0991SDimitry Andric std::move(Lib), GlobalPrefix, std::move(Allow)); 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 236480093f4SDimitry Andric Error DynamicLibrarySearchGenerator::tryToGenerate( 237e8d8bef9SDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 238e8d8bef9SDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 2390b57cec5SDimitry Andric orc::SymbolMap NewSymbols; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric bool HasGlobalPrefix = (GlobalPrefix != '\0'); 2420b57cec5SDimitry Andric 243480093f4SDimitry Andric for (auto &KV : Symbols) { 244480093f4SDimitry Andric auto &Name = KV.first; 245480093f4SDimitry Andric 2460b57cec5SDimitry Andric if ((*Name).empty()) 2470b57cec5SDimitry Andric continue; 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric if (Allow && !Allow(Name)) 2500b57cec5SDimitry Andric continue; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric if (HasGlobalPrefix && (*Name).front() != GlobalPrefix) 2530b57cec5SDimitry Andric continue; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric std::string Tmp((*Name).data() + HasGlobalPrefix, 2560b57cec5SDimitry Andric (*Name).size() - HasGlobalPrefix); 257*06c3fb27SDimitry Andric if (void *P = Dylib.getAddressOfSymbol(Tmp.c_str())) 258*06c3fb27SDimitry Andric NewSymbols[Name] = {ExecutorAddr::fromPtr(P), JITSymbolFlags::Exported}; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 261480093f4SDimitry Andric if (NewSymbols.empty()) 262480093f4SDimitry Andric return Error::success(); 2630b57cec5SDimitry Andric 264480093f4SDimitry Andric return JD.define(absoluteSymbols(std::move(NewSymbols))); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2678bcb0991SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 2680eae32dcSDimitry Andric StaticLibraryDefinitionGenerator::Load( 2690eae32dcSDimitry Andric ObjectLayer &L, const char *FileName, 2700eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface) { 2710eae32dcSDimitry Andric 2725ffd83dbSDimitry Andric auto B = object::createBinary(FileName); 2735ffd83dbSDimitry Andric if (!B) 27481ad6265SDimitry Andric return createFileError(FileName, B.takeError()); 2755ffd83dbSDimitry Andric 2765ffd83dbSDimitry Andric // If this is a regular archive then create an instance from it. 277*06c3fb27SDimitry Andric if (isa<object::Archive>(B->getBinary())) { 278*06c3fb27SDimitry Andric auto [Archive, ArchiveBuffer] = B->takeBinary(); 279*06c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), 280*06c3fb27SDimitry Andric std::unique_ptr<object::Archive>( 281*06c3fb27SDimitry Andric static_cast<object::Archive *>(Archive.release())), 2820eae32dcSDimitry Andric std::move(GetObjFileInterface)); 283*06c3fb27SDimitry Andric } 2845ffd83dbSDimitry Andric 2855ffd83dbSDimitry Andric // If this is a universal binary then search for a slice matching the given 2865ffd83dbSDimitry Andric // Triple. 2875ffd83dbSDimitry Andric if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) { 288*06c3fb27SDimitry Andric 289*06c3fb27SDimitry Andric const auto &TT = L.getExecutionSession().getTargetTriple(); 290*06c3fb27SDimitry Andric 291*06c3fb27SDimitry Andric auto SliceRange = getSliceRangeForArch(*UB, TT); 292*06c3fb27SDimitry Andric if (!SliceRange) 293*06c3fb27SDimitry Andric return SliceRange.takeError(); 294*06c3fb27SDimitry Andric 295*06c3fb27SDimitry Andric auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, SliceRange->second, 296*06c3fb27SDimitry Andric SliceRange->first); 2975ffd83dbSDimitry Andric if (!SliceBuffer) 2985ffd83dbSDimitry Andric return make_error<StringError>( 2995ffd83dbSDimitry Andric Twine("Could not create buffer for ") + TT.str() + " slice of " + 300*06c3fb27SDimitry Andric FileName + ": [ " + formatv("{0:x}", SliceRange->first) + " .. " + 301*06c3fb27SDimitry Andric formatv("{0:x}", SliceRange->first + SliceRange->second) + ": " + 302*06c3fb27SDimitry Andric SliceBuffer.getError().message(), 3035ffd83dbSDimitry Andric SliceBuffer.getError()); 3045ffd83dbSDimitry Andric 305*06c3fb27SDimitry Andric return Create(L, std::move(*SliceBuffer), std::move(GetObjFileInterface)); 3065ffd83dbSDimitry Andric } 3075ffd83dbSDimitry Andric 3085ffd83dbSDimitry Andric return make_error<StringError>(Twine("Unrecognized file type for ") + 3095ffd83dbSDimitry Andric FileName, 3105ffd83dbSDimitry Andric inconvertibleErrorCode()); 3115ffd83dbSDimitry Andric } 3125ffd83dbSDimitry Andric 3135ffd83dbSDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 3148bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::Create( 3150eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 316*06c3fb27SDimitry Andric std::unique_ptr<object::Archive> Archive, 3170eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface) { 318*06c3fb27SDimitry Andric 3198bcb0991SDimitry Andric Error Err = Error::success(); 3208bcb0991SDimitry Andric 3218bcb0991SDimitry Andric std::unique_ptr<StaticLibraryDefinitionGenerator> ADG( 3220eae32dcSDimitry Andric new StaticLibraryDefinitionGenerator( 323*06c3fb27SDimitry Andric L, std::move(ArchiveBuffer), std::move(Archive), 324*06c3fb27SDimitry Andric std::move(GetObjFileInterface), Err)); 3258bcb0991SDimitry Andric 3268bcb0991SDimitry Andric if (Err) 3278bcb0991SDimitry Andric return std::move(Err); 3288bcb0991SDimitry Andric 3298bcb0991SDimitry Andric return std::move(ADG); 3308bcb0991SDimitry Andric } 3318bcb0991SDimitry Andric 332*06c3fb27SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 333*06c3fb27SDimitry Andric StaticLibraryDefinitionGenerator::Create( 334*06c3fb27SDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 335*06c3fb27SDimitry Andric GetObjectFileInterface GetObjFileInterface) { 336*06c3fb27SDimitry Andric 337*06c3fb27SDimitry Andric auto B = object::createBinary(ArchiveBuffer->getMemBufferRef()); 338*06c3fb27SDimitry Andric if (!B) 339*06c3fb27SDimitry Andric return B.takeError(); 340*06c3fb27SDimitry Andric 341*06c3fb27SDimitry Andric // If this is a regular archive then create an instance from it. 342*06c3fb27SDimitry Andric if (isa<object::Archive>(*B)) 343*06c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), 344*06c3fb27SDimitry Andric std::unique_ptr<object::Archive>( 345*06c3fb27SDimitry Andric static_cast<object::Archive *>(B->release())), 346*06c3fb27SDimitry Andric std::move(GetObjFileInterface)); 347*06c3fb27SDimitry Andric 348*06c3fb27SDimitry Andric // If this is a universal binary then search for a slice matching the given 349*06c3fb27SDimitry Andric // Triple. 350*06c3fb27SDimitry Andric if (auto *UB = cast<object::MachOUniversalBinary>(B->get())) { 351*06c3fb27SDimitry Andric 352*06c3fb27SDimitry Andric const auto &TT = L.getExecutionSession().getTargetTriple(); 353*06c3fb27SDimitry Andric 354*06c3fb27SDimitry Andric auto SliceRange = getSliceRangeForArch(*UB, TT); 355*06c3fb27SDimitry Andric if (!SliceRange) 356*06c3fb27SDimitry Andric return SliceRange.takeError(); 357*06c3fb27SDimitry Andric 358*06c3fb27SDimitry Andric MemoryBufferRef SliceRef( 359*06c3fb27SDimitry Andric StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first, 360*06c3fb27SDimitry Andric SliceRange->second), 361*06c3fb27SDimitry Andric ArchiveBuffer->getBufferIdentifier()); 362*06c3fb27SDimitry Andric 363*06c3fb27SDimitry Andric auto Archive = object::Archive::create(SliceRef); 364*06c3fb27SDimitry Andric if (!Archive) 365*06c3fb27SDimitry Andric return Archive.takeError(); 366*06c3fb27SDimitry Andric 367*06c3fb27SDimitry Andric return Create(L, std::move(ArchiveBuffer), std::move(*Archive), 368*06c3fb27SDimitry Andric std::move(GetObjFileInterface)); 369*06c3fb27SDimitry Andric } 370*06c3fb27SDimitry Andric 371*06c3fb27SDimitry Andric return make_error<StringError>(Twine("Unrecognized file type for ") + 372*06c3fb27SDimitry Andric ArchiveBuffer->getBufferIdentifier(), 373*06c3fb27SDimitry Andric inconvertibleErrorCode()); 374*06c3fb27SDimitry Andric } 375*06c3fb27SDimitry Andric 376480093f4SDimitry Andric Error StaticLibraryDefinitionGenerator::tryToGenerate( 377e8d8bef9SDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 378e8d8bef9SDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 379480093f4SDimitry Andric // Don't materialize symbols from static archives unless this is a static 380480093f4SDimitry Andric // lookup. 381480093f4SDimitry Andric if (K != LookupKind::Static) 382480093f4SDimitry Andric return Error::success(); 383480093f4SDimitry Andric 384480093f4SDimitry Andric // Bail out early if we've already freed the archive. 385480093f4SDimitry Andric if (!Archive) 386480093f4SDimitry Andric return Error::success(); 3878bcb0991SDimitry Andric 3888bcb0991SDimitry Andric DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; 3898bcb0991SDimitry Andric 390480093f4SDimitry Andric for (const auto &KV : Symbols) { 391480093f4SDimitry Andric const auto &Name = KV.first; 392bdd1243dSDimitry Andric if (!ObjectFilesMap.count(Name)) 3938bcb0991SDimitry Andric continue; 394bdd1243dSDimitry Andric auto ChildBuffer = ObjectFilesMap[Name]; 3958bcb0991SDimitry Andric ChildBufferInfos.insert( 396bdd1243dSDimitry Andric {ChildBuffer.getBuffer(), ChildBuffer.getBufferIdentifier()}); 3978bcb0991SDimitry Andric } 3988bcb0991SDimitry Andric 3998bcb0991SDimitry Andric for (auto ChildBufferInfo : ChildBufferInfos) { 4008bcb0991SDimitry Andric MemoryBufferRef ChildBufferRef(ChildBufferInfo.first, 4018bcb0991SDimitry Andric ChildBufferInfo.second); 4028bcb0991SDimitry Andric 4030eae32dcSDimitry Andric auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef); 4040eae32dcSDimitry Andric if (!I) 4050eae32dcSDimitry Andric return I.takeError(); 4060eae32dcSDimitry Andric 4070eae32dcSDimitry Andric if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false), 4080eae32dcSDimitry Andric std::move(*I))) 409480093f4SDimitry Andric return Err; 4108bcb0991SDimitry Andric } 4118bcb0991SDimitry Andric 412480093f4SDimitry Andric return Error::success(); 4138bcb0991SDimitry Andric } 4148bcb0991SDimitry Andric 415bdd1243dSDimitry Andric Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() { 416bdd1243dSDimitry Andric DenseMap<uint64_t, MemoryBufferRef> MemoryBuffers; 417bdd1243dSDimitry Andric DenseSet<uint64_t> Visited; 418bdd1243dSDimitry Andric DenseSet<uint64_t> Excluded; 419bdd1243dSDimitry Andric for (auto &S : Archive->symbols()) { 420bdd1243dSDimitry Andric StringRef SymName = S.getName(); 421bdd1243dSDimitry Andric auto Member = S.getMember(); 422bdd1243dSDimitry Andric if (!Member) 423bdd1243dSDimitry Andric return Member.takeError(); 424bdd1243dSDimitry Andric auto DataOffset = Member->getDataOffset(); 425bdd1243dSDimitry Andric if (!Visited.count(DataOffset)) { 426bdd1243dSDimitry Andric Visited.insert(DataOffset); 427bdd1243dSDimitry Andric auto Child = Member->getAsBinary(); 428bdd1243dSDimitry Andric if (!Child) 429bdd1243dSDimitry Andric return Child.takeError(); 430bdd1243dSDimitry Andric if ((*Child)->isCOFFImportFile()) { 431bdd1243dSDimitry Andric ImportedDynamicLibraries.insert((*Child)->getFileName().str()); 432bdd1243dSDimitry Andric Excluded.insert(DataOffset); 433bdd1243dSDimitry Andric continue; 434bdd1243dSDimitry Andric } 435bdd1243dSDimitry Andric MemoryBuffers[DataOffset] = (*Child)->getMemoryBufferRef(); 436bdd1243dSDimitry Andric } 437bdd1243dSDimitry Andric if (!Excluded.count(DataOffset)) 438bdd1243dSDimitry Andric ObjectFilesMap[L.getExecutionSession().intern(SymName)] = 439bdd1243dSDimitry Andric MemoryBuffers[DataOffset]; 440bdd1243dSDimitry Andric } 441bdd1243dSDimitry Andric 442bdd1243dSDimitry Andric return Error::success(); 443bdd1243dSDimitry Andric } 444bdd1243dSDimitry Andric 445*06c3fb27SDimitry Andric Expected<std::pair<size_t, size_t>> 446*06c3fb27SDimitry Andric StaticLibraryDefinitionGenerator::getSliceRangeForArch( 447*06c3fb27SDimitry Andric object::MachOUniversalBinary &UB, const Triple &TT) { 448*06c3fb27SDimitry Andric 449*06c3fb27SDimitry Andric for (const auto &Obj : UB.objects()) { 450*06c3fb27SDimitry Andric auto ObjTT = Obj.getTriple(); 451*06c3fb27SDimitry Andric if (ObjTT.getArch() == TT.getArch() && 452*06c3fb27SDimitry Andric ObjTT.getSubArch() == TT.getSubArch() && 453*06c3fb27SDimitry Andric (TT.getVendor() == Triple::UnknownVendor || 454*06c3fb27SDimitry Andric ObjTT.getVendor() == TT.getVendor())) { 455*06c3fb27SDimitry Andric // We found a match. Return the range for the slice. 456*06c3fb27SDimitry Andric return std::make_pair(Obj.getOffset(), Obj.getSize()); 457*06c3fb27SDimitry Andric } 458*06c3fb27SDimitry Andric } 459*06c3fb27SDimitry Andric 460*06c3fb27SDimitry Andric return make_error<StringError>(Twine("Universal binary ") + UB.getFileName() + 461*06c3fb27SDimitry Andric " does not contain a slice for " + 462*06c3fb27SDimitry Andric TT.str(), 463*06c3fb27SDimitry Andric inconvertibleErrorCode()); 464*06c3fb27SDimitry Andric } 465*06c3fb27SDimitry Andric 4668bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( 4670eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 468*06c3fb27SDimitry Andric std::unique_ptr<object::Archive> Archive, 4690eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface, Error &Err) 4700eae32dcSDimitry Andric : L(L), GetObjFileInterface(std::move(GetObjFileInterface)), 471*06c3fb27SDimitry Andric ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)) { 472bdd1243dSDimitry Andric ErrorAsOutParameter _(&Err); 4730eae32dcSDimitry Andric if (!this->GetObjFileInterface) 4740eae32dcSDimitry Andric this->GetObjFileInterface = getObjectFileInterface; 475bdd1243dSDimitry Andric if (!Err) 476bdd1243dSDimitry Andric Err = buildObjectFilesMap(); 477bdd1243dSDimitry Andric } 478bdd1243dSDimitry Andric 479bdd1243dSDimitry Andric std::unique_ptr<DLLImportDefinitionGenerator> 480bdd1243dSDimitry Andric DLLImportDefinitionGenerator::Create(ExecutionSession &ES, 481bdd1243dSDimitry Andric ObjectLinkingLayer &L) { 482bdd1243dSDimitry Andric return std::unique_ptr<DLLImportDefinitionGenerator>( 483bdd1243dSDimitry Andric new DLLImportDefinitionGenerator(ES, L)); 484bdd1243dSDimitry Andric } 485bdd1243dSDimitry Andric 486bdd1243dSDimitry Andric Error DLLImportDefinitionGenerator::tryToGenerate( 487bdd1243dSDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 488bdd1243dSDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 489bdd1243dSDimitry Andric JITDylibSearchOrder LinkOrder; 490bdd1243dSDimitry Andric JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) { 491bdd1243dSDimitry Andric LinkOrder.reserve(LO.size()); 492bdd1243dSDimitry Andric for (auto &KV : LO) { 493bdd1243dSDimitry Andric if (KV.first == &JD) 494bdd1243dSDimitry Andric continue; 495bdd1243dSDimitry Andric LinkOrder.push_back(KV); 496bdd1243dSDimitry Andric } 497bdd1243dSDimitry Andric }); 498bdd1243dSDimitry Andric 499bdd1243dSDimitry Andric // FIXME: if regular symbol name start with __imp_ we have to issue lookup of 500bdd1243dSDimitry Andric // both __imp_ and stripped name and use the lookup information to resolve the 501bdd1243dSDimitry Andric // real symbol name. 502bdd1243dSDimitry Andric SymbolLookupSet LookupSet; 503bdd1243dSDimitry Andric DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols; 504bdd1243dSDimitry Andric for (auto &KV : Symbols) { 505bdd1243dSDimitry Andric StringRef Deinterned = *KV.first; 506bdd1243dSDimitry Andric if (Deinterned.startswith(getImpPrefix())) 507bdd1243dSDimitry Andric Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size()); 508bdd1243dSDimitry Andric // Don't degrade the required state 509bdd1243dSDimitry Andric if (ToLookUpSymbols.count(Deinterned) && 510bdd1243dSDimitry Andric ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol) 511bdd1243dSDimitry Andric continue; 512bdd1243dSDimitry Andric ToLookUpSymbols[Deinterned] = KV.second; 513bdd1243dSDimitry Andric } 514bdd1243dSDimitry Andric 515bdd1243dSDimitry Andric for (auto &KV : ToLookUpSymbols) 516bdd1243dSDimitry Andric LookupSet.add(ES.intern(KV.first), KV.second); 517bdd1243dSDimitry Andric 518bdd1243dSDimitry Andric auto Resolved = 519bdd1243dSDimitry Andric ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved); 520bdd1243dSDimitry Andric if (!Resolved) 521bdd1243dSDimitry Andric return Resolved.takeError(); 522bdd1243dSDimitry Andric 523bdd1243dSDimitry Andric auto G = createStubsGraph(*Resolved); 524bdd1243dSDimitry Andric if (!G) 525bdd1243dSDimitry Andric return G.takeError(); 526bdd1243dSDimitry Andric return L.add(JD, std::move(*G)); 527bdd1243dSDimitry Andric } 528bdd1243dSDimitry Andric 529bdd1243dSDimitry Andric Expected<unsigned> 530bdd1243dSDimitry Andric DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) { 531bdd1243dSDimitry Andric switch (TT.getArch()) { 532bdd1243dSDimitry Andric case Triple::x86_64: 533bdd1243dSDimitry Andric return 8; 534bdd1243dSDimitry Andric default: 535bdd1243dSDimitry Andric return make_error<StringError>( 536bdd1243dSDimitry Andric "architecture unsupported by DLLImportDefinitionGenerator", 537bdd1243dSDimitry Andric inconvertibleErrorCode()); 538bdd1243dSDimitry Andric } 539bdd1243dSDimitry Andric } 540bdd1243dSDimitry Andric 541bdd1243dSDimitry Andric Expected<support::endianness> 542bdd1243dSDimitry Andric DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) { 543bdd1243dSDimitry Andric switch (TT.getArch()) { 544bdd1243dSDimitry Andric case Triple::x86_64: 545bdd1243dSDimitry Andric return support::endianness::little; 546bdd1243dSDimitry Andric default: 547bdd1243dSDimitry Andric return make_error<StringError>( 548bdd1243dSDimitry Andric "architecture unsupported by DLLImportDefinitionGenerator", 549bdd1243dSDimitry Andric inconvertibleErrorCode()); 550bdd1243dSDimitry Andric } 551bdd1243dSDimitry Andric } 552bdd1243dSDimitry Andric 553bdd1243dSDimitry Andric Expected<std::unique_ptr<jitlink::LinkGraph>> 554bdd1243dSDimitry Andric DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) { 555*06c3fb27SDimitry Andric Triple TT = ES.getTargetTriple(); 556bdd1243dSDimitry Andric auto PointerSize = getTargetEndianness(TT); 557bdd1243dSDimitry Andric if (!PointerSize) 558bdd1243dSDimitry Andric return PointerSize.takeError(); 559bdd1243dSDimitry Andric auto Endianness = getTargetEndianness(TT); 560bdd1243dSDimitry Andric if (!Endianness) 561bdd1243dSDimitry Andric return Endianness.takeError(); 562bdd1243dSDimitry Andric 563bdd1243dSDimitry Andric auto G = std::make_unique<jitlink::LinkGraph>( 564bdd1243dSDimitry Andric "<DLLIMPORT_STUBS>", TT, *PointerSize, *Endianness, 565bdd1243dSDimitry Andric jitlink::getGenericEdgeKindName); 566bdd1243dSDimitry Andric jitlink::Section &Sec = 567bdd1243dSDimitry Andric G->createSection(getSectionName(), MemProt::Read | MemProt::Exec); 568bdd1243dSDimitry Andric 569bdd1243dSDimitry Andric for (auto &KV : Resolved) { 570bdd1243dSDimitry Andric jitlink::Symbol &Target = G->addAbsoluteSymbol( 571*06c3fb27SDimitry Andric *KV.first, KV.second.getAddress(), *PointerSize, 572bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Local, false); 573bdd1243dSDimitry Andric 574bdd1243dSDimitry Andric // Create __imp_ symbol 575bdd1243dSDimitry Andric jitlink::Symbol &Ptr = 576bdd1243dSDimitry Andric jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target); 577*06c3fb27SDimitry Andric auto NameCopy = G->allocateContent(Twine(getImpPrefix()) + *KV.first); 578bdd1243dSDimitry Andric StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size()); 579bdd1243dSDimitry Andric Ptr.setName(NameCopyRef); 580bdd1243dSDimitry Andric Ptr.setLinkage(jitlink::Linkage::Strong); 581bdd1243dSDimitry Andric Ptr.setScope(jitlink::Scope::Default); 582bdd1243dSDimitry Andric 583bdd1243dSDimitry Andric // Create PLT stub 584bdd1243dSDimitry Andric // FIXME: check PLT stub of data symbol is not accessed 585bdd1243dSDimitry Andric jitlink::Block &StubBlock = 586bdd1243dSDimitry Andric jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr); 587bdd1243dSDimitry Andric G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(), 588bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, true, 589bdd1243dSDimitry Andric false); 590bdd1243dSDimitry Andric } 591bdd1243dSDimitry Andric 592bdd1243dSDimitry Andric return std::move(G); 5930eae32dcSDimitry Andric } 5948bcb0991SDimitry Andric 5950b57cec5SDimitry Andric } // End namespace orc. 5960b57cec5SDimitry Andric } // End namespace llvm. 597