1bdd1243dSDimitry Andric //===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric 9bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/COFFPlatform.h" 10bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 11bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h" 12bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 13*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 14bdd1243dSDimitry Andric 15bdd1243dSDimitry Andric #include "llvm/Object/COFF.h" 16bdd1243dSDimitry Andric 17bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" 18bdd1243dSDimitry Andric 19bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h" 20bdd1243dSDimitry Andric 21bdd1243dSDimitry Andric #define DEBUG_TYPE "orc" 22bdd1243dSDimitry Andric 23bdd1243dSDimitry Andric using namespace llvm; 24bdd1243dSDimitry Andric using namespace llvm::orc; 25bdd1243dSDimitry Andric using namespace llvm::orc::shared; 26bdd1243dSDimitry Andric 27bdd1243dSDimitry Andric namespace llvm { 28bdd1243dSDimitry Andric namespace orc { 29bdd1243dSDimitry Andric namespace shared { 30bdd1243dSDimitry Andric 31bdd1243dSDimitry Andric using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>; 32bdd1243dSDimitry Andric using SPSCOFFJITDylibDepInfoMap = 33bdd1243dSDimitry Andric SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>; 34bdd1243dSDimitry Andric using SPSCOFFObjectSectionsMap = 35bdd1243dSDimitry Andric SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>; 36bdd1243dSDimitry Andric using SPSCOFFRegisterObjectSectionsArgs = 37bdd1243dSDimitry Andric SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>; 38bdd1243dSDimitry Andric using SPSCOFFDeregisterObjectSectionsArgs = 39bdd1243dSDimitry Andric SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>; 40bdd1243dSDimitry Andric 41bdd1243dSDimitry Andric } // namespace shared 42bdd1243dSDimitry Andric } // namespace orc 43bdd1243dSDimitry Andric } // namespace llvm 44bdd1243dSDimitry Andric namespace { 45bdd1243dSDimitry Andric 46bdd1243dSDimitry Andric class COFFHeaderMaterializationUnit : public MaterializationUnit { 47bdd1243dSDimitry Andric public: 48bdd1243dSDimitry Andric COFFHeaderMaterializationUnit(COFFPlatform &CP, 49bdd1243dSDimitry Andric const SymbolStringPtr &HeaderStartSymbol) 50bdd1243dSDimitry Andric : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)), 51bdd1243dSDimitry Andric CP(CP) {} 52bdd1243dSDimitry Andric 53bdd1243dSDimitry Andric StringRef getName() const override { return "COFFHeaderMU"; } 54bdd1243dSDimitry Andric 55bdd1243dSDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> R) override { 56bdd1243dSDimitry Andric unsigned PointerSize; 57bdd1243dSDimitry Andric support::endianness Endianness; 58*06c3fb27SDimitry Andric const auto &TT = CP.getExecutionSession().getTargetTriple(); 59bdd1243dSDimitry Andric 60bdd1243dSDimitry Andric switch (TT.getArch()) { 61bdd1243dSDimitry Andric case Triple::x86_64: 62bdd1243dSDimitry Andric PointerSize = 8; 63bdd1243dSDimitry Andric Endianness = support::endianness::little; 64bdd1243dSDimitry Andric break; 65bdd1243dSDimitry Andric default: 66bdd1243dSDimitry Andric llvm_unreachable("Unrecognized architecture"); 67bdd1243dSDimitry Andric } 68bdd1243dSDimitry Andric 69bdd1243dSDimitry Andric auto G = std::make_unique<jitlink::LinkGraph>( 70bdd1243dSDimitry Andric "<COFFHeaderMU>", TT, PointerSize, Endianness, 71bdd1243dSDimitry Andric jitlink::getGenericEdgeKindName); 72bdd1243dSDimitry Andric auto &HeaderSection = G->createSection("__header", MemProt::Read); 73bdd1243dSDimitry Andric auto &HeaderBlock = createHeaderBlock(*G, HeaderSection); 74bdd1243dSDimitry Andric 75bdd1243dSDimitry Andric // Init symbol is __ImageBase symbol. 76bdd1243dSDimitry Andric auto &ImageBaseSymbol = G->addDefinedSymbol( 77bdd1243dSDimitry Andric HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(), 78bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, false, true); 79bdd1243dSDimitry Andric 80bdd1243dSDimitry Andric addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol); 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric CP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 83bdd1243dSDimitry Andric } 84bdd1243dSDimitry Andric 85bdd1243dSDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 86bdd1243dSDimitry Andric 87bdd1243dSDimitry Andric private: 88bdd1243dSDimitry Andric struct HeaderSymbol { 89bdd1243dSDimitry Andric const char *Name; 90bdd1243dSDimitry Andric uint64_t Offset; 91bdd1243dSDimitry Andric }; 92bdd1243dSDimitry Andric 93bdd1243dSDimitry Andric struct NTHeader { 94bdd1243dSDimitry Andric support::ulittle32_t PEMagic; 95bdd1243dSDimitry Andric object::coff_file_header FileHeader; 96bdd1243dSDimitry Andric struct PEHeader { 97bdd1243dSDimitry Andric object::pe32plus_header Header; 98bdd1243dSDimitry Andric object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1]; 99bdd1243dSDimitry Andric } OptionalHeader; 100bdd1243dSDimitry Andric }; 101bdd1243dSDimitry Andric 102bdd1243dSDimitry Andric struct HeaderBlockContent { 103bdd1243dSDimitry Andric object::dos_header DOSHeader; 104bdd1243dSDimitry Andric COFFHeaderMaterializationUnit::NTHeader NTHeader; 105bdd1243dSDimitry Andric }; 106bdd1243dSDimitry Andric 107bdd1243dSDimitry Andric static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G, 108bdd1243dSDimitry Andric jitlink::Section &HeaderSection) { 109bdd1243dSDimitry Andric HeaderBlockContent Hdr = {}; 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric // Set up magic 112bdd1243dSDimitry Andric Hdr.DOSHeader.Magic[0] = 'M'; 113bdd1243dSDimitry Andric Hdr.DOSHeader.Magic[1] = 'Z'; 114bdd1243dSDimitry Andric Hdr.DOSHeader.AddressOfNewExeHeader = 115bdd1243dSDimitry Andric offsetof(HeaderBlockContent, NTHeader); 116bdd1243dSDimitry Andric uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic); 117bdd1243dSDimitry Andric Hdr.NTHeader.PEMagic = PEMagic; 118bdd1243dSDimitry Andric Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS; 119bdd1243dSDimitry Andric 120bdd1243dSDimitry Andric switch (G.getTargetTriple().getArch()) { 121bdd1243dSDimitry Andric case Triple::x86_64: 122bdd1243dSDimitry Andric Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64; 123bdd1243dSDimitry Andric break; 124bdd1243dSDimitry Andric default: 125bdd1243dSDimitry Andric llvm_unreachable("Unrecognized architecture"); 126bdd1243dSDimitry Andric } 127bdd1243dSDimitry Andric 128*06c3fb27SDimitry Andric auto HeaderContent = G.allocateContent( 129*06c3fb27SDimitry Andric ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr))); 130bdd1243dSDimitry Andric 131bdd1243dSDimitry Andric return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8, 132bdd1243dSDimitry Andric 0); 133bdd1243dSDimitry Andric } 134bdd1243dSDimitry Andric 135bdd1243dSDimitry Andric static void addImageBaseRelocationEdge(jitlink::Block &B, 136bdd1243dSDimitry Andric jitlink::Symbol &ImageBase) { 137bdd1243dSDimitry Andric auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) + 138bdd1243dSDimitry Andric offsetof(NTHeader, OptionalHeader) + 139bdd1243dSDimitry Andric offsetof(object::pe32plus_header, ImageBase); 140bdd1243dSDimitry Andric B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0); 141bdd1243dSDimitry Andric } 142bdd1243dSDimitry Andric 143bdd1243dSDimitry Andric static MaterializationUnit::Interface 144bdd1243dSDimitry Andric createHeaderInterface(COFFPlatform &MOP, 145bdd1243dSDimitry Andric const SymbolStringPtr &HeaderStartSymbol) { 146bdd1243dSDimitry Andric SymbolFlagsMap HeaderSymbolFlags; 147bdd1243dSDimitry Andric 148bdd1243dSDimitry Andric HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported; 149bdd1243dSDimitry Andric 150bdd1243dSDimitry Andric return MaterializationUnit::Interface(std::move(HeaderSymbolFlags), 151bdd1243dSDimitry Andric HeaderStartSymbol); 152bdd1243dSDimitry Andric } 153bdd1243dSDimitry Andric 154bdd1243dSDimitry Andric COFFPlatform &CP; 155bdd1243dSDimitry Andric }; 156bdd1243dSDimitry Andric 157bdd1243dSDimitry Andric } // end anonymous namespace 158bdd1243dSDimitry Andric 159bdd1243dSDimitry Andric namespace llvm { 160bdd1243dSDimitry Andric namespace orc { 161bdd1243dSDimitry Andric 162*06c3fb27SDimitry Andric Expected<std::unique_ptr<COFFPlatform>> COFFPlatform::Create( 163*06c3fb27SDimitry Andric ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 164*06c3fb27SDimitry Andric JITDylib &PlatformJD, std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer, 165bdd1243dSDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, 166*06c3fb27SDimitry Andric const char *VCRuntimePath, std::optional<SymbolAliasMap> RuntimeAliases) { 167bdd1243dSDimitry Andric 168bdd1243dSDimitry Andric // If the target is not supported then bail out immediately. 169*06c3fb27SDimitry Andric if (!supportedTarget(ES.getTargetTriple())) 170bdd1243dSDimitry Andric return make_error<StringError>("Unsupported COFFPlatform triple: " + 171*06c3fb27SDimitry Andric ES.getTargetTriple().str(), 172bdd1243dSDimitry Andric inconvertibleErrorCode()); 173bdd1243dSDimitry Andric 174*06c3fb27SDimitry Andric auto &EPC = ES.getExecutorProcessControl(); 175*06c3fb27SDimitry Andric 176*06c3fb27SDimitry Andric auto GeneratorArchive = 177*06c3fb27SDimitry Andric object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef()); 178*06c3fb27SDimitry Andric if (!GeneratorArchive) 179*06c3fb27SDimitry Andric return GeneratorArchive.takeError(); 180*06c3fb27SDimitry Andric 181*06c3fb27SDimitry Andric auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Create( 182*06c3fb27SDimitry Andric ObjLinkingLayer, nullptr, std::move(*GeneratorArchive)); 183*06c3fb27SDimitry Andric if (!OrcRuntimeArchiveGenerator) 184*06c3fb27SDimitry Andric return OrcRuntimeArchiveGenerator.takeError(); 185*06c3fb27SDimitry Andric 186*06c3fb27SDimitry Andric // We need a second instance of the archive (for now) for the Platform. We 187*06c3fb27SDimitry Andric // can `cantFail` this call, since if it were going to fail it would have 188*06c3fb27SDimitry Andric // failed above. 189*06c3fb27SDimitry Andric auto RuntimeArchive = cantFail( 190*06c3fb27SDimitry Andric object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef())); 191*06c3fb27SDimitry Andric 192bdd1243dSDimitry Andric // Create default aliases if the caller didn't supply any. 193bdd1243dSDimitry Andric if (!RuntimeAliases) 194bdd1243dSDimitry Andric RuntimeAliases = standardPlatformAliases(ES); 195bdd1243dSDimitry Andric 196bdd1243dSDimitry Andric // Define the aliases. 197bdd1243dSDimitry Andric if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases)))) 198bdd1243dSDimitry Andric return std::move(Err); 199bdd1243dSDimitry Andric 200bdd1243dSDimitry Andric auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>"); 201bdd1243dSDimitry Andric 202bdd1243dSDimitry Andric // Add JIT-dispatch function support symbols. 203*06c3fb27SDimitry Andric if (auto Err = HostFuncJD.define( 204*06c3fb27SDimitry Andric absoluteSymbols({{ES.intern("__orc_rt_jit_dispatch"), 205*06c3fb27SDimitry Andric {EPC.getJITDispatchInfo().JITDispatchFunction, 206bdd1243dSDimitry Andric JITSymbolFlags::Exported}}, 207bdd1243dSDimitry Andric {ES.intern("__orc_rt_jit_dispatch_ctx"), 208*06c3fb27SDimitry Andric {EPC.getJITDispatchInfo().JITDispatchContext, 209bdd1243dSDimitry Andric JITSymbolFlags::Exported}}}))) 210bdd1243dSDimitry Andric return std::move(Err); 211bdd1243dSDimitry Andric 212bdd1243dSDimitry Andric PlatformJD.addToLinkOrder(HostFuncJD); 213bdd1243dSDimitry Andric 214bdd1243dSDimitry Andric // Create the instance. 215bdd1243dSDimitry Andric Error Err = Error::success(); 216bdd1243dSDimitry Andric auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform( 217*06c3fb27SDimitry Andric ES, ObjLinkingLayer, PlatformJD, std::move(*OrcRuntimeArchiveGenerator), 218*06c3fb27SDimitry Andric std::move(OrcRuntimeArchiveBuffer), std::move(RuntimeArchive), 219bdd1243dSDimitry Andric std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err)); 220bdd1243dSDimitry Andric if (Err) 221bdd1243dSDimitry Andric return std::move(Err); 222bdd1243dSDimitry Andric return std::move(P); 223bdd1243dSDimitry Andric } 224bdd1243dSDimitry Andric 225*06c3fb27SDimitry Andric Expected<std::unique_ptr<COFFPlatform>> 226*06c3fb27SDimitry Andric COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 227*06c3fb27SDimitry Andric JITDylib &PlatformJD, const char *OrcRuntimePath, 228*06c3fb27SDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, 229*06c3fb27SDimitry Andric const char *VCRuntimePath, 230*06c3fb27SDimitry Andric std::optional<SymbolAliasMap> RuntimeAliases) { 231*06c3fb27SDimitry Andric 232*06c3fb27SDimitry Andric auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath); 233*06c3fb27SDimitry Andric if (!ArchiveBuffer) 234*06c3fb27SDimitry Andric return createFileError(OrcRuntimePath, ArchiveBuffer.getError()); 235*06c3fb27SDimitry Andric 236*06c3fb27SDimitry Andric return Create(ES, ObjLinkingLayer, PlatformJD, std::move(*ArchiveBuffer), 237*06c3fb27SDimitry Andric std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, 238*06c3fb27SDimitry Andric std::move(RuntimeAliases)); 239*06c3fb27SDimitry Andric } 240*06c3fb27SDimitry Andric 241bdd1243dSDimitry Andric Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() { 242bdd1243dSDimitry Andric auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker"); 243bdd1243dSDimitry Andric if (!PerJDObj) 244bdd1243dSDimitry Andric return PerJDObj.takeError(); 245bdd1243dSDimitry Andric 246bdd1243dSDimitry Andric if (!*PerJDObj) 247bdd1243dSDimitry Andric return make_error<StringError>("Could not find per jd object file", 248bdd1243dSDimitry Andric inconvertibleErrorCode()); 249bdd1243dSDimitry Andric 250bdd1243dSDimitry Andric auto Buffer = (*PerJDObj)->getAsBinary(); 251bdd1243dSDimitry Andric if (!Buffer) 252bdd1243dSDimitry Andric return Buffer.takeError(); 253bdd1243dSDimitry Andric 254bdd1243dSDimitry Andric return (*Buffer)->getMemoryBufferRef(); 255bdd1243dSDimitry Andric } 256bdd1243dSDimitry Andric 257bdd1243dSDimitry Andric static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, 258bdd1243dSDimitry Andric ArrayRef<std::pair<const char *, const char *>> AL) { 259bdd1243dSDimitry Andric for (auto &KV : AL) { 260bdd1243dSDimitry Andric auto AliasName = ES.intern(KV.first); 261bdd1243dSDimitry Andric assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); 262bdd1243dSDimitry Andric Aliases[std::move(AliasName)] = {ES.intern(KV.second), 263bdd1243dSDimitry Andric JITSymbolFlags::Exported}; 264bdd1243dSDimitry Andric } 265bdd1243dSDimitry Andric } 266bdd1243dSDimitry Andric 267bdd1243dSDimitry Andric Error COFFPlatform::setupJITDylib(JITDylib &JD) { 268bdd1243dSDimitry Andric if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>( 269bdd1243dSDimitry Andric *this, COFFHeaderStartSymbol))) 270bdd1243dSDimitry Andric return Err; 271bdd1243dSDimitry Andric 272bdd1243dSDimitry Andric if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError()) 273bdd1243dSDimitry Andric return Err; 274bdd1243dSDimitry Andric 275bdd1243dSDimitry Andric // Define the CXX aliases. 276bdd1243dSDimitry Andric SymbolAliasMap CXXAliases; 277bdd1243dSDimitry Andric addAliases(ES, CXXAliases, requiredCXXAliases()); 278bdd1243dSDimitry Andric if (auto Err = JD.define(symbolAliases(std::move(CXXAliases)))) 279bdd1243dSDimitry Andric return Err; 280bdd1243dSDimitry Andric 281bdd1243dSDimitry Andric auto PerJDObj = getPerJDObjectFile(); 282bdd1243dSDimitry Andric if (!PerJDObj) 283bdd1243dSDimitry Andric return PerJDObj.takeError(); 284bdd1243dSDimitry Andric 285bdd1243dSDimitry Andric auto I = getObjectFileInterface(ES, *PerJDObj); 286bdd1243dSDimitry Andric if (!I) 287bdd1243dSDimitry Andric return I.takeError(); 288bdd1243dSDimitry Andric 289bdd1243dSDimitry Andric if (auto Err = ObjLinkingLayer.add( 290bdd1243dSDimitry Andric JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I))) 291bdd1243dSDimitry Andric return Err; 292bdd1243dSDimitry Andric 293bdd1243dSDimitry Andric if (!Bootstrapping) { 294bdd1243dSDimitry Andric auto ImportedLibs = StaticVCRuntime 295bdd1243dSDimitry Andric ? VCRuntimeBootstrap->loadStaticVCRuntime(JD) 296bdd1243dSDimitry Andric : VCRuntimeBootstrap->loadDynamicVCRuntime(JD); 297bdd1243dSDimitry Andric if (!ImportedLibs) 298bdd1243dSDimitry Andric return ImportedLibs.takeError(); 299bdd1243dSDimitry Andric for (auto &Lib : *ImportedLibs) 300bdd1243dSDimitry Andric if (auto Err = LoadDynLibrary(JD, Lib)) 301bdd1243dSDimitry Andric return Err; 302bdd1243dSDimitry Andric if (StaticVCRuntime) 303bdd1243dSDimitry Andric if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD)) 304bdd1243dSDimitry Andric return Err; 305bdd1243dSDimitry Andric } 306bdd1243dSDimitry Andric 307bdd1243dSDimitry Andric JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer)); 308bdd1243dSDimitry Andric return Error::success(); 309bdd1243dSDimitry Andric } 310bdd1243dSDimitry Andric 311bdd1243dSDimitry Andric Error COFFPlatform::teardownJITDylib(JITDylib &JD) { 312bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 313bdd1243dSDimitry Andric auto I = JITDylibToHeaderAddr.find(&JD); 314bdd1243dSDimitry Andric if (I != JITDylibToHeaderAddr.end()) { 315bdd1243dSDimitry Andric assert(HeaderAddrToJITDylib.count(I->second) && 316bdd1243dSDimitry Andric "HeaderAddrToJITDylib missing entry"); 317bdd1243dSDimitry Andric HeaderAddrToJITDylib.erase(I->second); 318bdd1243dSDimitry Andric JITDylibToHeaderAddr.erase(I); 319bdd1243dSDimitry Andric } 320bdd1243dSDimitry Andric return Error::success(); 321bdd1243dSDimitry Andric } 322bdd1243dSDimitry Andric 323bdd1243dSDimitry Andric Error COFFPlatform::notifyAdding(ResourceTracker &RT, 324bdd1243dSDimitry Andric const MaterializationUnit &MU) { 325bdd1243dSDimitry Andric auto &JD = RT.getJITDylib(); 326bdd1243dSDimitry Andric const auto &InitSym = MU.getInitializerSymbol(); 327bdd1243dSDimitry Andric if (!InitSym) 328bdd1243dSDimitry Andric return Error::success(); 329bdd1243dSDimitry Andric 330bdd1243dSDimitry Andric RegisteredInitSymbols[&JD].add(InitSym, 331bdd1243dSDimitry Andric SymbolLookupFlags::WeaklyReferencedSymbol); 332bdd1243dSDimitry Andric 333bdd1243dSDimitry Andric LLVM_DEBUG({ 334bdd1243dSDimitry Andric dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU " 335bdd1243dSDimitry Andric << MU.getName() << "\n"; 336bdd1243dSDimitry Andric }); 337bdd1243dSDimitry Andric return Error::success(); 338bdd1243dSDimitry Andric } 339bdd1243dSDimitry Andric 340bdd1243dSDimitry Andric Error COFFPlatform::notifyRemoving(ResourceTracker &RT) { 341bdd1243dSDimitry Andric llvm_unreachable("Not supported yet"); 342bdd1243dSDimitry Andric } 343bdd1243dSDimitry Andric 344bdd1243dSDimitry Andric SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) { 345bdd1243dSDimitry Andric SymbolAliasMap Aliases; 346bdd1243dSDimitry Andric addAliases(ES, Aliases, standardRuntimeUtilityAliases()); 347bdd1243dSDimitry Andric return Aliases; 348bdd1243dSDimitry Andric } 349bdd1243dSDimitry Andric 350bdd1243dSDimitry Andric ArrayRef<std::pair<const char *, const char *>> 351bdd1243dSDimitry Andric COFFPlatform::requiredCXXAliases() { 352bdd1243dSDimitry Andric static const std::pair<const char *, const char *> RequiredCXXAliases[] = { 353bdd1243dSDimitry Andric {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"}, 354bdd1243dSDimitry Andric {"_onexit", "__orc_rt_coff_onexit_per_jd"}, 355bdd1243dSDimitry Andric {"atexit", "__orc_rt_coff_atexit_per_jd"}}; 356bdd1243dSDimitry Andric 357bdd1243dSDimitry Andric return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases); 358bdd1243dSDimitry Andric } 359bdd1243dSDimitry Andric 360bdd1243dSDimitry Andric ArrayRef<std::pair<const char *, const char *>> 361bdd1243dSDimitry Andric COFFPlatform::standardRuntimeUtilityAliases() { 362bdd1243dSDimitry Andric static const std::pair<const char *, const char *> 363bdd1243dSDimitry Andric StandardRuntimeUtilityAliases[] = { 364bdd1243dSDimitry Andric {"__orc_rt_run_program", "__orc_rt_coff_run_program"}, 365bdd1243dSDimitry Andric {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"}, 366bdd1243dSDimitry Andric {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"}, 367bdd1243dSDimitry Andric {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"}, 368bdd1243dSDimitry Andric {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"}, 369bdd1243dSDimitry Andric {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}}; 370bdd1243dSDimitry Andric 371bdd1243dSDimitry Andric return ArrayRef<std::pair<const char *, const char *>>( 372bdd1243dSDimitry Andric StandardRuntimeUtilityAliases); 373bdd1243dSDimitry Andric } 374bdd1243dSDimitry Andric 375bdd1243dSDimitry Andric bool COFFPlatform::supportedTarget(const Triple &TT) { 376bdd1243dSDimitry Andric switch (TT.getArch()) { 377bdd1243dSDimitry Andric case Triple::x86_64: 378bdd1243dSDimitry Andric return true; 379bdd1243dSDimitry Andric default: 380bdd1243dSDimitry Andric return false; 381bdd1243dSDimitry Andric } 382bdd1243dSDimitry Andric } 383bdd1243dSDimitry Andric 384*06c3fb27SDimitry Andric COFFPlatform::COFFPlatform( 385*06c3fb27SDimitry Andric ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 386*06c3fb27SDimitry Andric JITDylib &PlatformJD, 387*06c3fb27SDimitry Andric std::unique_ptr<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator, 388*06c3fb27SDimitry Andric std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer, 389*06c3fb27SDimitry Andric std::unique_ptr<object::Archive> OrcRuntimeArchive, 390*06c3fb27SDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime, 391*06c3fb27SDimitry Andric const char *VCRuntimePath, Error &Err) 392bdd1243dSDimitry Andric : ES(ES), ObjLinkingLayer(ObjLinkingLayer), 393bdd1243dSDimitry Andric LoadDynLibrary(std::move(LoadDynLibrary)), 394*06c3fb27SDimitry Andric OrcRuntimeArchiveBuffer(std::move(OrcRuntimeArchiveBuffer)), 395*06c3fb27SDimitry Andric OrcRuntimeArchive(std::move(OrcRuntimeArchive)), 396bdd1243dSDimitry Andric StaticVCRuntime(StaticVCRuntime), 397bdd1243dSDimitry Andric COFFHeaderStartSymbol(ES.intern("__ImageBase")) { 398bdd1243dSDimitry Andric ErrorAsOutParameter _(&Err); 399bdd1243dSDimitry Andric 400bdd1243dSDimitry Andric Bootstrapping.store(true); 401bdd1243dSDimitry Andric ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this)); 402bdd1243dSDimitry Andric 403bdd1243dSDimitry Andric // Load vc runtime 404bdd1243dSDimitry Andric auto VCRT = 405bdd1243dSDimitry Andric COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath); 406bdd1243dSDimitry Andric if (!VCRT) { 407bdd1243dSDimitry Andric Err = VCRT.takeError(); 408bdd1243dSDimitry Andric return; 409bdd1243dSDimitry Andric } 410bdd1243dSDimitry Andric VCRuntimeBootstrap = std::move(*VCRT); 411bdd1243dSDimitry Andric 412*06c3fb27SDimitry Andric for (auto &Lib : OrcRuntimeGenerator->getImportedDynamicLibraries()) 413bdd1243dSDimitry Andric DylibsToPreload.insert(Lib); 414bdd1243dSDimitry Andric 415bdd1243dSDimitry Andric auto ImportedLibs = 416bdd1243dSDimitry Andric StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD) 417bdd1243dSDimitry Andric : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD); 418bdd1243dSDimitry Andric if (!ImportedLibs) { 419bdd1243dSDimitry Andric Err = ImportedLibs.takeError(); 420bdd1243dSDimitry Andric return; 421bdd1243dSDimitry Andric } 422bdd1243dSDimitry Andric 423bdd1243dSDimitry Andric for (auto &Lib : *ImportedLibs) 424bdd1243dSDimitry Andric DylibsToPreload.insert(Lib); 425bdd1243dSDimitry Andric 426*06c3fb27SDimitry Andric PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); 427bdd1243dSDimitry Andric 428bdd1243dSDimitry Andric // PlatformJD hasn't been set up by the platform yet (since we're creating 429bdd1243dSDimitry Andric // the platform now), so set it up. 430bdd1243dSDimitry Andric if (auto E2 = setupJITDylib(PlatformJD)) { 431bdd1243dSDimitry Andric Err = std::move(E2); 432bdd1243dSDimitry Andric return; 433bdd1243dSDimitry Andric } 434bdd1243dSDimitry Andric 435bdd1243dSDimitry Andric for (auto& Lib : DylibsToPreload) 436*06c3fb27SDimitry Andric if (auto E2 = this->LoadDynLibrary(PlatformJD, Lib)) { 437bdd1243dSDimitry Andric Err = std::move(E2); 438bdd1243dSDimitry Andric return; 439bdd1243dSDimitry Andric } 440bdd1243dSDimitry Andric 441bdd1243dSDimitry Andric if (StaticVCRuntime) 442bdd1243dSDimitry Andric if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) { 443bdd1243dSDimitry Andric Err = std::move(E2); 444bdd1243dSDimitry Andric return; 445bdd1243dSDimitry Andric } 446bdd1243dSDimitry Andric 447bdd1243dSDimitry Andric // Associate wrapper function tags with JIT-side function implementations. 448bdd1243dSDimitry Andric if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) { 449bdd1243dSDimitry Andric Err = std::move(E2); 450bdd1243dSDimitry Andric return; 451bdd1243dSDimitry Andric } 452bdd1243dSDimitry Andric 453bdd1243dSDimitry Andric // Lookup addresses of runtime functions callable by the platform, 454bdd1243dSDimitry Andric // call the platform bootstrap function to initialize the platform-state 455bdd1243dSDimitry Andric // object in the executor. 456bdd1243dSDimitry Andric if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) { 457bdd1243dSDimitry Andric Err = std::move(E2); 458bdd1243dSDimitry Andric return; 459bdd1243dSDimitry Andric } 460bdd1243dSDimitry Andric 461bdd1243dSDimitry Andric Bootstrapping.store(false); 462bdd1243dSDimitry Andric JDBootstrapStates.clear(); 463bdd1243dSDimitry Andric } 464bdd1243dSDimitry Andric 465bdd1243dSDimitry Andric Expected<COFFPlatform::JITDylibDepMap> 466bdd1243dSDimitry Andric COFFPlatform::buildJDDepMap(JITDylib &JD) { 467bdd1243dSDimitry Andric return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> { 468bdd1243dSDimitry Andric JITDylibDepMap JDDepMap; 469bdd1243dSDimitry Andric 470bdd1243dSDimitry Andric SmallVector<JITDylib *, 16> Worklist({&JD}); 471bdd1243dSDimitry Andric while (!Worklist.empty()) { 472bdd1243dSDimitry Andric auto CurJD = Worklist.back(); 473bdd1243dSDimitry Andric Worklist.pop_back(); 474bdd1243dSDimitry Andric 475bdd1243dSDimitry Andric auto &DM = JDDepMap[CurJD]; 476bdd1243dSDimitry Andric CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) { 477bdd1243dSDimitry Andric DM.reserve(O.size()); 478bdd1243dSDimitry Andric for (auto &KV : O) { 479bdd1243dSDimitry Andric if (KV.first == CurJD) 480bdd1243dSDimitry Andric continue; 481bdd1243dSDimitry Andric { 482bdd1243dSDimitry Andric // Bare jitdylibs not known to the platform 483bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 484bdd1243dSDimitry Andric if (!JITDylibToHeaderAddr.count(KV.first)) { 485bdd1243dSDimitry Andric LLVM_DEBUG({ 486bdd1243dSDimitry Andric dbgs() << "JITDylib unregistered to COFFPlatform detected in " 487bdd1243dSDimitry Andric "LinkOrder: " 488bdd1243dSDimitry Andric << CurJD->getName() << "\n"; 489bdd1243dSDimitry Andric }); 490bdd1243dSDimitry Andric continue; 491bdd1243dSDimitry Andric } 492bdd1243dSDimitry Andric } 493bdd1243dSDimitry Andric DM.push_back(KV.first); 494bdd1243dSDimitry Andric // Push unvisited entry. 495bdd1243dSDimitry Andric if (!JDDepMap.count(KV.first)) { 496bdd1243dSDimitry Andric Worklist.push_back(KV.first); 497bdd1243dSDimitry Andric JDDepMap[KV.first] = {}; 498bdd1243dSDimitry Andric } 499bdd1243dSDimitry Andric } 500bdd1243dSDimitry Andric }); 501bdd1243dSDimitry Andric } 502bdd1243dSDimitry Andric return std::move(JDDepMap); 503bdd1243dSDimitry Andric }); 504bdd1243dSDimitry Andric } 505bdd1243dSDimitry Andric 506bdd1243dSDimitry Andric void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult, 507bdd1243dSDimitry Andric JITDylibSP JD, 508bdd1243dSDimitry Andric JITDylibDepMap &JDDepMap) { 509bdd1243dSDimitry Andric SmallVector<JITDylib *, 16> Worklist({JD.get()}); 510bdd1243dSDimitry Andric DenseSet<JITDylib *> Visited({JD.get()}); 511bdd1243dSDimitry Andric DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols; 512bdd1243dSDimitry Andric ES.runSessionLocked([&]() { 513bdd1243dSDimitry Andric while (!Worklist.empty()) { 514bdd1243dSDimitry Andric auto CurJD = Worklist.back(); 515bdd1243dSDimitry Andric Worklist.pop_back(); 516bdd1243dSDimitry Andric 517bdd1243dSDimitry Andric auto RISItr = RegisteredInitSymbols.find(CurJD); 518bdd1243dSDimitry Andric if (RISItr != RegisteredInitSymbols.end()) { 519bdd1243dSDimitry Andric NewInitSymbols[CurJD] = std::move(RISItr->second); 520bdd1243dSDimitry Andric RegisteredInitSymbols.erase(RISItr); 521bdd1243dSDimitry Andric } 522bdd1243dSDimitry Andric 523bdd1243dSDimitry Andric for (auto *DepJD : JDDepMap[CurJD]) 524bdd1243dSDimitry Andric if (!Visited.count(DepJD)) { 525bdd1243dSDimitry Andric Worklist.push_back(DepJD); 526bdd1243dSDimitry Andric Visited.insert(DepJD); 527bdd1243dSDimitry Andric } 528bdd1243dSDimitry Andric } 529bdd1243dSDimitry Andric }); 530bdd1243dSDimitry Andric 531bdd1243dSDimitry Andric // If there are no further init symbols to look up then send the link order 532bdd1243dSDimitry Andric // (as a list of header addresses) to the caller. 533bdd1243dSDimitry Andric if (NewInitSymbols.empty()) { 534bdd1243dSDimitry Andric // Build the dep info map to return. 535bdd1243dSDimitry Andric COFFJITDylibDepInfoMap DIM; 536bdd1243dSDimitry Andric DIM.reserve(JDDepMap.size()); 537bdd1243dSDimitry Andric for (auto &KV : JDDepMap) { 538bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 539bdd1243dSDimitry Andric COFFJITDylibDepInfo DepInfo; 540bdd1243dSDimitry Andric DepInfo.reserve(KV.second.size()); 541bdd1243dSDimitry Andric for (auto &Dep : KV.second) { 542bdd1243dSDimitry Andric DepInfo.push_back(JITDylibToHeaderAddr[Dep]); 543bdd1243dSDimitry Andric } 544bdd1243dSDimitry Andric auto H = JITDylibToHeaderAddr[KV.first]; 545bdd1243dSDimitry Andric DIM.push_back(std::make_pair(H, std::move(DepInfo))); 546bdd1243dSDimitry Andric } 547bdd1243dSDimitry Andric SendResult(DIM); 548bdd1243dSDimitry Andric return; 549bdd1243dSDimitry Andric } 550bdd1243dSDimitry Andric 551bdd1243dSDimitry Andric // Otherwise issue a lookup and re-run this phase when it completes. 552bdd1243dSDimitry Andric lookupInitSymbolsAsync( 553bdd1243dSDimitry Andric [this, SendResult = std::move(SendResult), &JD, 554bdd1243dSDimitry Andric JDDepMap = std::move(JDDepMap)](Error Err) mutable { 555bdd1243dSDimitry Andric if (Err) 556bdd1243dSDimitry Andric SendResult(std::move(Err)); 557bdd1243dSDimitry Andric else 558bdd1243dSDimitry Andric pushInitializersLoop(std::move(SendResult), JD, JDDepMap); 559bdd1243dSDimitry Andric }, 560bdd1243dSDimitry Andric ES, std::move(NewInitSymbols)); 561bdd1243dSDimitry Andric } 562bdd1243dSDimitry Andric 563bdd1243dSDimitry Andric void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult, 564bdd1243dSDimitry Andric ExecutorAddr JDHeaderAddr) { 565bdd1243dSDimitry Andric JITDylibSP JD; 566bdd1243dSDimitry Andric { 567bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 568bdd1243dSDimitry Andric auto I = HeaderAddrToJITDylib.find(JDHeaderAddr); 569bdd1243dSDimitry Andric if (I != HeaderAddrToJITDylib.end()) 570bdd1243dSDimitry Andric JD = I->second; 571bdd1243dSDimitry Andric } 572bdd1243dSDimitry Andric 573bdd1243dSDimitry Andric LLVM_DEBUG({ 574bdd1243dSDimitry Andric dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") "; 575bdd1243dSDimitry Andric if (JD) 576bdd1243dSDimitry Andric dbgs() << "pushing initializers for " << JD->getName() << "\n"; 577bdd1243dSDimitry Andric else 578bdd1243dSDimitry Andric dbgs() << "No JITDylib for header address.\n"; 579bdd1243dSDimitry Andric }); 580bdd1243dSDimitry Andric 581bdd1243dSDimitry Andric if (!JD) { 582*06c3fb27SDimitry Andric SendResult(make_error<StringError>("No JITDylib with header addr " + 583*06c3fb27SDimitry Andric formatv("{0:x}", JDHeaderAddr), 584bdd1243dSDimitry Andric inconvertibleErrorCode())); 585bdd1243dSDimitry Andric return; 586bdd1243dSDimitry Andric } 587bdd1243dSDimitry Andric 588bdd1243dSDimitry Andric auto JDDepMap = buildJDDepMap(*JD); 589bdd1243dSDimitry Andric if (!JDDepMap) { 590bdd1243dSDimitry Andric SendResult(JDDepMap.takeError()); 591bdd1243dSDimitry Andric return; 592bdd1243dSDimitry Andric } 593bdd1243dSDimitry Andric 594bdd1243dSDimitry Andric pushInitializersLoop(std::move(SendResult), JD, *JDDepMap); 595bdd1243dSDimitry Andric } 596bdd1243dSDimitry Andric 597bdd1243dSDimitry Andric void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult, 598bdd1243dSDimitry Andric ExecutorAddr Handle, StringRef SymbolName) { 599*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "COFFPlatform::rt_lookupSymbol(\"" << Handle << "\")\n"); 600bdd1243dSDimitry Andric 601bdd1243dSDimitry Andric JITDylib *JD = nullptr; 602bdd1243dSDimitry Andric 603bdd1243dSDimitry Andric { 604bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 605bdd1243dSDimitry Andric auto I = HeaderAddrToJITDylib.find(Handle); 606bdd1243dSDimitry Andric if (I != HeaderAddrToJITDylib.end()) 607bdd1243dSDimitry Andric JD = I->second; 608bdd1243dSDimitry Andric } 609bdd1243dSDimitry Andric 610bdd1243dSDimitry Andric if (!JD) { 611*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n"); 612bdd1243dSDimitry Andric SendResult(make_error<StringError>("No JITDylib associated with handle " + 613*06c3fb27SDimitry Andric formatv("{0:x}", Handle), 614bdd1243dSDimitry Andric inconvertibleErrorCode())); 615bdd1243dSDimitry Andric return; 616bdd1243dSDimitry Andric } 617bdd1243dSDimitry Andric 618bdd1243dSDimitry Andric // Use functor class to work around XL build compiler issue on AIX. 619bdd1243dSDimitry Andric class RtLookupNotifyComplete { 620bdd1243dSDimitry Andric public: 621bdd1243dSDimitry Andric RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult) 622bdd1243dSDimitry Andric : SendResult(std::move(SendResult)) {} 623bdd1243dSDimitry Andric void operator()(Expected<SymbolMap> Result) { 624bdd1243dSDimitry Andric if (Result) { 625bdd1243dSDimitry Andric assert(Result->size() == 1 && "Unexpected result map count"); 626*06c3fb27SDimitry Andric SendResult(Result->begin()->second.getAddress()); 627bdd1243dSDimitry Andric } else { 628bdd1243dSDimitry Andric SendResult(Result.takeError()); 629bdd1243dSDimitry Andric } 630bdd1243dSDimitry Andric } 631bdd1243dSDimitry Andric 632bdd1243dSDimitry Andric private: 633bdd1243dSDimitry Andric SendSymbolAddressFn SendResult; 634bdd1243dSDimitry Andric }; 635bdd1243dSDimitry Andric 636bdd1243dSDimitry Andric ES.lookup( 637bdd1243dSDimitry Andric LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 638bdd1243dSDimitry Andric SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready, 639bdd1243dSDimitry Andric RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister); 640bdd1243dSDimitry Andric } 641bdd1243dSDimitry Andric 642bdd1243dSDimitry Andric Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) { 643bdd1243dSDimitry Andric ExecutionSession::JITDispatchHandlerAssociationMap WFs; 644bdd1243dSDimitry Andric 645bdd1243dSDimitry Andric using LookupSymbolSPSSig = 646bdd1243dSDimitry Andric SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString); 647bdd1243dSDimitry Andric WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] = 648bdd1243dSDimitry Andric ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this, 649bdd1243dSDimitry Andric &COFFPlatform::rt_lookupSymbol); 650bdd1243dSDimitry Andric using PushInitializersSPSSig = 651bdd1243dSDimitry Andric SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr); 652bdd1243dSDimitry Andric WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] = 653bdd1243dSDimitry Andric ES.wrapAsyncWithSPS<PushInitializersSPSSig>( 654bdd1243dSDimitry Andric this, &COFFPlatform::rt_pushInitializers); 655bdd1243dSDimitry Andric 656bdd1243dSDimitry Andric return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs)); 657bdd1243dSDimitry Andric } 658bdd1243dSDimitry Andric 659bdd1243dSDimitry Andric Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) { 660bdd1243dSDimitry Andric llvm::sort(BState.Initializers); 661bdd1243dSDimitry Andric if (auto Err = 662bdd1243dSDimitry Andric runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ")) 663bdd1243dSDimitry Andric return Err; 664bdd1243dSDimitry Andric 665bdd1243dSDimitry Andric if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init")) 666bdd1243dSDimitry Andric return Err; 667bdd1243dSDimitry Andric 668bdd1243dSDimitry Andric if (auto Err = 669bdd1243dSDimitry Andric runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ")) 670bdd1243dSDimitry Andric return Err; 671bdd1243dSDimitry Andric return Error::success(); 672bdd1243dSDimitry Andric } 673bdd1243dSDimitry Andric 674bdd1243dSDimitry Andric Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState, 675bdd1243dSDimitry Andric StringRef Start, 676bdd1243dSDimitry Andric StringRef End) { 677bdd1243dSDimitry Andric for (auto &Initializer : BState.Initializers) 678bdd1243dSDimitry Andric if (Initializer.first >= Start && Initializer.first <= End && 679bdd1243dSDimitry Andric Initializer.second) { 680bdd1243dSDimitry Andric auto Res = 681bdd1243dSDimitry Andric ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second); 682bdd1243dSDimitry Andric if (!Res) 683bdd1243dSDimitry Andric return Res.takeError(); 684bdd1243dSDimitry Andric } 685bdd1243dSDimitry Andric return Error::success(); 686bdd1243dSDimitry Andric } 687bdd1243dSDimitry Andric 688bdd1243dSDimitry Andric Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) { 689bdd1243dSDimitry Andric // Lookup of runtime symbols causes the collection of initializers if 690bdd1243dSDimitry Andric // it's static linking setting. 691bdd1243dSDimitry Andric if (auto Err = lookupAndRecordAddrs( 692bdd1243dSDimitry Andric ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD), 693bdd1243dSDimitry Andric { 694bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_platform_bootstrap"), 695bdd1243dSDimitry Andric &orc_rt_coff_platform_bootstrap}, 696bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_platform_shutdown"), 697bdd1243dSDimitry Andric &orc_rt_coff_platform_shutdown}, 698bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_register_jitdylib"), 699bdd1243dSDimitry Andric &orc_rt_coff_register_jitdylib}, 700bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_deregister_jitdylib"), 701bdd1243dSDimitry Andric &orc_rt_coff_deregister_jitdylib}, 702bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_register_object_sections"), 703bdd1243dSDimitry Andric &orc_rt_coff_register_object_sections}, 704bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_deregister_object_sections"), 705bdd1243dSDimitry Andric &orc_rt_coff_deregister_object_sections}, 706bdd1243dSDimitry Andric })) 707bdd1243dSDimitry Andric return Err; 708bdd1243dSDimitry Andric 709bdd1243dSDimitry Andric // Call bootstrap functions 710bdd1243dSDimitry Andric if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap)) 711bdd1243dSDimitry Andric return Err; 712bdd1243dSDimitry Andric 713bdd1243dSDimitry Andric // Do the pending jitdylib registration actions that we couldn't do 714bdd1243dSDimitry Andric // because orc runtime was not linked fully. 715bdd1243dSDimitry Andric for (auto KV : JDBootstrapStates) { 716bdd1243dSDimitry Andric auto &JDBState = KV.second; 717bdd1243dSDimitry Andric if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>( 718bdd1243dSDimitry Andric orc_rt_coff_register_jitdylib, JDBState.JDName, 719bdd1243dSDimitry Andric JDBState.HeaderAddr)) 720bdd1243dSDimitry Andric return Err; 721bdd1243dSDimitry Andric 722bdd1243dSDimitry Andric for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps) 723bdd1243dSDimitry Andric if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr, 724bdd1243dSDimitry Andric SPSCOFFObjectSectionsMap, bool)>( 725bdd1243dSDimitry Andric orc_rt_coff_register_object_sections, JDBState.HeaderAddr, 726bdd1243dSDimitry Andric ObjSectionMap, false)) 727bdd1243dSDimitry Andric return Err; 728bdd1243dSDimitry Andric } 729bdd1243dSDimitry Andric 730bdd1243dSDimitry Andric // Run static initializers collected in bootstrap stage. 731bdd1243dSDimitry Andric for (auto KV : JDBootstrapStates) { 732bdd1243dSDimitry Andric auto &JDBState = KV.second; 733bdd1243dSDimitry Andric if (auto Err = runBootstrapInitializers(JDBState)) 734bdd1243dSDimitry Andric return Err; 735bdd1243dSDimitry Andric } 736bdd1243dSDimitry Andric 737bdd1243dSDimitry Andric return Error::success(); 738bdd1243dSDimitry Andric } 739bdd1243dSDimitry Andric 740bdd1243dSDimitry Andric Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD, 741bdd1243dSDimitry Andric StringRef SymbolName) { 742bdd1243dSDimitry Andric ExecutorAddr jit_function; 743bdd1243dSDimitry Andric auto AfterCLookupErr = lookupAndRecordAddrs( 744bdd1243dSDimitry Andric ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD), 745bdd1243dSDimitry Andric {{ES.intern(SymbolName), &jit_function}}); 746bdd1243dSDimitry Andric if (!AfterCLookupErr) { 747bdd1243dSDimitry Andric auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function); 748bdd1243dSDimitry Andric if (!Res) 749bdd1243dSDimitry Andric return Res.takeError(); 750bdd1243dSDimitry Andric return Error::success(); 751bdd1243dSDimitry Andric } 752bdd1243dSDimitry Andric if (!AfterCLookupErr.isA<SymbolsNotFound>()) 753bdd1243dSDimitry Andric return AfterCLookupErr; 754bdd1243dSDimitry Andric consumeError(std::move(AfterCLookupErr)); 755bdd1243dSDimitry Andric return Error::success(); 756bdd1243dSDimitry Andric } 757bdd1243dSDimitry Andric 758bdd1243dSDimitry Andric void COFFPlatform::COFFPlatformPlugin::modifyPassConfig( 759bdd1243dSDimitry Andric MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 760bdd1243dSDimitry Andric jitlink::PassConfiguration &Config) { 761bdd1243dSDimitry Andric 762bdd1243dSDimitry Andric bool IsBootstrapping = CP.Bootstrapping.load(); 763bdd1243dSDimitry Andric 764bdd1243dSDimitry Andric if (auto InitSymbol = MR.getInitializerSymbol()) { 765bdd1243dSDimitry Andric if (InitSymbol == CP.COFFHeaderStartSymbol) { 766bdd1243dSDimitry Andric Config.PostAllocationPasses.push_back( 767bdd1243dSDimitry Andric [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) { 768bdd1243dSDimitry Andric return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping); 769bdd1243dSDimitry Andric }); 770bdd1243dSDimitry Andric return; 771bdd1243dSDimitry Andric } 772bdd1243dSDimitry Andric Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) { 773bdd1243dSDimitry Andric return preserveInitializerSections(G, MR); 774bdd1243dSDimitry Andric }); 775bdd1243dSDimitry Andric } 776bdd1243dSDimitry Andric 777bdd1243dSDimitry Andric if (!IsBootstrapping) 778bdd1243dSDimitry Andric Config.PostFixupPasses.push_back( 779bdd1243dSDimitry Andric [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 780bdd1243dSDimitry Andric return registerObjectPlatformSections(G, JD); 781bdd1243dSDimitry Andric }); 782bdd1243dSDimitry Andric else 783bdd1243dSDimitry Andric Config.PostFixupPasses.push_back( 784bdd1243dSDimitry Andric [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 785bdd1243dSDimitry Andric return registerObjectPlatformSectionsInBootstrap(G, JD); 786bdd1243dSDimitry Andric }); 787bdd1243dSDimitry Andric } 788bdd1243dSDimitry Andric 789bdd1243dSDimitry Andric ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap 790bdd1243dSDimitry Andric COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies( 791bdd1243dSDimitry Andric MaterializationResponsibility &MR) { 792bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex); 793bdd1243dSDimitry Andric auto I = InitSymbolDeps.find(&MR); 794bdd1243dSDimitry Andric if (I != InitSymbolDeps.end()) { 795bdd1243dSDimitry Andric SyntheticSymbolDependenciesMap Result; 796bdd1243dSDimitry Andric Result[MR.getInitializerSymbol()] = std::move(I->second); 797bdd1243dSDimitry Andric InitSymbolDeps.erase(&MR); 798bdd1243dSDimitry Andric return Result; 799bdd1243dSDimitry Andric } 800bdd1243dSDimitry Andric return SyntheticSymbolDependenciesMap(); 801bdd1243dSDimitry Andric } 802bdd1243dSDimitry Andric 803bdd1243dSDimitry Andric Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol( 804bdd1243dSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR, 805bdd1243dSDimitry Andric bool IsBootstraping) { 806bdd1243dSDimitry Andric auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 807bdd1243dSDimitry Andric return Sym->getName() == *CP.COFFHeaderStartSymbol; 808bdd1243dSDimitry Andric }); 809bdd1243dSDimitry Andric assert(I != G.defined_symbols().end() && "Missing COFF header start symbol"); 810bdd1243dSDimitry Andric 811bdd1243dSDimitry Andric auto &JD = MR.getTargetJITDylib(); 812bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(CP.PlatformMutex); 813bdd1243dSDimitry Andric auto HeaderAddr = (*I)->getAddress(); 814bdd1243dSDimitry Andric CP.JITDylibToHeaderAddr[&JD] = HeaderAddr; 815bdd1243dSDimitry Andric CP.HeaderAddrToJITDylib[HeaderAddr] = &JD; 816bdd1243dSDimitry Andric if (!IsBootstraping) { 817bdd1243dSDimitry Andric G.allocActions().push_back( 818bdd1243dSDimitry Andric {cantFail(WrapperFunctionCall::Create< 819bdd1243dSDimitry Andric SPSArgList<SPSString, SPSExecutorAddr>>( 820bdd1243dSDimitry Andric CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)), 821bdd1243dSDimitry Andric cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 822bdd1243dSDimitry Andric CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))}); 823bdd1243dSDimitry Andric } else { 824bdd1243dSDimitry Andric G.allocActions().push_back( 825bdd1243dSDimitry Andric {{}, 826bdd1243dSDimitry Andric cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 827bdd1243dSDimitry Andric CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))}); 828bdd1243dSDimitry Andric JDBootstrapState BState; 829bdd1243dSDimitry Andric BState.JD = &JD; 830bdd1243dSDimitry Andric BState.JDName = JD.getName(); 831bdd1243dSDimitry Andric BState.HeaderAddr = HeaderAddr; 832bdd1243dSDimitry Andric CP.JDBootstrapStates.emplace(&JD, BState); 833bdd1243dSDimitry Andric } 834bdd1243dSDimitry Andric 835bdd1243dSDimitry Andric return Error::success(); 836bdd1243dSDimitry Andric } 837bdd1243dSDimitry Andric 838bdd1243dSDimitry Andric Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections( 839bdd1243dSDimitry Andric jitlink::LinkGraph &G, JITDylib &JD) { 840bdd1243dSDimitry Andric COFFObjectSectionsMap ObjSecs; 841bdd1243dSDimitry Andric auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD]; 842bdd1243dSDimitry Andric assert(HeaderAddr && "Must be registered jitdylib"); 843bdd1243dSDimitry Andric for (auto &S : G.sections()) { 844bdd1243dSDimitry Andric jitlink::SectionRange Range(S); 845bdd1243dSDimitry Andric if (Range.getSize()) 846bdd1243dSDimitry Andric ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange())); 847bdd1243dSDimitry Andric } 848bdd1243dSDimitry Andric 849bdd1243dSDimitry Andric G.allocActions().push_back( 850bdd1243dSDimitry Andric {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>( 851bdd1243dSDimitry Andric CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)), 852bdd1243dSDimitry Andric cantFail( 853bdd1243dSDimitry Andric WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>( 854bdd1243dSDimitry Andric CP.orc_rt_coff_deregister_object_sections, HeaderAddr, 855bdd1243dSDimitry Andric ObjSecs))}); 856bdd1243dSDimitry Andric 857bdd1243dSDimitry Andric return Error::success(); 858bdd1243dSDimitry Andric } 859bdd1243dSDimitry Andric 860bdd1243dSDimitry Andric Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections( 861bdd1243dSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 862bdd1243dSDimitry Andric JITLinkSymbolSet InitSectionSymbols; 863bdd1243dSDimitry Andric for (auto &Sec : G.sections()) 864*06c3fb27SDimitry Andric if (isCOFFInitializerSection(Sec.getName())) 865bdd1243dSDimitry Andric for (auto *B : Sec.blocks()) 866bdd1243dSDimitry Andric if (!B->edges_empty()) 867bdd1243dSDimitry Andric InitSectionSymbols.insert( 868bdd1243dSDimitry Andric &G.addAnonymousSymbol(*B, 0, 0, false, true)); 869bdd1243dSDimitry Andric 870bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex); 871bdd1243dSDimitry Andric InitSymbolDeps[&MR] = InitSectionSymbols; 872bdd1243dSDimitry Andric return Error::success(); 873bdd1243dSDimitry Andric } 874bdd1243dSDimitry Andric 875bdd1243dSDimitry Andric Error COFFPlatform::COFFPlatformPlugin:: 876bdd1243dSDimitry Andric registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G, 877bdd1243dSDimitry Andric JITDylib &JD) { 878bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(CP.PlatformMutex); 879bdd1243dSDimitry Andric auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD]; 880bdd1243dSDimitry Andric COFFObjectSectionsMap ObjSecs; 881bdd1243dSDimitry Andric for (auto &S : G.sections()) { 882bdd1243dSDimitry Andric jitlink::SectionRange Range(S); 883bdd1243dSDimitry Andric if (Range.getSize()) 884bdd1243dSDimitry Andric ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange())); 885bdd1243dSDimitry Andric } 886bdd1243dSDimitry Andric 887bdd1243dSDimitry Andric G.allocActions().push_back( 888bdd1243dSDimitry Andric {{}, 889bdd1243dSDimitry Andric cantFail( 890bdd1243dSDimitry Andric WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>( 891bdd1243dSDimitry Andric CP.orc_rt_coff_deregister_object_sections, HeaderAddr, 892bdd1243dSDimitry Andric ObjSecs))}); 893bdd1243dSDimitry Andric 894bdd1243dSDimitry Andric auto &BState = CP.JDBootstrapStates[&JD]; 895bdd1243dSDimitry Andric BState.ObjectSectionsMaps.push_back(std::move(ObjSecs)); 896bdd1243dSDimitry Andric 897bdd1243dSDimitry Andric // Collect static initializers 898bdd1243dSDimitry Andric for (auto &S : G.sections()) 899*06c3fb27SDimitry Andric if (isCOFFInitializerSection(S.getName())) 900bdd1243dSDimitry Andric for (auto *B : S.blocks()) { 901bdd1243dSDimitry Andric if (B->edges_empty()) 902bdd1243dSDimitry Andric continue; 903bdd1243dSDimitry Andric for (auto &E : B->edges()) 904bdd1243dSDimitry Andric BState.Initializers.push_back(std::make_pair( 905*06c3fb27SDimitry Andric S.getName().str(), E.getTarget().getAddress() + E.getAddend())); 906bdd1243dSDimitry Andric } 907bdd1243dSDimitry Andric 908bdd1243dSDimitry Andric return Error::success(); 909bdd1243dSDimitry Andric } 910bdd1243dSDimitry Andric 911bdd1243dSDimitry Andric } // End namespace orc. 912bdd1243dSDimitry Andric } // End namespace llvm. 913