diff options
Diffstat (limited to 'llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp')
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp | 229 |
1 files changed, 177 insertions, 52 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp index 2572b7f4878d..02066b458dfc 100644 --- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp @@ -50,9 +50,9 @@ public: void lookup(const LookupMap &Symbols, std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { - JITDylibSearchOrder SearchOrder; - MR.getTargetJITDylib().withSearchOrderDo( - [&](const JITDylibSearchOrder &O) { SearchOrder = O; }); + JITDylibSearchOrder LinkOrder; + MR.getTargetJITDylib().withLinkOrderDo( + [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); auto &ES = Layer.getExecutionSession(); @@ -84,7 +84,13 @@ public: } }; - ES.lookup(LookupKind::Static, SearchOrder, std::move(LookupSet), + for (auto &KV : InternalNamedSymbolDeps) { + SymbolDependenceMap InternalDeps; + InternalDeps[&MR.getTargetJITDylib()] = std::move(KV.second); + MR.addDependencies(KV.first, InternalDeps); + } + + ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), SymbolState::Resolved, std::move(OnResolve), [this](const SymbolDependenceMap &Deps) { registerDependencies(Deps); @@ -138,6 +144,56 @@ public: if (!ExtraSymbolsToClaim.empty()) if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim)) return notifyFailed(std::move(Err)); + + { + + // Check that InternedResult matches up with MR.getSymbols(). + // This guards against faulty transformations / compilers / object caches. + + // First check that there aren't any missing symbols. + size_t NumMaterializationSideEffectsOnlySymbols = 0; + SymbolNameVector ExtraSymbols; + SymbolNameVector MissingSymbols; + for (auto &KV : MR.getSymbols()) { + + // If this is a materialization-side-effects only symbol then bump + // the counter and make sure it's *not* defined, otherwise make + // sure that it is defined. + if (KV.second.hasMaterializationSideEffectsOnly()) { + ++NumMaterializationSideEffectsOnlySymbols; + if (InternedResult.count(KV.first)) + ExtraSymbols.push_back(KV.first); + continue; + } else if (!InternedResult.count(KV.first)) + MissingSymbols.push_back(KV.first); + } + + // If there were missing symbols then report the error. + if (!MissingSymbols.empty()) { + ES.reportError(make_error<MissingSymbolDefinitions>( + G.getName(), std::move(MissingSymbols))); + MR.failMaterialization(); + return; + } + + // If there are more definitions than expected, add them to the + // ExtraSymbols vector. + if (InternedResult.size() > + MR.getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { + for (auto &KV : InternedResult) + if (!MR.getSymbols().count(KV.first)) + ExtraSymbols.push_back(KV.first); + } + + // If there were extra definitions then report the error. + if (!ExtraSymbols.empty()) { + ES.reportError(make_error<UnexpectedSymbolDefinitions>( + G.getName(), std::move(ExtraSymbols))); + MR.failMaterialization(); + return; + } + } + if (auto Err = MR.notifyResolved(InternedResult)) { Layer.getExecutionSession().reportError(std::move(Err)); MR.failMaterialization(); @@ -168,16 +224,22 @@ public: // link graph to build the symbol dependence graph. Config.PrePrunePasses.push_back( [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); }); - Config.PostPrunePasses.push_back( - [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); Layer.modifyPassConfig(MR, TT, Config); + Config.PostPrunePasses.push_back( + [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); + return Error::success(); } private: - using AnonToNamedDependenciesMap = DenseMap<const Symbol *, SymbolNameSet>; + struct LocalSymbolNamedDependencies { + SymbolNameSet Internal, External; + }; + + using LocalSymbolNamedDependenciesMap = + DenseMap<const Symbol *, LocalSymbolNamedDependencies>; Error externalizeWeakAndCommonSymbols(LinkGraph &G) { auto &ES = Layer.getExecutionSession(); @@ -206,30 +268,69 @@ private: Error computeNamedSymbolDependencies(LinkGraph &G) { auto &ES = MR.getTargetJITDylib().getExecutionSession(); - auto AnonDeps = computeAnonDeps(G); + auto LocalDeps = computeLocalDeps(G); + // Compute dependencies for symbols defined in the JITLink graph. for (auto *Sym : G.defined_symbols()) { - // Skip anonymous and non-global atoms: we do not need dependencies for - // these. + // Skip local symbols: we do not track dependencies for these. if (Sym->getScope() == Scope::Local) continue; + assert(Sym->hasName() && + "Defined non-local jitlink::Symbol should have a name"); - auto SymName = ES.intern(Sym->getName()); - SymbolNameSet &SymDeps = NamedSymbolDeps[SymName]; + SymbolNameSet ExternalSymDeps, InternalSymDeps; + // Find internal and external named symbol dependencies. for (auto &E : Sym->getBlock().edges()) { auto &TargetSym = E.getTarget(); - if (TargetSym.getScope() != Scope::Local) - SymDeps.insert(ES.intern(TargetSym.getName())); - else { + if (TargetSym.getScope() != Scope::Local) { + if (TargetSym.isExternal()) + ExternalSymDeps.insert(ES.intern(TargetSym.getName())); + else if (&TargetSym != Sym) + InternalSymDeps.insert(ES.intern(TargetSym.getName())); + } else { assert(TargetSym.isDefined() && - "Anonymous/local symbols must be defined"); - auto I = AnonDeps.find(&TargetSym); - if (I != AnonDeps.end()) - for (auto &S : I->second) - SymDeps.insert(S); + "local symbols must be defined"); + auto I = LocalDeps.find(&TargetSym); + if (I != LocalDeps.end()) { + for (auto &S : I->second.External) + ExternalSymDeps.insert(S); + for (auto &S : I->second.Internal) + InternalSymDeps.insert(S); + } + } + } + + if (ExternalSymDeps.empty() && InternalSymDeps.empty()) + continue; + + auto SymName = ES.intern(Sym->getName()); + if (!ExternalSymDeps.empty()) + ExternalNamedSymbolDeps[SymName] = std::move(ExternalSymDeps); + if (!InternalSymDeps.empty()) + InternalNamedSymbolDeps[SymName] = std::move(InternalSymDeps); + } + + for (auto &P : Layer.Plugins) { + auto SyntheticLocalDeps = P->getSyntheticSymbolLocalDependencies(MR); + if (SyntheticLocalDeps.empty()) + continue; + + for (auto &KV : SyntheticLocalDeps) { + auto &Name = KV.first; + auto &LocalDepsForName = KV.second; + for (auto *Local : LocalDepsForName) { + assert(Local->getScope() == Scope::Local && + "Dependence on non-local symbol"); + auto LocalNamedDepsItr = LocalDeps.find(Local); + if (LocalNamedDepsItr == LocalDeps.end()) + continue; + for (auto &S : LocalNamedDepsItr->second.Internal) + InternalNamedSymbolDeps[Name].insert(S); + for (auto &S : LocalNamedDepsItr->second.External) + ExternalNamedSymbolDeps[Name].insert(S); } } } @@ -237,68 +338,85 @@ private: return Error::success(); } - AnonToNamedDependenciesMap computeAnonDeps(LinkGraph &G) { + LocalSymbolNamedDependenciesMap computeLocalDeps(LinkGraph &G) { + DenseMap<jitlink::Symbol *, DenseSet<jitlink::Symbol *>> DepMap; - auto &ES = MR.getTargetJITDylib().getExecutionSession(); - AnonToNamedDependenciesMap DepMap; - - // For all anonymous symbols: + // For all local symbols: // (1) Add their named dependencies. // (2) Add them to the worklist for further iteration if they have any - // depend on any other anonymous symbols. + // depend on any other local symbols. struct WorklistEntry { - WorklistEntry(Symbol *Sym, DenseSet<Symbol *> SymAnonDeps) - : Sym(Sym), SymAnonDeps(std::move(SymAnonDeps)) {} + WorklistEntry(Symbol *Sym, DenseSet<Symbol *> LocalDeps) + : Sym(Sym), LocalDeps(std::move(LocalDeps)) {} Symbol *Sym = nullptr; - DenseSet<Symbol *> SymAnonDeps; + DenseSet<Symbol *> LocalDeps; }; std::vector<WorklistEntry> Worklist; for (auto *Sym : G.defined_symbols()) - if (!Sym->hasName()) { + if (Sym->getScope() == Scope::Local) { auto &SymNamedDeps = DepMap[Sym]; - DenseSet<Symbol *> SymAnonDeps; + DenseSet<Symbol *> LocalDeps; for (auto &E : Sym->getBlock().edges()) { auto &TargetSym = E.getTarget(); - if (TargetSym.hasName()) - SymNamedDeps.insert(ES.intern(TargetSym.getName())); + if (TargetSym.getScope() != Scope::Local) + SymNamedDeps.insert(&TargetSym); else { assert(TargetSym.isDefined() && - "Anonymous symbols must be defined"); - SymAnonDeps.insert(&TargetSym); + "local symbols must be defined"); + LocalDeps.insert(&TargetSym); } } - if (!SymAnonDeps.empty()) - Worklist.push_back(WorklistEntry(Sym, std::move(SymAnonDeps))); + if (!LocalDeps.empty()) + Worklist.push_back(WorklistEntry(Sym, std::move(LocalDeps))); } - // Loop over all anonymous symbols with anonymous dependencies, propagating - // their respective *named* dependencies. Iterate until we hit a stable + // Loop over all local symbols with local dependencies, propagating + // their respective non-local dependencies. Iterate until we hit a stable // state. bool Changed; do { Changed = false; for (auto &WLEntry : Worklist) { auto *Sym = WLEntry.Sym; - auto &SymNamedDeps = DepMap[Sym]; - auto &SymAnonDeps = WLEntry.SymAnonDeps; + auto &NamedDeps = DepMap[Sym]; + auto &LocalDeps = WLEntry.LocalDeps; - for (auto *TargetSym : SymAnonDeps) { + for (auto *TargetSym : LocalDeps) { auto I = DepMap.find(TargetSym); if (I != DepMap.end()) for (const auto &S : I->second) - Changed |= SymNamedDeps.insert(S).second; + Changed |= NamedDeps.insert(S).second; } } } while (Changed); - return DepMap; + // Intern the results to produce a mapping of jitlink::Symbol* to internal + // and external symbol names. + auto &ES = Layer.getExecutionSession(); + LocalSymbolNamedDependenciesMap Result; + for (auto &KV : DepMap) { + auto *Local = KV.first; + assert(Local->getScope() == Scope::Local && + "DepMap keys should all be local symbols"); + auto &LocalNamedDeps = Result[Local]; + for (auto *Named : KV.second) { + assert(Named->getScope() != Scope::Local && + "DepMap values should all be non-local symbol sets"); + if (Named->isExternal()) + LocalNamedDeps.External.insert(ES.intern(Named->getName())); + else + LocalNamedDeps.Internal.insert(ES.intern(Named->getName())); + } + } + + return Result; } void registerDependencies(const SymbolDependenceMap &QueryDeps) { - for (auto &NamedDepsEntry : NamedSymbolDeps) { + for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) { auto &Name = NamedDepsEntry.first; auto &NameDeps = NamedDepsEntry.second; SymbolDependenceMap SymbolDeps; @@ -323,7 +441,8 @@ private: ObjectLinkingLayer &Layer; MaterializationResponsibility MR; std::unique_ptr<MemoryBuffer> ObjBuffer; - DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps; + DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps; + DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps; }; ObjectLinkingLayer::Plugin::~Plugin() {} @@ -426,18 +545,21 @@ EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( void EHFrameRegistrationPlugin::modifyPassConfig( MaterializationResponsibility &MR, const Triple &TT, PassConfiguration &PassConfig) { - assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?"); - PassConfig.PostFixupPasses.push_back( - createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr, - size_t Size) { - if (Addr) - InProcessLinks[&MR] = { Addr, Size }; + PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( + TT, [this, &MR](JITTargetAddress Addr, size_t Size) { + if (Addr) { + std::lock_guard<std::mutex> Lock(EHFramePluginMutex); + assert(!InProcessLinks.count(&MR) && + "Link for MR already being tracked?"); + InProcessLinks[&MR] = {Addr, Size}; + } })); } Error EHFrameRegistrationPlugin::notifyEmitted( MaterializationResponsibility &MR) { + std::lock_guard<std::mutex> Lock(EHFramePluginMutex); auto EHFrameRangeItr = InProcessLinks.find(&MR); if (EHFrameRangeItr == InProcessLinks.end()) @@ -457,6 +579,8 @@ Error EHFrameRegistrationPlugin::notifyEmitted( } Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) { + std::lock_guard<std::mutex> Lock(EHFramePluginMutex); + auto EHFrameRangeItr = TrackedEHFrameRanges.find(K); if (EHFrameRangeItr == TrackedEHFrameRanges.end()) return Error::success(); @@ -470,6 +594,7 @@ Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) { } Error EHFrameRegistrationPlugin::notifyRemovingAllModules() { + std::lock_guard<std::mutex> Lock(EHFramePluginMutex); std::vector<EHFrameRange> EHFrameRanges = std::move(UntrackedEHFrameRanges); |