Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
35266 views
//===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//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/ObjectLinkingLayer.h"9#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"10#include "llvm/ExecutionEngine/JITLink/aarch32.h"11#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"12#include "llvm/ExecutionEngine/Orc/DebugUtils.h"13#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"14#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"15#include "llvm/Support/MemoryBuffer.h"16#include <string>17#include <vector>1819#define DEBUG_TYPE "orc"2021using namespace llvm;22using namespace llvm::jitlink;23using namespace llvm::orc;2425namespace {2627bool hasInitializerSection(jitlink::LinkGraph &G) {28bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();29bool IsElf = G.getTargetTriple().isOSBinFormatELF();30if (!IsMachO && !IsElf)31return false;3233for (auto &Sec : G.sections()) {34if (IsMachO && isMachOInitializerSection(Sec.getName()))35return true;36if (IsElf && isELFInitializerSection(Sec.getName()))37return true;38}3940return false;41}4243ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {44switch (TT.getArch()) {45case Triple::arm:46case Triple::armeb:47case Triple::thumb:48case Triple::thumbeb:49if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) {50// Set LSB to indicate thumb target51assert(Sym.isCallable() && "Only callable symbols can have thumb flag");52assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");53return Sym.getAddress() + 0x01;54}55return Sym.getAddress();56default:57return Sym.getAddress();58}59}6061JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) {62JITSymbolFlags Flags;6364if (Sym.getLinkage() == Linkage::Weak)65Flags |= JITSymbolFlags::Weak;6667if (Sym.getScope() == Scope::Default)68Flags |= JITSymbolFlags::Exported;6970if (Sym.isCallable())71Flags |= JITSymbolFlags::Callable;7273return Flags;74}7576class LinkGraphMaterializationUnit : public MaterializationUnit {77public:78static std::unique_ptr<LinkGraphMaterializationUnit>79Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {80auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);81return std::unique_ptr<LinkGraphMaterializationUnit>(82new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),83std::move(LGI)));84}8586StringRef getName() const override { return G->getName(); }87void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {88ObjLinkingLayer.emit(std::move(MR), std::move(G));89}9091private:92static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) {9394Interface LGI;9596auto AddSymbol = [&](Symbol *Sym) {97// Skip local symbols.98if (Sym->getScope() == Scope::Local)99return;100assert(Sym->hasName() && "Anonymous non-local symbol?");101102LGI.SymbolFlags[ES.intern(Sym->getName())] =103getJITSymbolFlagsForSymbol(*Sym);104};105106for (auto *Sym : G.defined_symbols())107AddSymbol(Sym);108for (auto *Sym : G.absolute_symbols())109AddSymbol(Sym);110111if (hasInitializerSection(G))112LGI.InitSymbol = makeInitSymbol(ES, G);113114return LGI;115}116117static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {118std::string InitSymString;119raw_string_ostream(InitSymString)120<< "$." << G.getName() << ".__inits" << Counter++;121return ES.intern(InitSymString);122}123124LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,125std::unique_ptr<LinkGraph> G, Interface LGI)126: MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),127G(std::move(G)) {}128129void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {130for (auto *Sym : G->defined_symbols())131if (Sym->getName() == *Name) {132assert(Sym->getLinkage() == Linkage::Weak &&133"Discarding non-weak definition");134G->makeExternal(*Sym);135break;136}137}138139ObjectLinkingLayer &ObjLinkingLayer;140std::unique_ptr<LinkGraph> G;141static std::atomic<uint64_t> Counter;142};143144std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};145146} // end anonymous namespace147148namespace llvm {149namespace orc {150151class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {152public:153ObjectLinkingLayerJITLinkContext(154ObjectLinkingLayer &Layer,155std::unique_ptr<MaterializationResponsibility> MR,156std::unique_ptr<MemoryBuffer> ObjBuffer)157: JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),158MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {159std::lock_guard<std::mutex> Lock(Layer.LayerMutex);160Plugins = Layer.Plugins;161}162163~ObjectLinkingLayerJITLinkContext() {164// If there is an object buffer return function then use it to165// return ownership of the buffer.166if (Layer.ReturnObjectBuffer && ObjBuffer)167Layer.ReturnObjectBuffer(std::move(ObjBuffer));168}169170JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }171172void notifyMaterializing(LinkGraph &G) {173for (auto &P : Plugins)174P->notifyMaterializing(*MR, G, *this,175ObjBuffer ? ObjBuffer->getMemBufferRef()176: MemoryBufferRef());177}178179void notifyFailed(Error Err) override {180for (auto &P : Plugins)181Err = joinErrors(std::move(Err), P->notifyFailed(*MR));182Layer.getExecutionSession().reportError(std::move(Err));183MR->failMaterialization();184}185186void lookup(const LookupMap &Symbols,187std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {188189JITDylibSearchOrder LinkOrder;190MR->getTargetJITDylib().withLinkOrderDo(191[&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });192193auto &ES = Layer.getExecutionSession();194195SymbolLookupSet LookupSet;196for (auto &KV : Symbols) {197orc::SymbolLookupFlags LookupFlags;198switch (KV.second) {199case jitlink::SymbolLookupFlags::RequiredSymbol:200LookupFlags = orc::SymbolLookupFlags::RequiredSymbol;201break;202case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol:203LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol;204break;205}206LookupSet.add(ES.intern(KV.first), LookupFlags);207}208209// OnResolve -- De-intern the symbols and pass the result to the linker.210auto OnResolve = [LookupContinuation =211std::move(LC)](Expected<SymbolMap> Result) mutable {212if (!Result)213LookupContinuation->run(Result.takeError());214else {215AsyncLookupResult LR;216for (auto &KV : *Result)217LR[*KV.first] = KV.second;218LookupContinuation->run(std::move(LR));219}220};221222ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),223SymbolState::Resolved, std::move(OnResolve),224[this](const SymbolDependenceMap &Deps) {225// Translate LookupDeps map to SymbolSourceJD.226for (auto &[DepJD, Deps] : Deps)227for (auto &DepSym : Deps)228SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD;229});230}231232Error notifyResolved(LinkGraph &G) override {233auto &ES = Layer.getExecutionSession();234235SymbolFlagsMap ExtraSymbolsToClaim;236bool AutoClaim = Layer.AutoClaimObjectSymbols;237238SymbolMap InternedResult;239for (auto *Sym : G.defined_symbols())240if (Sym->hasName() && Sym->getScope() != Scope::Local) {241auto InternedName = ES.intern(Sym->getName());242auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());243auto Flags = getJITSymbolFlagsForSymbol(*Sym);244InternedResult[InternedName] = {Ptr, Flags};245if (AutoClaim && !MR->getSymbols().count(InternedName)) {246assert(!ExtraSymbolsToClaim.count(InternedName) &&247"Duplicate symbol to claim?");248ExtraSymbolsToClaim[InternedName] = Flags;249}250}251252for (auto *Sym : G.absolute_symbols())253if (Sym->hasName() && Sym->getScope() != Scope::Local) {254auto InternedName = ES.intern(Sym->getName());255auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());256auto Flags = getJITSymbolFlagsForSymbol(*Sym);257InternedResult[InternedName] = {Ptr, Flags};258if (AutoClaim && !MR->getSymbols().count(InternedName)) {259assert(!ExtraSymbolsToClaim.count(InternedName) &&260"Duplicate symbol to claim?");261ExtraSymbolsToClaim[InternedName] = Flags;262}263}264265if (!ExtraSymbolsToClaim.empty())266if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))267return Err;268269{270271// Check that InternedResult matches up with MR->getSymbols(), overriding272// flags if requested.273// This guards against faulty transformations / compilers / object caches.274275// First check that there aren't any missing symbols.276size_t NumMaterializationSideEffectsOnlySymbols = 0;277SymbolNameVector ExtraSymbols;278SymbolNameVector MissingSymbols;279for (auto &KV : MR->getSymbols()) {280281auto I = InternedResult.find(KV.first);282283// If this is a materialization-side-effects only symbol then bump284// the counter and make sure it's *not* defined, otherwise make285// sure that it is defined.286if (KV.second.hasMaterializationSideEffectsOnly()) {287++NumMaterializationSideEffectsOnlySymbols;288if (I != InternedResult.end())289ExtraSymbols.push_back(KV.first);290continue;291} else if (I == InternedResult.end())292MissingSymbols.push_back(KV.first);293else if (Layer.OverrideObjectFlags)294I->second.setFlags(KV.second);295}296297// If there were missing symbols then report the error.298if (!MissingSymbols.empty())299return make_error<MissingSymbolDefinitions>(300Layer.getExecutionSession().getSymbolStringPool(), G.getName(),301std::move(MissingSymbols));302303// If there are more definitions than expected, add them to the304// ExtraSymbols vector.305if (InternedResult.size() >306MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {307for (auto &KV : InternedResult)308if (!MR->getSymbols().count(KV.first))309ExtraSymbols.push_back(KV.first);310}311312// If there were extra definitions then report the error.313if (!ExtraSymbols.empty())314return make_error<UnexpectedSymbolDefinitions>(315Layer.getExecutionSession().getSymbolStringPool(), G.getName(),316std::move(ExtraSymbols));317}318319if (auto Err = MR->notifyResolved(InternedResult))320return Err;321322notifyLoaded();323return Error::success();324}325326void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override {327if (auto Err = notifyEmitted(std::move(A))) {328Layer.getExecutionSession().reportError(std::move(Err));329MR->failMaterialization();330return;331}332if (auto Err = MR->notifyEmitted(SymbolDepGroups)) {333Layer.getExecutionSession().reportError(std::move(Err));334MR->failMaterialization();335}336}337338LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {339return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };340}341342Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override {343// Add passes to mark duplicate defs as should-discard, and to walk the344// link graph to build the symbol dependence graph.345Config.PrePrunePasses.push_back([this](LinkGraph &G) {346return claimOrExternalizeWeakAndCommonSymbols(G);347});348349for (auto &P : Plugins)350P->modifyPassConfig(*MR, LG, Config);351352Config.PreFixupPasses.push_back(353[this](LinkGraph &G) { return registerDependencies(G); });354355return Error::success();356}357358void notifyLoaded() {359for (auto &P : Plugins)360P->notifyLoaded(*MR);361}362363Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) {364Error Err = Error::success();365for (auto &P : Plugins)366Err = joinErrors(std::move(Err), P->notifyEmitted(*MR));367368if (Err) {369if (FA)370Err =371joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA)));372return Err;373}374375if (FA)376return Layer.recordFinalizedAlloc(*MR, std::move(FA));377378return Error::success();379}380381private:382// Symbol name dependencies:383// Internal: Defined in this graph.384// External: Defined externally.385struct BlockSymbolDependencies {386SymbolNameSet Internal, External;387};388389// Lazily populated map of blocks to BlockSymbolDependencies values.390class BlockDependenciesMap {391public:392BlockDependenciesMap(ExecutionSession &ES,393DenseMap<const Block *, DenseSet<Block *>> BlockDeps)394: ES(ES), BlockDeps(std::move(BlockDeps)) {}395396const BlockSymbolDependencies &operator[](const Block &B) {397// Check the cache first.398auto I = BlockTransitiveDepsCache.find(&B);399if (I != BlockTransitiveDepsCache.end())400return I->second;401402// No value. Populate the cache.403BlockSymbolDependencies BTDCacheVal;404auto BDI = BlockDeps.find(&B);405assert(BDI != BlockDeps.end() && "No block dependencies");406407for (auto *BDep : BDI->second) {408auto &BID = getBlockImmediateDeps(*BDep);409for (auto &ExternalDep : BID.External)410BTDCacheVal.External.insert(ExternalDep);411for (auto &InternalDep : BID.Internal)412BTDCacheVal.Internal.insert(InternalDep);413}414415return BlockTransitiveDepsCache416.insert(std::make_pair(&B, std::move(BTDCacheVal)))417.first->second;418}419420SymbolStringPtr &getInternedName(Symbol &Sym) {421auto I = NameCache.find(&Sym);422if (I != NameCache.end())423return I->second;424425return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))426.first->second;427}428429private:430BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {431// Check the cache first.432auto I = BlockImmediateDepsCache.find(&B);433if (I != BlockImmediateDepsCache.end())434return I->second;435436BlockSymbolDependencies BIDCacheVal;437for (auto &E : B.edges()) {438auto &Tgt = E.getTarget();439if (Tgt.getScope() != Scope::Local) {440if (Tgt.isExternal()) {441if (Tgt.getAddress() || !Tgt.isWeaklyReferenced())442BIDCacheVal.External.insert(getInternedName(Tgt));443} else444BIDCacheVal.Internal.insert(getInternedName(Tgt));445}446}447448return BlockImmediateDepsCache449.insert(std::make_pair(&B, std::move(BIDCacheVal)))450.first->second;451}452453ExecutionSession &ES;454DenseMap<const Block *, DenseSet<Block *>> BlockDeps;455DenseMap<const Symbol *, SymbolStringPtr> NameCache;456DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache;457DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache;458};459460Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {461auto &ES = Layer.getExecutionSession();462463SymbolFlagsMap NewSymbolsToClaim;464std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;465466auto ProcessSymbol = [&](Symbol *Sym) {467if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&468Sym->getScope() != Scope::Local) {469auto Name = ES.intern(Sym->getName());470if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {471NewSymbolsToClaim[Name] =472getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak;473NameToSym.push_back(std::make_pair(std::move(Name), Sym));474}475}476};477478for (auto *Sym : G.defined_symbols())479ProcessSymbol(Sym);480for (auto *Sym : G.absolute_symbols())481ProcessSymbol(Sym);482483// Attempt to claim all weak defs that we're not already responsible for.484// This may fail if the resource tracker has become defunct, but should485// always succeed otherwise.486if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))487return Err;488489// Walk the list of symbols that we just tried to claim. Symbols that we're490// responsible for are marked live. Symbols that we're not responsible for491// are turned into external references.492for (auto &KV : NameToSym) {493if (MR->getSymbols().count(KV.first))494KV.second->setLive(true);495else496G.makeExternal(*KV.second);497}498499return Error::success();500}501502Error markResponsibilitySymbolsLive(LinkGraph &G) const {503auto &ES = Layer.getExecutionSession();504for (auto *Sym : G.defined_symbols())505if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))506Sym->setLive(true);507return Error::success();508}509510Error registerDependencies(LinkGraph &G) {511auto &TargetJD = MR->getTargetJITDylib();512auto &ES = TargetJD.getExecutionSession();513auto BlockDeps = computeBlockNonLocalDeps(G);514515DenseSet<Block *> BlockDepsProcessed;516DenseMap<Block *, SymbolDependenceGroup> DepGroupForBlock;517518// Compute dependencies for symbols defined in the JITLink graph.519for (auto *Sym : G.defined_symbols()) {520521// Skip local symbols.522if (Sym->getScope() == Scope::Local)523continue;524assert(Sym->hasName() &&525"Defined non-local jitlink::Symbol should have a name");526527auto &BDeps = BlockDeps[Sym->getBlock()];528529// Skip symbols in blocks that don't depend on anything.530if (BDeps.Internal.empty() && BDeps.External.empty())531continue;532533SymbolDependenceGroup &SDG = DepGroupForBlock[&Sym->getBlock()];534SDG.Symbols.insert(ES.intern(Sym->getName()));535536if (!BlockDepsProcessed.count(&Sym->getBlock())) {537BlockDepsProcessed.insert(&Sym->getBlock());538539if (!BDeps.Internal.empty())540SDG.Dependencies[&TargetJD] = BDeps.Internal;541for (auto &Dep : BDeps.External) {542auto DepSrcItr = SymbolSourceJDs.find(NonOwningSymbolStringPtr(Dep));543if (DepSrcItr != SymbolSourceJDs.end())544SDG.Dependencies[DepSrcItr->second].insert(Dep);545}546}547}548549SymbolDependenceGroup SynthSDG;550551for (auto &P : Plugins) {552auto SynthDeps = P->getSyntheticSymbolDependencies(*MR);553if (SynthDeps.empty())554continue;555556DenseSet<Block *> BlockVisited;557for (auto &[Name, DepSyms] : SynthDeps) {558SynthSDG.Symbols.insert(Name);559for (auto *Sym : DepSyms) {560if (Sym->getScope() == Scope::Local) {561auto &BDeps = BlockDeps[Sym->getBlock()];562for (auto &S : BDeps.Internal)563SynthSDG.Dependencies[&TargetJD].insert(S);564for (auto &S : BDeps.External) {565auto DepSrcItr =566SymbolSourceJDs.find(NonOwningSymbolStringPtr(S));567if (DepSrcItr != SymbolSourceJDs.end())568SynthSDG.Dependencies[DepSrcItr->second].insert(S);569}570} else {571auto SymName = ES.intern(Sym->getName());572if (Sym->isExternal()) {573assert(SymbolSourceJDs.count(NonOwningSymbolStringPtr(SymName)) &&574"External symbol source entry missing");575SynthSDG576.Dependencies[SymbolSourceJDs[NonOwningSymbolStringPtr(577SymName)]]578.insert(SymName);579} else580SynthSDG.Dependencies[&TargetJD].insert(SymName);581}582}583}584}585586// Transfer SDGs to SymbolDepGroups.587DepGroupForBlock.reserve(DepGroupForBlock.size() + 1);588for (auto &[B, SDG] : DepGroupForBlock) {589assert(!SDG.Symbols.empty() && "SymbolDependenceGroup covers no symbols");590if (!SDG.Dependencies.empty())591SymbolDepGroups.push_back(std::move(SDG));592}593if (!SynthSDG.Symbols.empty() && !SynthSDG.Dependencies.empty())594SymbolDepGroups.push_back(std::move(SynthSDG));595596return Error::success();597}598599BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) {600// First calculate the reachable-via-non-local-symbol blocks for each block.601struct BlockInfo {602DenseSet<Block *> Dependencies;603DenseSet<Block *> Dependants;604bool DependenciesChanged = true;605};606DenseMap<Block *, BlockInfo> BlockInfos;607SmallVector<Block *> WorkList;608609// Pre-allocate map entries. This prevents any iterator/reference610// invalidation in the next loop.611for (auto *B : G.blocks())612(void)BlockInfos[B];613614// Build initial worklist, record block dependencies/dependants and615// non-local symbol dependencies.616for (auto *B : G.blocks()) {617auto &BI = BlockInfos[B];618for (auto &E : B->edges()) {619if (E.getTarget().getScope() == Scope::Local &&620!E.getTarget().isAbsolute()) {621auto &TgtB = E.getTarget().getBlock();622if (&TgtB != B) {623BI.Dependencies.insert(&TgtB);624BlockInfos[&TgtB].Dependants.insert(B);625}626}627}628}629630// Add blocks with both dependants and dependencies to the worklist to631// propagate dependencies to dependants.632for (auto &[B, BI] : BlockInfos) {633if (!BI.Dependants.empty() && !BI.Dependencies.empty())634WorkList.push_back(B);635}636637// Propagate block-level dependencies through the block-dependence graph.638while (!WorkList.empty()) {639auto *B = WorkList.pop_back_val();640641auto &BI = BlockInfos[B];642assert(BI.DependenciesChanged &&643"Block in worklist has unchanged dependencies");644BI.DependenciesChanged = false;645for (auto *Dependant : BI.Dependants) {646auto &DependantBI = BlockInfos[Dependant];647for (auto *Dependency : BI.Dependencies) {648if (Dependant != Dependency &&649DependantBI.Dependencies.insert(Dependency).second)650if (!DependantBI.DependenciesChanged) {651DependantBI.DependenciesChanged = true;652WorkList.push_back(Dependant);653}654}655}656}657658DenseMap<const Block *, DenseSet<Block *>> BlockDeps;659for (auto &KV : BlockInfos)660BlockDeps[KV.first] = std::move(KV.second.Dependencies);661662return BlockDependenciesMap(Layer.getExecutionSession(),663std::move(BlockDeps));664}665666ObjectLinkingLayer &Layer;667std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins;668std::unique_ptr<MaterializationResponsibility> MR;669std::unique_ptr<MemoryBuffer> ObjBuffer;670DenseMap<Block *, SymbolNameSet> ExternalBlockDeps;671DenseMap<Block *, SymbolNameSet> InternalBlockDeps;672DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;673std::vector<SymbolDependenceGroup> SymbolDepGroups;674};675676ObjectLinkingLayer::Plugin::~Plugin() = default;677678char ObjectLinkingLayer::ID;679680using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;681682ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)683: BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {684ES.registerResourceManager(*this);685}686687ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,688JITLinkMemoryManager &MemMgr)689: BaseT(ES), MemMgr(MemMgr) {690ES.registerResourceManager(*this);691}692693ObjectLinkingLayer::ObjectLinkingLayer(694ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)695: BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {696ES.registerResourceManager(*this);697}698699ObjectLinkingLayer::~ObjectLinkingLayer() {700assert(Allocs.empty() && "Layer destroyed with resources still attached");701getExecutionSession().deregisterResourceManager(*this);702}703704Error ObjectLinkingLayer::add(ResourceTrackerSP RT,705std::unique_ptr<LinkGraph> G) {706auto &JD = RT->getJITDylib();707return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),708std::move(RT));709}710711void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,712std::unique_ptr<MemoryBuffer> O) {713assert(O && "Object must not be null");714MemoryBufferRef ObjBuffer = O->getMemBufferRef();715716auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(717*this, std::move(R), std::move(O));718if (auto G = createLinkGraphFromObject(ObjBuffer)) {719Ctx->notifyMaterializing(**G);720link(std::move(*G), std::move(Ctx));721} else {722Ctx->notifyFailed(G.takeError());723}724}725726void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,727std::unique_ptr<LinkGraph> G) {728auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(729*this, std::move(R), nullptr);730Ctx->notifyMaterializing(*G);731link(std::move(G), std::move(Ctx));732}733734Error ObjectLinkingLayer::recordFinalizedAlloc(735MaterializationResponsibility &MR, FinalizedAlloc FA) {736auto Err = MR.withResourceKeyDo(737[&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });738739if (Err)740Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));741742return Err;743}744745Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) {746747{748Error Err = Error::success();749for (auto &P : Plugins)750Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));751if (Err)752return Err;753}754755std::vector<FinalizedAlloc> AllocsToRemove;756getExecutionSession().runSessionLocked([&] {757auto I = Allocs.find(K);758if (I != Allocs.end()) {759std::swap(AllocsToRemove, I->second);760Allocs.erase(I);761}762});763764if (AllocsToRemove.empty())765return Error::success();766767return MemMgr.deallocate(std::move(AllocsToRemove));768}769770void ObjectLinkingLayer::handleTransferResources(JITDylib &JD,771ResourceKey DstKey,772ResourceKey SrcKey) {773auto I = Allocs.find(SrcKey);774if (I != Allocs.end()) {775auto &SrcAllocs = I->second;776auto &DstAllocs = Allocs[DstKey];777DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());778for (auto &Alloc : SrcAllocs)779DstAllocs.push_back(std::move(Alloc));780781// Erase SrcKey entry using value rather than iterator I: I may have been782// invalidated when we looked up DstKey.783Allocs.erase(SrcKey);784}785786for (auto &P : Plugins)787P->notifyTransferringResources(JD, DstKey, SrcKey);788}789790EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(791ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)792: ES(ES), Registrar(std::move(Registrar)) {}793794void EHFrameRegistrationPlugin::modifyPassConfig(795MaterializationResponsibility &MR, LinkGraph &G,796PassConfiguration &PassConfig) {797798PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(799G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {800if (Addr) {801std::lock_guard<std::mutex> Lock(EHFramePluginMutex);802assert(!InProcessLinks.count(&MR) &&803"Link for MR already being tracked?");804InProcessLinks[&MR] = {Addr, Size};805}806}));807}808809Error EHFrameRegistrationPlugin::notifyEmitted(810MaterializationResponsibility &MR) {811812ExecutorAddrRange EmittedRange;813{814std::lock_guard<std::mutex> Lock(EHFramePluginMutex);815816auto EHFrameRangeItr = InProcessLinks.find(&MR);817if (EHFrameRangeItr == InProcessLinks.end())818return Error::success();819820EmittedRange = EHFrameRangeItr->second;821assert(EmittedRange.Start && "eh-frame addr to register can not be null");822InProcessLinks.erase(EHFrameRangeItr);823}824825if (auto Err = MR.withResourceKeyDo(826[&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))827return Err;828829return Registrar->registerEHFrames(EmittedRange);830}831832Error EHFrameRegistrationPlugin::notifyFailed(833MaterializationResponsibility &MR) {834std::lock_guard<std::mutex> Lock(EHFramePluginMutex);835InProcessLinks.erase(&MR);836return Error::success();837}838839Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,840ResourceKey K) {841std::vector<ExecutorAddrRange> RangesToRemove;842843ES.runSessionLocked([&] {844auto I = EHFrameRanges.find(K);845if (I != EHFrameRanges.end()) {846RangesToRemove = std::move(I->second);847EHFrameRanges.erase(I);848}849});850851Error Err = Error::success();852while (!RangesToRemove.empty()) {853auto RangeToRemove = RangesToRemove.back();854RangesToRemove.pop_back();855assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");856Err = joinErrors(std::move(Err),857Registrar->deregisterEHFrames(RangeToRemove));858}859860return Err;861}862863void EHFrameRegistrationPlugin::notifyTransferringResources(864JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {865auto SI = EHFrameRanges.find(SrcKey);866if (SI == EHFrameRanges.end())867return;868869auto DI = EHFrameRanges.find(DstKey);870if (DI != EHFrameRanges.end()) {871auto &SrcRanges = SI->second;872auto &DstRanges = DI->second;873DstRanges.reserve(DstRanges.size() + SrcRanges.size());874for (auto &SrcRange : SrcRanges)875DstRanges.push_back(std::move(SrcRange));876EHFrameRanges.erase(SI);877} else {878// We need to move SrcKey's ranges over without invalidating the SI879// iterator.880auto Tmp = std::move(SI->second);881EHFrameRanges.erase(SI);882EHFrameRanges[DstKey] = std::move(Tmp);883}884}885886} // End namespace orc.887} // End namespace llvm.888889890