123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902 |
- //===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
- #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
- #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
- #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
- #include "llvm/Object/COFF.h"
- #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
- #include "llvm/ExecutionEngine/JITLink/x86_64.h"
- #define DEBUG_TYPE "orc"
- using namespace llvm;
- using namespace llvm::orc;
- using namespace llvm::orc::shared;
- namespace llvm {
- namespace orc {
- namespace shared {
- using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;
- using SPSCOFFJITDylibDepInfoMap =
- SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;
- using SPSCOFFObjectSectionsMap =
- SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
- using SPSCOFFRegisterObjectSectionsArgs =
- SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;
- using SPSCOFFDeregisterObjectSectionsArgs =
- SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;
- } // namespace shared
- } // namespace orc
- } // namespace llvm
- namespace {
- class COFFHeaderMaterializationUnit : public MaterializationUnit {
- public:
- COFFHeaderMaterializationUnit(COFFPlatform &CP,
- const SymbolStringPtr &HeaderStartSymbol)
- : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
- CP(CP) {}
- StringRef getName() const override { return "COFFHeaderMU"; }
- void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
- unsigned PointerSize;
- support::endianness Endianness;
- const auto &TT =
- CP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
- switch (TT.getArch()) {
- case Triple::x86_64:
- PointerSize = 8;
- Endianness = support::endianness::little;
- break;
- default:
- llvm_unreachable("Unrecognized architecture");
- }
- auto G = std::make_unique<jitlink::LinkGraph>(
- "<COFFHeaderMU>", TT, PointerSize, Endianness,
- jitlink::getGenericEdgeKindName);
- auto &HeaderSection = G->createSection("__header", MemProt::Read);
- auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
- // Init symbol is __ImageBase symbol.
- auto &ImageBaseSymbol = G->addDefinedSymbol(
- HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),
- jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
- addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);
- CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
- }
- void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
- private:
- struct HeaderSymbol {
- const char *Name;
- uint64_t Offset;
- };
- struct NTHeader {
- support::ulittle32_t PEMagic;
- object::coff_file_header FileHeader;
- struct PEHeader {
- object::pe32plus_header Header;
- object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];
- } OptionalHeader;
- };
- struct HeaderBlockContent {
- object::dos_header DOSHeader;
- COFFHeaderMaterializationUnit::NTHeader NTHeader;
- };
- static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
- jitlink::Section &HeaderSection) {
- HeaderBlockContent Hdr = {};
- // Set up magic
- Hdr.DOSHeader.Magic[0] = 'M';
- Hdr.DOSHeader.Magic[1] = 'Z';
- Hdr.DOSHeader.AddressOfNewExeHeader =
- offsetof(HeaderBlockContent, NTHeader);
- uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);
- Hdr.NTHeader.PEMagic = PEMagic;
- Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;
- switch (G.getTargetTriple().getArch()) {
- case Triple::x86_64:
- Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
- break;
- default:
- llvm_unreachable("Unrecognized architecture");
- }
- auto HeaderContent = G.allocateString(
- StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
- return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
- 0);
- }
- static void addImageBaseRelocationEdge(jitlink::Block &B,
- jitlink::Symbol &ImageBase) {
- auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +
- offsetof(NTHeader, OptionalHeader) +
- offsetof(object::pe32plus_header, ImageBase);
- B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
- }
- static MaterializationUnit::Interface
- createHeaderInterface(COFFPlatform &MOP,
- const SymbolStringPtr &HeaderStartSymbol) {
- SymbolFlagsMap HeaderSymbolFlags;
- HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
- return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
- HeaderStartSymbol);
- }
- COFFPlatform &CP;
- };
- } // end anonymous namespace
- namespace llvm {
- namespace orc {
- Expected<std::unique_ptr<COFFPlatform>>
- COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
- JITDylib &PlatformJD, const char *OrcRuntimePath,
- LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
- const char *VCRuntimePath,
- std::optional<SymbolAliasMap> RuntimeAliases) {
- auto &EPC = ES.getExecutorProcessControl();
- // If the target is not supported then bail out immediately.
- if (!supportedTarget(EPC.getTargetTriple()))
- return make_error<StringError>("Unsupported COFFPlatform triple: " +
- EPC.getTargetTriple().str(),
- inconvertibleErrorCode());
- // Create default aliases if the caller didn't supply any.
- if (!RuntimeAliases)
- RuntimeAliases = standardPlatformAliases(ES);
- // Define the aliases.
- if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
- return std::move(Err);
- auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
- // Add JIT-dispatch function support symbols.
- if (auto Err = HostFuncJD.define(absoluteSymbols(
- {{ES.intern("__orc_rt_jit_dispatch"),
- {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
- JITSymbolFlags::Exported}},
- {ES.intern("__orc_rt_jit_dispatch_ctx"),
- {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
- JITSymbolFlags::Exported}}})))
- return std::move(Err);
- PlatformJD.addToLinkOrder(HostFuncJD);
- // Create the instance.
- Error Err = Error::success();
- auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
- ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath,
- std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
- if (Err)
- return std::move(Err);
- return std::move(P);
- }
- Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
- auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
- if (!PerJDObj)
- return PerJDObj.takeError();
- if (!*PerJDObj)
- return make_error<StringError>("Could not find per jd object file",
- inconvertibleErrorCode());
- auto Buffer = (*PerJDObj)->getAsBinary();
- if (!Buffer)
- return Buffer.takeError();
- return (*Buffer)->getMemoryBufferRef();
- }
- static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
- ArrayRef<std::pair<const char *, const char *>> AL) {
- for (auto &KV : AL) {
- auto AliasName = ES.intern(KV.first);
- assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
- Aliases[std::move(AliasName)] = {ES.intern(KV.second),
- JITSymbolFlags::Exported};
- }
- }
- Error COFFPlatform::setupJITDylib(JITDylib &JD) {
- if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
- *this, COFFHeaderStartSymbol)))
- return Err;
- if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
- return Err;
- // Define the CXX aliases.
- SymbolAliasMap CXXAliases;
- addAliases(ES, CXXAliases, requiredCXXAliases());
- if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
- return Err;
- auto PerJDObj = getPerJDObjectFile();
- if (!PerJDObj)
- return PerJDObj.takeError();
- auto I = getObjectFileInterface(ES, *PerJDObj);
- if (!I)
- return I.takeError();
- if (auto Err = ObjLinkingLayer.add(
- JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
- return Err;
- if (!Bootstrapping) {
- auto ImportedLibs = StaticVCRuntime
- ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
- : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
- if (!ImportedLibs)
- return ImportedLibs.takeError();
- for (auto &Lib : *ImportedLibs)
- if (auto Err = LoadDynLibrary(JD, Lib))
- return Err;
- if (StaticVCRuntime)
- if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
- return Err;
- }
- JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
- return Error::success();
- }
- Error COFFPlatform::teardownJITDylib(JITDylib &JD) {
- std::lock_guard<std::mutex> Lock(PlatformMutex);
- auto I = JITDylibToHeaderAddr.find(&JD);
- if (I != JITDylibToHeaderAddr.end()) {
- assert(HeaderAddrToJITDylib.count(I->second) &&
- "HeaderAddrToJITDylib missing entry");
- HeaderAddrToJITDylib.erase(I->second);
- JITDylibToHeaderAddr.erase(I);
- }
- return Error::success();
- }
- Error COFFPlatform::notifyAdding(ResourceTracker &RT,
- const MaterializationUnit &MU) {
- auto &JD = RT.getJITDylib();
- const auto &InitSym = MU.getInitializerSymbol();
- if (!InitSym)
- return Error::success();
- RegisteredInitSymbols[&JD].add(InitSym,
- SymbolLookupFlags::WeaklyReferencedSymbol);
- LLVM_DEBUG({
- dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "
- << MU.getName() << "\n";
- });
- return Error::success();
- }
- Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
- llvm_unreachable("Not supported yet");
- }
- SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {
- SymbolAliasMap Aliases;
- addAliases(ES, Aliases, standardRuntimeUtilityAliases());
- return Aliases;
- }
- ArrayRef<std::pair<const char *, const char *>>
- COFFPlatform::requiredCXXAliases() {
- static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
- {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
- {"_onexit", "__orc_rt_coff_onexit_per_jd"},
- {"atexit", "__orc_rt_coff_atexit_per_jd"}};
- return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
- }
- ArrayRef<std::pair<const char *, const char *>>
- COFFPlatform::standardRuntimeUtilityAliases() {
- static const std::pair<const char *, const char *>
- StandardRuntimeUtilityAliases[] = {
- {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
- {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
- {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
- {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
- {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
- {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
- return ArrayRef<std::pair<const char *, const char *>>(
- StandardRuntimeUtilityAliases);
- }
- bool COFFPlatform::supportedTarget(const Triple &TT) {
- switch (TT.getArch()) {
- case Triple::x86_64:
- return true;
- default:
- return false;
- }
- }
- COFFPlatform::COFFPlatform(ExecutionSession &ES,
- ObjectLinkingLayer &ObjLinkingLayer,
- JITDylib &PlatformJD, const char *OrcRuntimePath,
- LoadDynamicLibrary LoadDynLibrary,
- bool StaticVCRuntime, const char *VCRuntimePath,
- Error &Err)
- : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
- LoadDynLibrary(std::move(LoadDynLibrary)),
- StaticVCRuntime(StaticVCRuntime),
- COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
- ErrorAsOutParameter _(&Err);
- // Create a generator for the ORC runtime archive.
- auto OrcRuntimeArchiveGenerator =
- StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
- if (!OrcRuntimeArchiveGenerator) {
- Err = OrcRuntimeArchiveGenerator.takeError();
- return;
- }
- auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
- if (!ArchiveBuffer) {
- Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError());
- return;
- }
- OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer);
- OrcRuntimeArchive =
- std::make_unique<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
- if (Err)
- return;
- Bootstrapping.store(true);
- ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
- // Load vc runtime
- auto VCRT =
- COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
- if (!VCRT) {
- Err = VCRT.takeError();
- return;
- }
- VCRuntimeBootstrap = std::move(*VCRT);
- for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries())
- DylibsToPreload.insert(Lib);
- auto ImportedLibs =
- StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
- : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
- if (!ImportedLibs) {
- Err = ImportedLibs.takeError();
- return;
- }
- for (auto &Lib : *ImportedLibs)
- DylibsToPreload.insert(Lib);
- PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator));
- // PlatformJD hasn't been set up by the platform yet (since we're creating
- // the platform now), so set it up.
- if (auto E2 = setupJITDylib(PlatformJD)) {
- Err = std::move(E2);
- return;
- }
- for (auto& Lib : DylibsToPreload)
- if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) {
- Err = std::move(E2);
- return;
- }
- if (StaticVCRuntime)
- if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
- Err = std::move(E2);
- return;
- }
- // Associate wrapper function tags with JIT-side function implementations.
- if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
- Err = std::move(E2);
- return;
- }
- // Lookup addresses of runtime functions callable by the platform,
- // call the platform bootstrap function to initialize the platform-state
- // object in the executor.
- if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
- Err = std::move(E2);
- return;
- }
- Bootstrapping.store(false);
- JDBootstrapStates.clear();
- }
- Expected<COFFPlatform::JITDylibDepMap>
- COFFPlatform::buildJDDepMap(JITDylib &JD) {
- return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
- JITDylibDepMap JDDepMap;
- SmallVector<JITDylib *, 16> Worklist({&JD});
- while (!Worklist.empty()) {
- auto CurJD = Worklist.back();
- Worklist.pop_back();
- auto &DM = JDDepMap[CurJD];
- CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
- DM.reserve(O.size());
- for (auto &KV : O) {
- if (KV.first == CurJD)
- continue;
- {
- // Bare jitdylibs not known to the platform
- std::lock_guard<std::mutex> Lock(PlatformMutex);
- if (!JITDylibToHeaderAddr.count(KV.first)) {
- LLVM_DEBUG({
- dbgs() << "JITDylib unregistered to COFFPlatform detected in "
- "LinkOrder: "
- << CurJD->getName() << "\n";
- });
- continue;
- }
- }
- DM.push_back(KV.first);
- // Push unvisited entry.
- if (!JDDepMap.count(KV.first)) {
- Worklist.push_back(KV.first);
- JDDepMap[KV.first] = {};
- }
- }
- });
- }
- return std::move(JDDepMap);
- });
- }
- void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
- JITDylibSP JD,
- JITDylibDepMap &JDDepMap) {
- SmallVector<JITDylib *, 16> Worklist({JD.get()});
- DenseSet<JITDylib *> Visited({JD.get()});
- DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
- ES.runSessionLocked([&]() {
- while (!Worklist.empty()) {
- auto CurJD = Worklist.back();
- Worklist.pop_back();
- auto RISItr = RegisteredInitSymbols.find(CurJD);
- if (RISItr != RegisteredInitSymbols.end()) {
- NewInitSymbols[CurJD] = std::move(RISItr->second);
- RegisteredInitSymbols.erase(RISItr);
- }
- for (auto *DepJD : JDDepMap[CurJD])
- if (!Visited.count(DepJD)) {
- Worklist.push_back(DepJD);
- Visited.insert(DepJD);
- }
- }
- });
- // If there are no further init symbols to look up then send the link order
- // (as a list of header addresses) to the caller.
- if (NewInitSymbols.empty()) {
- // Build the dep info map to return.
- COFFJITDylibDepInfoMap DIM;
- DIM.reserve(JDDepMap.size());
- for (auto &KV : JDDepMap) {
- std::lock_guard<std::mutex> Lock(PlatformMutex);
- COFFJITDylibDepInfo DepInfo;
- DepInfo.reserve(KV.second.size());
- for (auto &Dep : KV.second) {
- DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
- }
- auto H = JITDylibToHeaderAddr[KV.first];
- DIM.push_back(std::make_pair(H, std::move(DepInfo)));
- }
- SendResult(DIM);
- return;
- }
- // Otherwise issue a lookup and re-run this phase when it completes.
- lookupInitSymbolsAsync(
- [this, SendResult = std::move(SendResult), &JD,
- JDDepMap = std::move(JDDepMap)](Error Err) mutable {
- if (Err)
- SendResult(std::move(Err));
- else
- pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
- },
- ES, std::move(NewInitSymbols));
- }
- void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
- ExecutorAddr JDHeaderAddr) {
- JITDylibSP JD;
- {
- std::lock_guard<std::mutex> Lock(PlatformMutex);
- auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
- if (I != HeaderAddrToJITDylib.end())
- JD = I->second;
- }
- LLVM_DEBUG({
- dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
- if (JD)
- dbgs() << "pushing initializers for " << JD->getName() << "\n";
- else
- dbgs() << "No JITDylib for header address.\n";
- });
- if (!JD) {
- SendResult(
- make_error<StringError>("No JITDylib with header addr " +
- formatv("{0:x}", JDHeaderAddr.getValue()),
- inconvertibleErrorCode()));
- return;
- }
- auto JDDepMap = buildJDDepMap(*JD);
- if (!JDDepMap) {
- SendResult(JDDepMap.takeError());
- return;
- }
- pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
- }
- void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
- ExecutorAddr Handle, StringRef SymbolName) {
- LLVM_DEBUG({
- dbgs() << "COFFPlatform::rt_lookupSymbol(\""
- << formatv("{0:x}", Handle.getValue()) << "\")\n";
- });
- JITDylib *JD = nullptr;
- {
- std::lock_guard<std::mutex> Lock(PlatformMutex);
- auto I = HeaderAddrToJITDylib.find(Handle);
- if (I != HeaderAddrToJITDylib.end())
- JD = I->second;
- }
- if (!JD) {
- LLVM_DEBUG({
- dbgs() << " No JITDylib for handle "
- << formatv("{0:x}", Handle.getValue()) << "\n";
- });
- SendResult(make_error<StringError>("No JITDylib associated with handle " +
- formatv("{0:x}", Handle.getValue()),
- inconvertibleErrorCode()));
- return;
- }
- // Use functor class to work around XL build compiler issue on AIX.
- class RtLookupNotifyComplete {
- public:
- RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
- : SendResult(std::move(SendResult)) {}
- void operator()(Expected<SymbolMap> Result) {
- if (Result) {
- assert(Result->size() == 1 && "Unexpected result map count");
- SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
- } else {
- SendResult(Result.takeError());
- }
- }
- private:
- SendSymbolAddressFn SendResult;
- };
- ES.lookup(
- LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
- SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
- RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
- }
- Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
- ExecutionSession::JITDispatchHandlerAssociationMap WFs;
- using LookupSymbolSPSSig =
- SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
- WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
- ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
- &COFFPlatform::rt_lookupSymbol);
- using PushInitializersSPSSig =
- SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);
- WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
- ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
- this, &COFFPlatform::rt_pushInitializers);
- return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
- }
- Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
- llvm::sort(BState.Initializers);
- if (auto Err =
- runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
- return Err;
- if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
- return Err;
- if (auto Err =
- runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
- return Err;
- return Error::success();
- }
- Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
- StringRef Start,
- StringRef End) {
- for (auto &Initializer : BState.Initializers)
- if (Initializer.first >= Start && Initializer.first <= End &&
- Initializer.second) {
- auto Res =
- ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
- if (!Res)
- return Res.takeError();
- }
- return Error::success();
- }
- Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
- // Lookup of runtime symbols causes the collection of initializers if
- // it's static linking setting.
- if (auto Err = lookupAndRecordAddrs(
- ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
- {
- {ES.intern("__orc_rt_coff_platform_bootstrap"),
- &orc_rt_coff_platform_bootstrap},
- {ES.intern("__orc_rt_coff_platform_shutdown"),
- &orc_rt_coff_platform_shutdown},
- {ES.intern("__orc_rt_coff_register_jitdylib"),
- &orc_rt_coff_register_jitdylib},
- {ES.intern("__orc_rt_coff_deregister_jitdylib"),
- &orc_rt_coff_deregister_jitdylib},
- {ES.intern("__orc_rt_coff_register_object_sections"),
- &orc_rt_coff_register_object_sections},
- {ES.intern("__orc_rt_coff_deregister_object_sections"),
- &orc_rt_coff_deregister_object_sections},
- }))
- return Err;
- // Call bootstrap functions
- if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
- return Err;
- // Do the pending jitdylib registration actions that we couldn't do
- // because orc runtime was not linked fully.
- for (auto KV : JDBootstrapStates) {
- auto &JDBState = KV.second;
- if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
- orc_rt_coff_register_jitdylib, JDBState.JDName,
- JDBState.HeaderAddr))
- return Err;
- for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
- if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
- SPSCOFFObjectSectionsMap, bool)>(
- orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
- ObjSectionMap, false))
- return Err;
- }
- // Run static initializers collected in bootstrap stage.
- for (auto KV : JDBootstrapStates) {
- auto &JDBState = KV.second;
- if (auto Err = runBootstrapInitializers(JDBState))
- return Err;
- }
- return Error::success();
- }
- Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
- StringRef SymbolName) {
- ExecutorAddr jit_function;
- auto AfterCLookupErr = lookupAndRecordAddrs(
- ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
- {{ES.intern(SymbolName), &jit_function}});
- if (!AfterCLookupErr) {
- auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
- if (!Res)
- return Res.takeError();
- return Error::success();
- }
- if (!AfterCLookupErr.isA<SymbolsNotFound>())
- return AfterCLookupErr;
- consumeError(std::move(AfterCLookupErr));
- return Error::success();
- }
- void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
- MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
- jitlink::PassConfiguration &Config) {
- bool IsBootstrapping = CP.Bootstrapping.load();
- if (auto InitSymbol = MR.getInitializerSymbol()) {
- if (InitSymbol == CP.COFFHeaderStartSymbol) {
- Config.PostAllocationPasses.push_back(
- [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
- return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
- });
- return;
- }
- Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
- return preserveInitializerSections(G, MR);
- });
- }
- if (!IsBootstrapping)
- Config.PostFixupPasses.push_back(
- [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
- return registerObjectPlatformSections(G, JD);
- });
- else
- Config.PostFixupPasses.push_back(
- [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
- return registerObjectPlatformSectionsInBootstrap(G, JD);
- });
- }
- ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
- COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(
- MaterializationResponsibility &MR) {
- std::lock_guard<std::mutex> Lock(PluginMutex);
- auto I = InitSymbolDeps.find(&MR);
- if (I != InitSymbolDeps.end()) {
- SyntheticSymbolDependenciesMap Result;
- Result[MR.getInitializerSymbol()] = std::move(I->second);
- InitSymbolDeps.erase(&MR);
- return Result;
- }
- return SyntheticSymbolDependenciesMap();
- }
- Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
- jitlink::LinkGraph &G, MaterializationResponsibility &MR,
- bool IsBootstraping) {
- auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
- return Sym->getName() == *CP.COFFHeaderStartSymbol;
- });
- assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");
- auto &JD = MR.getTargetJITDylib();
- std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
- auto HeaderAddr = (*I)->getAddress();
- CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
- CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
- if (!IsBootstraping) {
- G.allocActions().push_back(
- {cantFail(WrapperFunctionCall::Create<
- SPSArgList<SPSString, SPSExecutorAddr>>(
- CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
- cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
- CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
- } else {
- G.allocActions().push_back(
- {{},
- cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
- CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
- JDBootstrapState BState;
- BState.JD = &JD;
- BState.JDName = JD.getName();
- BState.HeaderAddr = HeaderAddr;
- CP.JDBootstrapStates.emplace(&JD, BState);
- }
- return Error::success();
- }
- Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
- jitlink::LinkGraph &G, JITDylib &JD) {
- COFFObjectSectionsMap ObjSecs;
- auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
- assert(HeaderAddr && "Must be registered jitdylib");
- for (auto &S : G.sections()) {
- jitlink::SectionRange Range(S);
- if (Range.getSize())
- ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
- }
- G.allocActions().push_back(
- {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
- CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
- cantFail(
- WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
- CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
- ObjSecs))});
- return Error::success();
- }
- Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
- jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
- JITLinkSymbolSet InitSectionSymbols;
- for (auto &Sec : G.sections())
- if (COFFPlatform::isInitializerSection(Sec.getName()))
- for (auto *B : Sec.blocks())
- if (!B->edges_empty())
- InitSectionSymbols.insert(
- &G.addAnonymousSymbol(*B, 0, 0, false, true));
- std::lock_guard<std::mutex> Lock(PluginMutex);
- InitSymbolDeps[&MR] = InitSectionSymbols;
- return Error::success();
- }
- Error COFFPlatform::COFFPlatformPlugin::
- registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
- JITDylib &JD) {
- std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
- auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
- COFFObjectSectionsMap ObjSecs;
- for (auto &S : G.sections()) {
- jitlink::SectionRange Range(S);
- if (Range.getSize())
- ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
- }
- G.allocActions().push_back(
- {{},
- cantFail(
- WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
- CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
- ObjSecs))});
- auto &BState = CP.JDBootstrapStates[&JD];
- BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));
- // Collect static initializers
- for (auto &S : G.sections())
- if (COFFPlatform::isInitializerSection(S.getName()))
- for (auto *B : S.blocks()) {
- if (B->edges_empty())
- continue;
- for (auto &E : B->edges())
- BState.Initializers.push_back(std::make_pair(
- S.getName().str(),
- ExecutorAddr(E.getTarget().getAddress() + E.getAddend())));
- }
- return Error::success();
- }
- } // End namespace orc.
- } // End namespace llvm.
|