Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
35266 views
//===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"9#include "llvm/ExecutionEngine/Orc/DebugUtils.h"10#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"11#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"12#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"1314#include "llvm/Object/COFF.h"1516#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"1718#include "llvm/ExecutionEngine/JITLink/x86_64.h"1920#define DEBUG_TYPE "orc"2122using namespace llvm;23using namespace llvm::orc;24using namespace llvm::orc::shared;2526namespace llvm {27namespace orc {28namespace shared {2930using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;31using SPSCOFFJITDylibDepInfoMap =32SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;33using SPSCOFFObjectSectionsMap =34SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;35using SPSCOFFRegisterObjectSectionsArgs =36SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;37using SPSCOFFDeregisterObjectSectionsArgs =38SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;3940} // namespace shared41} // namespace orc42} // namespace llvm43namespace {4445class COFFHeaderMaterializationUnit : public MaterializationUnit {46public:47COFFHeaderMaterializationUnit(COFFPlatform &CP,48const SymbolStringPtr &HeaderStartSymbol)49: MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),50CP(CP) {}5152StringRef getName() const override { return "COFFHeaderMU"; }5354void materialize(std::unique_ptr<MaterializationResponsibility> R) override {55unsigned PointerSize;56llvm::endianness Endianness;57const auto &TT = CP.getExecutionSession().getTargetTriple();5859switch (TT.getArch()) {60case Triple::x86_64:61PointerSize = 8;62Endianness = llvm::endianness::little;63break;64default:65llvm_unreachable("Unrecognized architecture");66}6768auto G = std::make_unique<jitlink::LinkGraph>(69"<COFFHeaderMU>", TT, PointerSize, Endianness,70jitlink::getGenericEdgeKindName);71auto &HeaderSection = G->createSection("__header", MemProt::Read);72auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);7374// Init symbol is __ImageBase symbol.75auto &ImageBaseSymbol = G->addDefinedSymbol(76HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),77jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);7879addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);8081CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));82}8384void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}8586private:87struct HeaderSymbol {88const char *Name;89uint64_t Offset;90};9192struct NTHeader {93support::ulittle32_t PEMagic;94object::coff_file_header FileHeader;95struct PEHeader {96object::pe32plus_header Header;97object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];98} OptionalHeader;99};100101struct HeaderBlockContent {102object::dos_header DOSHeader;103COFFHeaderMaterializationUnit::NTHeader NTHeader;104};105106static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,107jitlink::Section &HeaderSection) {108HeaderBlockContent Hdr = {};109110// Set up magic111Hdr.DOSHeader.Magic[0] = 'M';112Hdr.DOSHeader.Magic[1] = 'Z';113Hdr.DOSHeader.AddressOfNewExeHeader =114offsetof(HeaderBlockContent, NTHeader);115uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);116Hdr.NTHeader.PEMagic = PEMagic;117Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;118119switch (G.getTargetTriple().getArch()) {120case Triple::x86_64:121Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;122break;123default:124llvm_unreachable("Unrecognized architecture");125}126127auto HeaderContent = G.allocateContent(128ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));129130return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,1310);132}133134static void addImageBaseRelocationEdge(jitlink::Block &B,135jitlink::Symbol &ImageBase) {136auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +137offsetof(NTHeader, OptionalHeader) +138offsetof(object::pe32plus_header, ImageBase);139B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);140}141142static MaterializationUnit::Interface143createHeaderInterface(COFFPlatform &MOP,144const SymbolStringPtr &HeaderStartSymbol) {145SymbolFlagsMap HeaderSymbolFlags;146147HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;148149return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),150HeaderStartSymbol);151}152153COFFPlatform &CP;154};155156} // end anonymous namespace157158namespace llvm {159namespace orc {160161Expected<std::unique_ptr<COFFPlatform>> COFFPlatform::Create(162ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,163JITDylib &PlatformJD, std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,164LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,165const char *VCRuntimePath, std::optional<SymbolAliasMap> RuntimeAliases) {166167// If the target is not supported then bail out immediately.168if (!supportedTarget(ES.getTargetTriple()))169return make_error<StringError>("Unsupported COFFPlatform triple: " +170ES.getTargetTriple().str(),171inconvertibleErrorCode());172173auto &EPC = ES.getExecutorProcessControl();174175auto GeneratorArchive =176object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef());177if (!GeneratorArchive)178return GeneratorArchive.takeError();179180auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Create(181ObjLinkingLayer, nullptr, std::move(*GeneratorArchive));182if (!OrcRuntimeArchiveGenerator)183return OrcRuntimeArchiveGenerator.takeError();184185// We need a second instance of the archive (for now) for the Platform. We186// can `cantFail` this call, since if it were going to fail it would have187// failed above.188auto RuntimeArchive = cantFail(189object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef()));190191// Create default aliases if the caller didn't supply any.192if (!RuntimeAliases)193RuntimeAliases = standardPlatformAliases(ES);194195// Define the aliases.196if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))197return std::move(Err);198199auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");200201// Add JIT-dispatch function support symbols.202if (auto Err = HostFuncJD.define(203absoluteSymbols({{ES.intern("__orc_rt_jit_dispatch"),204{EPC.getJITDispatchInfo().JITDispatchFunction,205JITSymbolFlags::Exported}},206{ES.intern("__orc_rt_jit_dispatch_ctx"),207{EPC.getJITDispatchInfo().JITDispatchContext,208JITSymbolFlags::Exported}}})))209return std::move(Err);210211PlatformJD.addToLinkOrder(HostFuncJD);212213// Create the instance.214Error Err = Error::success();215auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(216ES, ObjLinkingLayer, PlatformJD, std::move(*OrcRuntimeArchiveGenerator),217std::move(OrcRuntimeArchiveBuffer), std::move(RuntimeArchive),218std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));219if (Err)220return std::move(Err);221return std::move(P);222}223224Expected<std::unique_ptr<COFFPlatform>>225COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,226JITDylib &PlatformJD, const char *OrcRuntimePath,227LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,228const char *VCRuntimePath,229std::optional<SymbolAliasMap> RuntimeAliases) {230231auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);232if (!ArchiveBuffer)233return createFileError(OrcRuntimePath, ArchiveBuffer.getError());234235return Create(ES, ObjLinkingLayer, PlatformJD, std::move(*ArchiveBuffer),236std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath,237std::move(RuntimeAliases));238}239240Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {241auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");242if (!PerJDObj)243return PerJDObj.takeError();244245if (!*PerJDObj)246return make_error<StringError>("Could not find per jd object file",247inconvertibleErrorCode());248249auto Buffer = (*PerJDObj)->getAsBinary();250if (!Buffer)251return Buffer.takeError();252253return (*Buffer)->getMemoryBufferRef();254}255256static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,257ArrayRef<std::pair<const char *, const char *>> AL) {258for (auto &KV : AL) {259auto AliasName = ES.intern(KV.first);260assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");261Aliases[std::move(AliasName)] = {ES.intern(KV.second),262JITSymbolFlags::Exported};263}264}265266Error COFFPlatform::setupJITDylib(JITDylib &JD) {267if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(268*this, COFFHeaderStartSymbol)))269return Err;270271if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())272return Err;273274// Define the CXX aliases.275SymbolAliasMap CXXAliases;276addAliases(ES, CXXAliases, requiredCXXAliases());277if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))278return Err;279280auto PerJDObj = getPerJDObjectFile();281if (!PerJDObj)282return PerJDObj.takeError();283284auto I = getObjectFileInterface(ES, *PerJDObj);285if (!I)286return I.takeError();287288if (auto Err = ObjLinkingLayer.add(289JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))290return Err;291292if (!Bootstrapping) {293auto ImportedLibs = StaticVCRuntime294? VCRuntimeBootstrap->loadStaticVCRuntime(JD)295: VCRuntimeBootstrap->loadDynamicVCRuntime(JD);296if (!ImportedLibs)297return ImportedLibs.takeError();298for (auto &Lib : *ImportedLibs)299if (auto Err = LoadDynLibrary(JD, Lib))300return Err;301if (StaticVCRuntime)302if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))303return Err;304}305306JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));307return Error::success();308}309310Error COFFPlatform::teardownJITDylib(JITDylib &JD) {311std::lock_guard<std::mutex> Lock(PlatformMutex);312auto I = JITDylibToHeaderAddr.find(&JD);313if (I != JITDylibToHeaderAddr.end()) {314assert(HeaderAddrToJITDylib.count(I->second) &&315"HeaderAddrToJITDylib missing entry");316HeaderAddrToJITDylib.erase(I->second);317JITDylibToHeaderAddr.erase(I);318}319return Error::success();320}321322Error COFFPlatform::notifyAdding(ResourceTracker &RT,323const MaterializationUnit &MU) {324auto &JD = RT.getJITDylib();325const auto &InitSym = MU.getInitializerSymbol();326if (!InitSym)327return Error::success();328329RegisteredInitSymbols[&JD].add(InitSym,330SymbolLookupFlags::WeaklyReferencedSymbol);331332LLVM_DEBUG({333dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "334<< MU.getName() << "\n";335});336return Error::success();337}338339Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {340llvm_unreachable("Not supported yet");341}342343SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {344SymbolAliasMap Aliases;345addAliases(ES, Aliases, standardRuntimeUtilityAliases());346return Aliases;347}348349ArrayRef<std::pair<const char *, const char *>>350COFFPlatform::requiredCXXAliases() {351static const std::pair<const char *, const char *> RequiredCXXAliases[] = {352{"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},353{"_onexit", "__orc_rt_coff_onexit_per_jd"},354{"atexit", "__orc_rt_coff_atexit_per_jd"}};355356return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);357}358359ArrayRef<std::pair<const char *, const char *>>360COFFPlatform::standardRuntimeUtilityAliases() {361static const std::pair<const char *, const char *>362StandardRuntimeUtilityAliases[] = {363{"__orc_rt_run_program", "__orc_rt_coff_run_program"},364{"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},365{"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},366{"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},367{"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},368{"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};369370return ArrayRef<std::pair<const char *, const char *>>(371StandardRuntimeUtilityAliases);372}373374bool COFFPlatform::supportedTarget(const Triple &TT) {375switch (TT.getArch()) {376case Triple::x86_64:377return true;378default:379return false;380}381}382383COFFPlatform::COFFPlatform(384ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,385JITDylib &PlatformJD,386std::unique_ptr<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator,387std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,388std::unique_ptr<object::Archive> OrcRuntimeArchive,389LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,390const char *VCRuntimePath, Error &Err)391: ES(ES), ObjLinkingLayer(ObjLinkingLayer),392LoadDynLibrary(std::move(LoadDynLibrary)),393OrcRuntimeArchiveBuffer(std::move(OrcRuntimeArchiveBuffer)),394OrcRuntimeArchive(std::move(OrcRuntimeArchive)),395StaticVCRuntime(StaticVCRuntime),396COFFHeaderStartSymbol(ES.intern("__ImageBase")) {397ErrorAsOutParameter _(&Err);398399Bootstrapping.store(true);400ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));401402// Load vc runtime403auto VCRT =404COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);405if (!VCRT) {406Err = VCRT.takeError();407return;408}409VCRuntimeBootstrap = std::move(*VCRT);410411for (auto &Lib : OrcRuntimeGenerator->getImportedDynamicLibraries())412DylibsToPreload.insert(Lib);413414auto ImportedLibs =415StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)416: VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);417if (!ImportedLibs) {418Err = ImportedLibs.takeError();419return;420}421422for (auto &Lib : *ImportedLibs)423DylibsToPreload.insert(Lib);424425PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));426427// PlatformJD hasn't been set up by the platform yet (since we're creating428// the platform now), so set it up.429if (auto E2 = setupJITDylib(PlatformJD)) {430Err = std::move(E2);431return;432}433434for (auto& Lib : DylibsToPreload)435if (auto E2 = this->LoadDynLibrary(PlatformJD, Lib)) {436Err = std::move(E2);437return;438}439440if (StaticVCRuntime)441if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {442Err = std::move(E2);443return;444}445446// Associate wrapper function tags with JIT-side function implementations.447if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {448Err = std::move(E2);449return;450}451452// Lookup addresses of runtime functions callable by the platform,453// call the platform bootstrap function to initialize the platform-state454// object in the executor.455if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {456Err = std::move(E2);457return;458}459460Bootstrapping.store(false);461JDBootstrapStates.clear();462}463464Expected<COFFPlatform::JITDylibDepMap>465COFFPlatform::buildJDDepMap(JITDylib &JD) {466return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {467JITDylibDepMap JDDepMap;468469SmallVector<JITDylib *, 16> Worklist({&JD});470while (!Worklist.empty()) {471auto CurJD = Worklist.back();472Worklist.pop_back();473474auto &DM = JDDepMap[CurJD];475CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {476DM.reserve(O.size());477for (auto &KV : O) {478if (KV.first == CurJD)479continue;480{481// Bare jitdylibs not known to the platform482std::lock_guard<std::mutex> Lock(PlatformMutex);483if (!JITDylibToHeaderAddr.count(KV.first)) {484LLVM_DEBUG({485dbgs() << "JITDylib unregistered to COFFPlatform detected in "486"LinkOrder: "487<< CurJD->getName() << "\n";488});489continue;490}491}492DM.push_back(KV.first);493// Push unvisited entry.494if (!JDDepMap.count(KV.first)) {495Worklist.push_back(KV.first);496JDDepMap[KV.first] = {};497}498}499});500}501return std::move(JDDepMap);502});503}504505void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,506JITDylibSP JD,507JITDylibDepMap &JDDepMap) {508SmallVector<JITDylib *, 16> Worklist({JD.get()});509DenseSet<JITDylib *> Visited({JD.get()});510DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;511ES.runSessionLocked([&]() {512while (!Worklist.empty()) {513auto CurJD = Worklist.back();514Worklist.pop_back();515516auto RISItr = RegisteredInitSymbols.find(CurJD);517if (RISItr != RegisteredInitSymbols.end()) {518NewInitSymbols[CurJD] = std::move(RISItr->second);519RegisteredInitSymbols.erase(RISItr);520}521522for (auto *DepJD : JDDepMap[CurJD])523if (!Visited.count(DepJD)) {524Worklist.push_back(DepJD);525Visited.insert(DepJD);526}527}528});529530// If there are no further init symbols to look up then send the link order531// (as a list of header addresses) to the caller.532if (NewInitSymbols.empty()) {533// Build the dep info map to return.534COFFJITDylibDepInfoMap DIM;535DIM.reserve(JDDepMap.size());536for (auto &KV : JDDepMap) {537std::lock_guard<std::mutex> Lock(PlatformMutex);538COFFJITDylibDepInfo DepInfo;539DepInfo.reserve(KV.second.size());540for (auto &Dep : KV.second) {541DepInfo.push_back(JITDylibToHeaderAddr[Dep]);542}543auto H = JITDylibToHeaderAddr[KV.first];544DIM.push_back(std::make_pair(H, std::move(DepInfo)));545}546SendResult(DIM);547return;548}549550// Otherwise issue a lookup and re-run this phase when it completes.551lookupInitSymbolsAsync(552[this, SendResult = std::move(SendResult), &JD,553JDDepMap = std::move(JDDepMap)](Error Err) mutable {554if (Err)555SendResult(std::move(Err));556else557pushInitializersLoop(std::move(SendResult), JD, JDDepMap);558},559ES, std::move(NewInitSymbols));560}561562void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,563ExecutorAddr JDHeaderAddr) {564JITDylibSP JD;565{566std::lock_guard<std::mutex> Lock(PlatformMutex);567auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);568if (I != HeaderAddrToJITDylib.end())569JD = I->second;570}571572LLVM_DEBUG({573dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";574if (JD)575dbgs() << "pushing initializers for " << JD->getName() << "\n";576else577dbgs() << "No JITDylib for header address.\n";578});579580if (!JD) {581SendResult(make_error<StringError>("No JITDylib with header addr " +582formatv("{0:x}", JDHeaderAddr),583inconvertibleErrorCode()));584return;585}586587auto JDDepMap = buildJDDepMap(*JD);588if (!JDDepMap) {589SendResult(JDDepMap.takeError());590return;591}592593pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);594}595596void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,597ExecutorAddr Handle, StringRef SymbolName) {598LLVM_DEBUG(dbgs() << "COFFPlatform::rt_lookupSymbol(\"" << Handle << "\")\n");599600JITDylib *JD = nullptr;601602{603std::lock_guard<std::mutex> Lock(PlatformMutex);604auto I = HeaderAddrToJITDylib.find(Handle);605if (I != HeaderAddrToJITDylib.end())606JD = I->second;607}608609if (!JD) {610LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n");611SendResult(make_error<StringError>("No JITDylib associated with handle " +612formatv("{0:x}", Handle),613inconvertibleErrorCode()));614return;615}616617// Use functor class to work around XL build compiler issue on AIX.618class RtLookupNotifyComplete {619public:620RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)621: SendResult(std::move(SendResult)) {}622void operator()(Expected<SymbolMap> Result) {623if (Result) {624assert(Result->size() == 1 && "Unexpected result map count");625SendResult(Result->begin()->second.getAddress());626} else {627SendResult(Result.takeError());628}629}630631private:632SendSymbolAddressFn SendResult;633};634635ES.lookup(636LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},637SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,638RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);639}640641Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {642ExecutionSession::JITDispatchHandlerAssociationMap WFs;643644using LookupSymbolSPSSig =645SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);646WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =647ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,648&COFFPlatform::rt_lookupSymbol);649using PushInitializersSPSSig =650SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);651WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =652ES.wrapAsyncWithSPS<PushInitializersSPSSig>(653this, &COFFPlatform::rt_pushInitializers);654655return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));656}657658Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {659llvm::sort(BState.Initializers);660if (auto Err =661runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))662return Err;663664if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))665return Err;666667if (auto Err =668runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))669return Err;670return Error::success();671}672673Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,674StringRef Start,675StringRef End) {676for (auto &Initializer : BState.Initializers)677if (Initializer.first >= Start && Initializer.first <= End &&678Initializer.second) {679auto Res =680ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);681if (!Res)682return Res.takeError();683}684return Error::success();685}686687Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {688// Lookup of runtime symbols causes the collection of initializers if689// it's static linking setting.690if (auto Err = lookupAndRecordAddrs(691ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),692{693{ES.intern("__orc_rt_coff_platform_bootstrap"),694&orc_rt_coff_platform_bootstrap},695{ES.intern("__orc_rt_coff_platform_shutdown"),696&orc_rt_coff_platform_shutdown},697{ES.intern("__orc_rt_coff_register_jitdylib"),698&orc_rt_coff_register_jitdylib},699{ES.intern("__orc_rt_coff_deregister_jitdylib"),700&orc_rt_coff_deregister_jitdylib},701{ES.intern("__orc_rt_coff_register_object_sections"),702&orc_rt_coff_register_object_sections},703{ES.intern("__orc_rt_coff_deregister_object_sections"),704&orc_rt_coff_deregister_object_sections},705}))706return Err;707708// Call bootstrap functions709if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))710return Err;711712// Do the pending jitdylib registration actions that we couldn't do713// because orc runtime was not linked fully.714for (auto KV : JDBootstrapStates) {715auto &JDBState = KV.second;716if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(717orc_rt_coff_register_jitdylib, JDBState.JDName,718JDBState.HeaderAddr))719return Err;720721for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)722if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,723SPSCOFFObjectSectionsMap, bool)>(724orc_rt_coff_register_object_sections, JDBState.HeaderAddr,725ObjSectionMap, false))726return Err;727}728729// Run static initializers collected in bootstrap stage.730for (auto KV : JDBootstrapStates) {731auto &JDBState = KV.second;732if (auto Err = runBootstrapInitializers(JDBState))733return Err;734}735736return Error::success();737}738739Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,740StringRef SymbolName) {741ExecutorAddr jit_function;742auto AfterCLookupErr = lookupAndRecordAddrs(743ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),744{{ES.intern(SymbolName), &jit_function}});745if (!AfterCLookupErr) {746auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);747if (!Res)748return Res.takeError();749return Error::success();750}751if (!AfterCLookupErr.isA<SymbolsNotFound>())752return AfterCLookupErr;753consumeError(std::move(AfterCLookupErr));754return Error::success();755}756757void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(758MaterializationResponsibility &MR, jitlink::LinkGraph &LG,759jitlink::PassConfiguration &Config) {760761bool IsBootstrapping = CP.Bootstrapping.load();762763if (auto InitSymbol = MR.getInitializerSymbol()) {764if (InitSymbol == CP.COFFHeaderStartSymbol) {765Config.PostAllocationPasses.push_back(766[this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {767return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);768});769return;770}771Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {772return preserveInitializerSections(G, MR);773});774}775776if (!IsBootstrapping)777Config.PostFixupPasses.push_back(778[this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {779return registerObjectPlatformSections(G, JD);780});781else782Config.PostFixupPasses.push_back(783[this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {784return registerObjectPlatformSectionsInBootstrap(G, JD);785});786}787788ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap789COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(790MaterializationResponsibility &MR) {791std::lock_guard<std::mutex> Lock(PluginMutex);792auto I = InitSymbolDeps.find(&MR);793if (I != InitSymbolDeps.end()) {794SyntheticSymbolDependenciesMap Result;795Result[MR.getInitializerSymbol()] = std::move(I->second);796InitSymbolDeps.erase(&MR);797return Result;798}799return SyntheticSymbolDependenciesMap();800}801802Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(803jitlink::LinkGraph &G, MaterializationResponsibility &MR,804bool IsBootstraping) {805auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {806return Sym->getName() == *CP.COFFHeaderStartSymbol;807});808assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");809810auto &JD = MR.getTargetJITDylib();811std::lock_guard<std::mutex> Lock(CP.PlatformMutex);812auto HeaderAddr = (*I)->getAddress();813CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;814CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;815if (!IsBootstraping) {816G.allocActions().push_back(817{cantFail(WrapperFunctionCall::Create<818SPSArgList<SPSString, SPSExecutorAddr>>(819CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),820cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(821CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});822} else {823G.allocActions().push_back(824{{},825cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(826CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});827JDBootstrapState BState;828BState.JD = &JD;829BState.JDName = JD.getName();830BState.HeaderAddr = HeaderAddr;831CP.JDBootstrapStates.emplace(&JD, BState);832}833834return Error::success();835}836837Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(838jitlink::LinkGraph &G, JITDylib &JD) {839COFFObjectSectionsMap ObjSecs;840auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];841assert(HeaderAddr && "Must be registered jitdylib");842for (auto &S : G.sections()) {843jitlink::SectionRange Range(S);844if (Range.getSize())845ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));846}847848G.allocActions().push_back(849{cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(850CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),851cantFail(852WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(853CP.orc_rt_coff_deregister_object_sections, HeaderAddr,854ObjSecs))});855856return Error::success();857}858859Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(860jitlink::LinkGraph &G, MaterializationResponsibility &MR) {861JITLinkSymbolSet InitSectionSymbols;862for (auto &Sec : G.sections())863if (isCOFFInitializerSection(Sec.getName()))864for (auto *B : Sec.blocks())865if (!B->edges_empty())866InitSectionSymbols.insert(867&G.addAnonymousSymbol(*B, 0, 0, false, true));868869std::lock_guard<std::mutex> Lock(PluginMutex);870InitSymbolDeps[&MR] = InitSectionSymbols;871return Error::success();872}873874Error COFFPlatform::COFFPlatformPlugin::875registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,876JITDylib &JD) {877std::lock_guard<std::mutex> Lock(CP.PlatformMutex);878auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];879COFFObjectSectionsMap ObjSecs;880for (auto &S : G.sections()) {881jitlink::SectionRange Range(S);882if (Range.getSize())883ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));884}885886G.allocActions().push_back(887{{},888cantFail(889WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(890CP.orc_rt_coff_deregister_object_sections, HeaderAddr,891ObjSecs))});892893auto &BState = CP.JDBootstrapStates[&JD];894BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));895896// Collect static initializers897for (auto &S : G.sections())898if (isCOFFInitializerSection(S.getName()))899for (auto *B : S.blocks()) {900if (B->edges_empty())901continue;902for (auto &E : B->edges())903BState.Initializers.push_back(std::make_pair(904S.getName().str(), E.getTarget().getAddress() + E.getAddend()));905}906907return Error::success();908}909910} // End namespace orc.911} // End namespace llvm.912913914