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" 10*bdd1243dSDimitry 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"); 1590b57cec5SDimitry Andric auto CtorDtor = reinterpret_cast<CtorDtorTy>( 1600b57cec5SDimitry Andric static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress())); 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; 1890b57cec5SDimitry Andric RuntimeInterposes[Mangle("__dso_handle")] = 1900b57cec5SDimitry Andric JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride), 1910b57cec5SDimitry Andric JITSymbolFlags::Exported); 1920b57cec5SDimitry Andric RuntimeInterposes[Mangle("__cxa_atexit")] = 1930b57cec5SDimitry Andric JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride), 1940b57cec5SDimitry Andric JITSymbolFlags::Exported); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric return JD.define(absoluteSymbols(std::move(RuntimeInterposes))); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1995ffd83dbSDimitry Andric void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx, 2005ffd83dbSDimitry Andric void *DSOHandle) { 2015ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(AtExitsMutex); 2025ffd83dbSDimitry Andric AtExitRecords[DSOHandle].push_back({F, Ctx}); 2035ffd83dbSDimitry Andric } 2045ffd83dbSDimitry Andric 2055ffd83dbSDimitry Andric void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) { 2065ffd83dbSDimitry Andric std::vector<AtExitRecord> AtExitsToRun; 2075ffd83dbSDimitry Andric 2085ffd83dbSDimitry Andric { 2095ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(AtExitsMutex); 2105ffd83dbSDimitry Andric auto I = AtExitRecords.find(DSOHandle); 2115ffd83dbSDimitry Andric if (I != AtExitRecords.end()) { 2125ffd83dbSDimitry Andric AtExitsToRun = std::move(I->second); 2135ffd83dbSDimitry Andric AtExitRecords.erase(I); 2145ffd83dbSDimitry Andric } 2155ffd83dbSDimitry Andric } 2165ffd83dbSDimitry Andric 2175ffd83dbSDimitry Andric while (!AtExitsToRun.empty()) { 2185ffd83dbSDimitry Andric AtExitsToRun.back().F(AtExitsToRun.back().Ctx); 2195ffd83dbSDimitry Andric AtExitsToRun.pop_back(); 2205ffd83dbSDimitry Andric } 2215ffd83dbSDimitry Andric } 2225ffd83dbSDimitry Andric 2230b57cec5SDimitry Andric DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator( 2240b57cec5SDimitry Andric sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow) 2250b57cec5SDimitry Andric : Dylib(std::move(Dylib)), Allow(std::move(Allow)), 2260b57cec5SDimitry Andric GlobalPrefix(GlobalPrefix) {} 2270b57cec5SDimitry Andric 2288bcb0991SDimitry Andric Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 2290b57cec5SDimitry Andric DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, 2300b57cec5SDimitry Andric SymbolPredicate Allow) { 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>( 2368bcb0991SDimitry Andric std::move(Lib), GlobalPrefix, std::move(Allow)); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 239480093f4SDimitry Andric Error DynamicLibrarySearchGenerator::tryToGenerate( 240e8d8bef9SDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 241e8d8bef9SDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 2420b57cec5SDimitry Andric orc::SymbolMap NewSymbols; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric bool HasGlobalPrefix = (GlobalPrefix != '\0'); 2450b57cec5SDimitry Andric 246480093f4SDimitry Andric for (auto &KV : Symbols) { 247480093f4SDimitry Andric auto &Name = KV.first; 248480093f4SDimitry Andric 2490b57cec5SDimitry Andric if ((*Name).empty()) 2500b57cec5SDimitry Andric continue; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric if (Allow && !Allow(Name)) 2530b57cec5SDimitry Andric continue; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric if (HasGlobalPrefix && (*Name).front() != GlobalPrefix) 2560b57cec5SDimitry Andric continue; 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric std::string Tmp((*Name).data() + HasGlobalPrefix, 2590b57cec5SDimitry Andric (*Name).size() - HasGlobalPrefix); 2600b57cec5SDimitry Andric if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) { 2610b57cec5SDimitry Andric NewSymbols[Name] = JITEvaluatedSymbol( 2620b57cec5SDimitry Andric static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)), 2630b57cec5SDimitry Andric JITSymbolFlags::Exported); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 267480093f4SDimitry Andric if (NewSymbols.empty()) 268480093f4SDimitry Andric return Error::success(); 2690b57cec5SDimitry Andric 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) { 27781ad6265SDimitry Andric auto ArchiveBuffer = MemoryBuffer::getFile(FileName); 2788bcb0991SDimitry Andric 2798bcb0991SDimitry Andric if (!ArchiveBuffer) 28081ad6265SDimitry Andric return createFileError(FileName, ArchiveBuffer.getError()); 2818bcb0991SDimitry Andric 2820eae32dcSDimitry Andric return Create(L, std::move(*ArchiveBuffer), std::move(GetObjFileInterface)); 2838bcb0991SDimitry Andric } 2848bcb0991SDimitry Andric 2858bcb0991SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 2860eae32dcSDimitry Andric StaticLibraryDefinitionGenerator::Load( 2870eae32dcSDimitry Andric ObjectLayer &L, const char *FileName, const Triple &TT, 2880eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface) { 2890eae32dcSDimitry Andric 2905ffd83dbSDimitry Andric auto B = object::createBinary(FileName); 2915ffd83dbSDimitry Andric if (!B) 29281ad6265SDimitry Andric return createFileError(FileName, B.takeError()); 2935ffd83dbSDimitry Andric 2945ffd83dbSDimitry Andric // If this is a regular archive then create an instance from it. 2955ffd83dbSDimitry Andric if (isa<object::Archive>(B->getBinary())) 2960eae32dcSDimitry Andric return Create(L, std::move(B->takeBinary().second), 2970eae32dcSDimitry Andric std::move(GetObjFileInterface)); 2985ffd83dbSDimitry Andric 2995ffd83dbSDimitry Andric // If this is a universal binary then search for a slice matching the given 3005ffd83dbSDimitry Andric // Triple. 3015ffd83dbSDimitry Andric if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) { 3025ffd83dbSDimitry Andric for (const auto &Obj : UB->objects()) { 3035ffd83dbSDimitry Andric auto ObjTT = Obj.getTriple(); 3045ffd83dbSDimitry Andric if (ObjTT.getArch() == TT.getArch() && 3055ffd83dbSDimitry Andric ObjTT.getSubArch() == TT.getSubArch() && 306e8d8bef9SDimitry Andric (TT.getVendor() == Triple::UnknownVendor || 307e8d8bef9SDimitry Andric ObjTT.getVendor() == TT.getVendor())) { 3085ffd83dbSDimitry Andric // We found a match. Create an instance from a buffer covering this 3095ffd83dbSDimitry Andric // slice. 3105ffd83dbSDimitry Andric auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(), 3115ffd83dbSDimitry Andric Obj.getOffset()); 3125ffd83dbSDimitry Andric if (!SliceBuffer) 3135ffd83dbSDimitry Andric return make_error<StringError>( 3145ffd83dbSDimitry Andric Twine("Could not create buffer for ") + TT.str() + " slice of " + 3155ffd83dbSDimitry Andric FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) + 3165ffd83dbSDimitry Andric " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) + 3175ffd83dbSDimitry Andric ": " + SliceBuffer.getError().message(), 3185ffd83dbSDimitry Andric SliceBuffer.getError()); 3190eae32dcSDimitry Andric return Create(L, std::move(*SliceBuffer), 3200eae32dcSDimitry Andric std::move(GetObjFileInterface)); 3215ffd83dbSDimitry Andric } 3225ffd83dbSDimitry Andric } 3235ffd83dbSDimitry Andric 3245ffd83dbSDimitry Andric return make_error<StringError>(Twine("Universal binary ") + FileName + 3255ffd83dbSDimitry Andric " does not contain a slice for " + 3265ffd83dbSDimitry Andric TT.str(), 3275ffd83dbSDimitry Andric inconvertibleErrorCode()); 3285ffd83dbSDimitry Andric } 3295ffd83dbSDimitry Andric 3305ffd83dbSDimitry Andric return make_error<StringError>(Twine("Unrecognized file type for ") + 3315ffd83dbSDimitry Andric FileName, 3325ffd83dbSDimitry Andric inconvertibleErrorCode()); 3335ffd83dbSDimitry Andric } 3345ffd83dbSDimitry Andric 3355ffd83dbSDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 3368bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::Create( 3370eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 3380eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface) { 3398bcb0991SDimitry Andric Error Err = Error::success(); 3408bcb0991SDimitry Andric 3418bcb0991SDimitry Andric std::unique_ptr<StaticLibraryDefinitionGenerator> ADG( 3420eae32dcSDimitry Andric new StaticLibraryDefinitionGenerator( 3430eae32dcSDimitry Andric L, std::move(ArchiveBuffer), std::move(GetObjFileInterface), Err)); 3448bcb0991SDimitry Andric 3458bcb0991SDimitry Andric if (Err) 3468bcb0991SDimitry Andric return std::move(Err); 3478bcb0991SDimitry Andric 3488bcb0991SDimitry Andric return std::move(ADG); 3498bcb0991SDimitry Andric } 3508bcb0991SDimitry Andric 351480093f4SDimitry Andric Error StaticLibraryDefinitionGenerator::tryToGenerate( 352e8d8bef9SDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 353e8d8bef9SDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 354480093f4SDimitry Andric // Don't materialize symbols from static archives unless this is a static 355480093f4SDimitry Andric // lookup. 356480093f4SDimitry Andric if (K != LookupKind::Static) 357480093f4SDimitry Andric return Error::success(); 358480093f4SDimitry Andric 359480093f4SDimitry Andric // Bail out early if we've already freed the archive. 360480093f4SDimitry Andric if (!Archive) 361480093f4SDimitry Andric return Error::success(); 3628bcb0991SDimitry Andric 3638bcb0991SDimitry Andric DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; 3648bcb0991SDimitry Andric 365480093f4SDimitry Andric for (const auto &KV : Symbols) { 366480093f4SDimitry Andric const auto &Name = KV.first; 367*bdd1243dSDimitry Andric if (!ObjectFilesMap.count(Name)) 3688bcb0991SDimitry Andric continue; 369*bdd1243dSDimitry Andric auto ChildBuffer = ObjectFilesMap[Name]; 3708bcb0991SDimitry Andric ChildBufferInfos.insert( 371*bdd1243dSDimitry Andric {ChildBuffer.getBuffer(), ChildBuffer.getBufferIdentifier()}); 3728bcb0991SDimitry Andric } 3738bcb0991SDimitry Andric 3748bcb0991SDimitry Andric for (auto ChildBufferInfo : ChildBufferInfos) { 3758bcb0991SDimitry Andric MemoryBufferRef ChildBufferRef(ChildBufferInfo.first, 3768bcb0991SDimitry Andric ChildBufferInfo.second); 3778bcb0991SDimitry Andric 3780eae32dcSDimitry Andric auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef); 3790eae32dcSDimitry Andric if (!I) 3800eae32dcSDimitry Andric return I.takeError(); 3810eae32dcSDimitry Andric 3820eae32dcSDimitry Andric if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false), 3830eae32dcSDimitry Andric std::move(*I))) 384480093f4SDimitry Andric return Err; 3858bcb0991SDimitry Andric } 3868bcb0991SDimitry Andric 387480093f4SDimitry Andric return Error::success(); 3888bcb0991SDimitry Andric } 3898bcb0991SDimitry Andric 390*bdd1243dSDimitry Andric Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() { 391*bdd1243dSDimitry Andric DenseMap<uint64_t, MemoryBufferRef> MemoryBuffers; 392*bdd1243dSDimitry Andric DenseSet<uint64_t> Visited; 393*bdd1243dSDimitry Andric DenseSet<uint64_t> Excluded; 394*bdd1243dSDimitry Andric for (auto &S : Archive->symbols()) { 395*bdd1243dSDimitry Andric StringRef SymName = S.getName(); 396*bdd1243dSDimitry Andric auto Member = S.getMember(); 397*bdd1243dSDimitry Andric if (!Member) 398*bdd1243dSDimitry Andric return Member.takeError(); 399*bdd1243dSDimitry Andric auto DataOffset = Member->getDataOffset(); 400*bdd1243dSDimitry Andric if (!Visited.count(DataOffset)) { 401*bdd1243dSDimitry Andric Visited.insert(DataOffset); 402*bdd1243dSDimitry Andric auto Child = Member->getAsBinary(); 403*bdd1243dSDimitry Andric if (!Child) 404*bdd1243dSDimitry Andric return Child.takeError(); 405*bdd1243dSDimitry Andric if ((*Child)->isCOFFImportFile()) { 406*bdd1243dSDimitry Andric ImportedDynamicLibraries.insert((*Child)->getFileName().str()); 407*bdd1243dSDimitry Andric Excluded.insert(DataOffset); 408*bdd1243dSDimitry Andric continue; 409*bdd1243dSDimitry Andric } 410*bdd1243dSDimitry Andric MemoryBuffers[DataOffset] = (*Child)->getMemoryBufferRef(); 411*bdd1243dSDimitry Andric } 412*bdd1243dSDimitry Andric if (!Excluded.count(DataOffset)) 413*bdd1243dSDimitry Andric ObjectFilesMap[L.getExecutionSession().intern(SymName)] = 414*bdd1243dSDimitry Andric MemoryBuffers[DataOffset]; 415*bdd1243dSDimitry Andric } 416*bdd1243dSDimitry Andric 417*bdd1243dSDimitry Andric return Error::success(); 418*bdd1243dSDimitry Andric } 419*bdd1243dSDimitry Andric 4208bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( 4210eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, 4220eae32dcSDimitry Andric GetObjectFileInterface GetObjFileInterface, Error &Err) 4230eae32dcSDimitry Andric : L(L), GetObjFileInterface(std::move(GetObjFileInterface)), 4240eae32dcSDimitry Andric ArchiveBuffer(std::move(ArchiveBuffer)), 4250eae32dcSDimitry Andric Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) { 426*bdd1243dSDimitry Andric ErrorAsOutParameter _(&Err); 4270eae32dcSDimitry Andric if (!this->GetObjFileInterface) 4280eae32dcSDimitry Andric this->GetObjFileInterface = getObjectFileInterface; 429*bdd1243dSDimitry Andric if (!Err) 430*bdd1243dSDimitry Andric Err = buildObjectFilesMap(); 431*bdd1243dSDimitry Andric } 432*bdd1243dSDimitry Andric 433*bdd1243dSDimitry Andric std::unique_ptr<DLLImportDefinitionGenerator> 434*bdd1243dSDimitry Andric DLLImportDefinitionGenerator::Create(ExecutionSession &ES, 435*bdd1243dSDimitry Andric ObjectLinkingLayer &L) { 436*bdd1243dSDimitry Andric return std::unique_ptr<DLLImportDefinitionGenerator>( 437*bdd1243dSDimitry Andric new DLLImportDefinitionGenerator(ES, L)); 438*bdd1243dSDimitry Andric } 439*bdd1243dSDimitry Andric 440*bdd1243dSDimitry Andric Error DLLImportDefinitionGenerator::tryToGenerate( 441*bdd1243dSDimitry Andric LookupState &LS, LookupKind K, JITDylib &JD, 442*bdd1243dSDimitry Andric JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { 443*bdd1243dSDimitry Andric JITDylibSearchOrder LinkOrder; 444*bdd1243dSDimitry Andric JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) { 445*bdd1243dSDimitry Andric LinkOrder.reserve(LO.size()); 446*bdd1243dSDimitry Andric for (auto &KV : LO) { 447*bdd1243dSDimitry Andric if (KV.first == &JD) 448*bdd1243dSDimitry Andric continue; 449*bdd1243dSDimitry Andric LinkOrder.push_back(KV); 450*bdd1243dSDimitry Andric } 451*bdd1243dSDimitry Andric }); 452*bdd1243dSDimitry Andric 453*bdd1243dSDimitry Andric // FIXME: if regular symbol name start with __imp_ we have to issue lookup of 454*bdd1243dSDimitry Andric // both __imp_ and stripped name and use the lookup information to resolve the 455*bdd1243dSDimitry Andric // real symbol name. 456*bdd1243dSDimitry Andric SymbolLookupSet LookupSet; 457*bdd1243dSDimitry Andric DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols; 458*bdd1243dSDimitry Andric for (auto &KV : Symbols) { 459*bdd1243dSDimitry Andric StringRef Deinterned = *KV.first; 460*bdd1243dSDimitry Andric if (Deinterned.startswith(getImpPrefix())) 461*bdd1243dSDimitry Andric Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size()); 462*bdd1243dSDimitry Andric // Don't degrade the required state 463*bdd1243dSDimitry Andric if (ToLookUpSymbols.count(Deinterned) && 464*bdd1243dSDimitry Andric ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol) 465*bdd1243dSDimitry Andric continue; 466*bdd1243dSDimitry Andric ToLookUpSymbols[Deinterned] = KV.second; 467*bdd1243dSDimitry Andric } 468*bdd1243dSDimitry Andric 469*bdd1243dSDimitry Andric for (auto &KV : ToLookUpSymbols) 470*bdd1243dSDimitry Andric LookupSet.add(ES.intern(KV.first), KV.second); 471*bdd1243dSDimitry Andric 472*bdd1243dSDimitry Andric auto Resolved = 473*bdd1243dSDimitry Andric ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved); 474*bdd1243dSDimitry Andric if (!Resolved) 475*bdd1243dSDimitry Andric return Resolved.takeError(); 476*bdd1243dSDimitry Andric 477*bdd1243dSDimitry Andric auto G = createStubsGraph(*Resolved); 478*bdd1243dSDimitry Andric if (!G) 479*bdd1243dSDimitry Andric return G.takeError(); 480*bdd1243dSDimitry Andric return L.add(JD, std::move(*G)); 481*bdd1243dSDimitry Andric } 482*bdd1243dSDimitry Andric 483*bdd1243dSDimitry Andric Expected<unsigned> 484*bdd1243dSDimitry Andric DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) { 485*bdd1243dSDimitry Andric switch (TT.getArch()) { 486*bdd1243dSDimitry Andric case Triple::x86_64: 487*bdd1243dSDimitry Andric return 8; 488*bdd1243dSDimitry Andric default: 489*bdd1243dSDimitry Andric return make_error<StringError>( 490*bdd1243dSDimitry Andric "architecture unsupported by DLLImportDefinitionGenerator", 491*bdd1243dSDimitry Andric inconvertibleErrorCode()); 492*bdd1243dSDimitry Andric } 493*bdd1243dSDimitry Andric } 494*bdd1243dSDimitry Andric 495*bdd1243dSDimitry Andric Expected<support::endianness> 496*bdd1243dSDimitry Andric DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) { 497*bdd1243dSDimitry Andric switch (TT.getArch()) { 498*bdd1243dSDimitry Andric case Triple::x86_64: 499*bdd1243dSDimitry Andric return support::endianness::little; 500*bdd1243dSDimitry Andric default: 501*bdd1243dSDimitry Andric return make_error<StringError>( 502*bdd1243dSDimitry Andric "architecture unsupported by DLLImportDefinitionGenerator", 503*bdd1243dSDimitry Andric inconvertibleErrorCode()); 504*bdd1243dSDimitry Andric } 505*bdd1243dSDimitry Andric } 506*bdd1243dSDimitry Andric 507*bdd1243dSDimitry Andric Expected<std::unique_ptr<jitlink::LinkGraph>> 508*bdd1243dSDimitry Andric DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) { 509*bdd1243dSDimitry Andric Triple TT = ES.getExecutorProcessControl().getTargetTriple(); 510*bdd1243dSDimitry Andric auto PointerSize = getTargetEndianness(TT); 511*bdd1243dSDimitry Andric if (!PointerSize) 512*bdd1243dSDimitry Andric return PointerSize.takeError(); 513*bdd1243dSDimitry Andric auto Endianness = getTargetEndianness(TT); 514*bdd1243dSDimitry Andric if (!Endianness) 515*bdd1243dSDimitry Andric return Endianness.takeError(); 516*bdd1243dSDimitry Andric 517*bdd1243dSDimitry Andric auto G = std::make_unique<jitlink::LinkGraph>( 518*bdd1243dSDimitry Andric "<DLLIMPORT_STUBS>", TT, *PointerSize, *Endianness, 519*bdd1243dSDimitry Andric jitlink::getGenericEdgeKindName); 520*bdd1243dSDimitry Andric jitlink::Section &Sec = 521*bdd1243dSDimitry Andric G->createSection(getSectionName(), MemProt::Read | MemProt::Exec); 522*bdd1243dSDimitry Andric 523*bdd1243dSDimitry Andric for (auto &KV : Resolved) { 524*bdd1243dSDimitry Andric jitlink::Symbol &Target = G->addAbsoluteSymbol( 525*bdd1243dSDimitry Andric *KV.first, ExecutorAddr(KV.second.getAddress()), *PointerSize, 526*bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Local, false); 527*bdd1243dSDimitry Andric 528*bdd1243dSDimitry Andric // Create __imp_ symbol 529*bdd1243dSDimitry Andric jitlink::Symbol &Ptr = 530*bdd1243dSDimitry Andric jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target); 531*bdd1243dSDimitry Andric auto NameCopy = G->allocateString(Twine(getImpPrefix()) + *KV.first); 532*bdd1243dSDimitry Andric StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size()); 533*bdd1243dSDimitry Andric Ptr.setName(NameCopyRef); 534*bdd1243dSDimitry Andric Ptr.setLinkage(jitlink::Linkage::Strong); 535*bdd1243dSDimitry Andric Ptr.setScope(jitlink::Scope::Default); 536*bdd1243dSDimitry Andric 537*bdd1243dSDimitry Andric // Create PLT stub 538*bdd1243dSDimitry Andric // FIXME: check PLT stub of data symbol is not accessed 539*bdd1243dSDimitry Andric jitlink::Block &StubBlock = 540*bdd1243dSDimitry Andric jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr); 541*bdd1243dSDimitry Andric G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(), 542*bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, true, 543*bdd1243dSDimitry Andric false); 544*bdd1243dSDimitry Andric } 545*bdd1243dSDimitry Andric 546*bdd1243dSDimitry Andric return std::move(G); 5470eae32dcSDimitry Andric } 5488bcb0991SDimitry Andric 5490b57cec5SDimitry Andric } // End namespace orc. 5500b57cec5SDimitry Andric } // End namespace llvm. 551