brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.7 KiB · 4d4a705 Raw
452 lines · cpp
1//===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <memory>10 11#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"12#include "llvm/Object/COFF.h"13 14namespace {15 16using namespace llvm;17using namespace llvm::orc;18 19class JITDylibSearchOrderResolver : public JITSymbolResolver {20public:21  JITDylibSearchOrderResolver(MaterializationResponsibility &MR,22                              SymbolDependenceMap &Deps)23      : MR(MR), Deps(Deps) {}24 25  void lookup(const LookupSet &Symbols,26              OnResolvedFunction OnResolved) override {27    auto &ES = MR.getTargetJITDylib().getExecutionSession();28    SymbolLookupSet InternedSymbols;29 30    // Intern the requested symbols: lookup takes interned strings.31    for (auto &S : Symbols)32      InternedSymbols.add(ES.intern(S));33 34    // Build an OnResolve callback to unwrap the interned strings and pass them35    // to the OnResolved callback.36    auto OnResolvedWithUnwrap =37        [OnResolved = std::move(OnResolved)](38            Expected<SymbolMap> InternedResult) mutable {39          if (!InternedResult) {40            OnResolved(InternedResult.takeError());41            return;42          }43 44          LookupResult Result;45          for (auto &KV : *InternedResult)46            Result[*KV.first] = {KV.second.getAddress().getValue(),47                                 KV.second.getFlags()};48          OnResolved(Result);49        };50 51    JITDylibSearchOrder LinkOrder;52    MR.getTargetJITDylib().withLinkOrderDo(53        [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });54    ES.lookup(55        LookupKind::Static, LinkOrder, InternedSymbols, SymbolState::Resolved,56        std::move(OnResolvedWithUnwrap),57        [this](const SymbolDependenceMap &LookupDeps) { Deps = LookupDeps; });58  }59 60  Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override {61    LookupSet Result;62 63    for (auto &KV : MR.getSymbols()) {64      if (Symbols.count(*KV.first))65        Result.insert(*KV.first);66    }67 68    return Result;69  }70 71private:72  MaterializationResponsibility &MR;73  SymbolDependenceMap &Deps;74};75 76} // end anonymous namespace77 78namespace llvm {79namespace orc {80 81char RTDyldObjectLinkingLayer::ID;82 83using BaseT = RTTIExtends<RTDyldObjectLinkingLayer, ObjectLayer>;84 85RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(86    ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)87    : BaseT(ES), GetMemoryManager(std::move(GetMemoryManager)) {88  ES.registerResourceManager(*this);89}90 91RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() {92  assert(MemMgrs.empty() &&93         "Layer destroyed with resources still attached"94         "(ExecutionSession::endSession() must be called prior to "95         "destruction)");96}97 98void RTDyldObjectLinkingLayer::emit(99    std::unique_ptr<MaterializationResponsibility> R,100    std::unique_ptr<MemoryBuffer> O) {101  assert(O && "Object must not be null");102 103  auto &ES = getExecutionSession();104 105  auto Obj = object::ObjectFile::createObjectFile(*O);106 107  if (!Obj) {108    getExecutionSession().reportError(Obj.takeError());109    R->failMaterialization();110    return;111  }112 113  // Collect the internal symbols from the object file: We will need to114  // filter these later.115  auto InternalSymbols = std::make_shared<std::set<StringRef>>();116  {117    SymbolFlagsMap ExtraSymbolsToClaim;118    for (auto &Sym : (*Obj)->symbols()) {119 120      // Skip file symbols.121      if (auto SymType = Sym.getType()) {122        if (*SymType == object::SymbolRef::ST_File)123          continue;124      } else {125        ES.reportError(SymType.takeError());126        R->failMaterialization();127        return;128      }129 130      Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();131      if (!SymFlagsOrErr) {132        // TODO: Test this error.133        ES.reportError(SymFlagsOrErr.takeError());134        R->failMaterialization();135        return;136      }137 138      // Try to claim responsibility of weak symbols139      // if AutoClaimObjectSymbols flag is set.140      if (AutoClaimObjectSymbols &&141          (*SymFlagsOrErr & object::BasicSymbolRef::SF_Weak)) {142        auto SymName = Sym.getName();143        if (!SymName) {144          ES.reportError(SymName.takeError());145          R->failMaterialization();146          return;147        }148 149        // Already included in responsibility set, skip it150        SymbolStringPtr SymbolName = ES.intern(*SymName);151        if (R->getSymbols().count(SymbolName))152          continue;153 154        auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);155        if (!SymFlags) {156          ES.reportError(SymFlags.takeError());157          R->failMaterialization();158          return;159        }160 161        ExtraSymbolsToClaim[SymbolName] = *SymFlags;162        continue;163      }164 165      // Don't include symbols that aren't global.166      if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) {167        if (auto SymName = Sym.getName())168          InternalSymbols->insert(*SymName);169        else {170          ES.reportError(SymName.takeError());171          R->failMaterialization();172          return;173        }174      }175    }176 177    if (!ExtraSymbolsToClaim.empty()) {178      if (auto Err = R->defineMaterializing(ExtraSymbolsToClaim)) {179        ES.reportError(std::move(Err));180        R->failMaterialization();181      }182    }183  }184 185  auto MemMgr = GetMemoryManager(*O);186  auto &MemMgrRef = *MemMgr;187 188  // Switch to shared ownership of MR so that it can be captured by both189  // lambdas below.190  std::shared_ptr<MaterializationResponsibility> SharedR(std::move(R));191  auto Deps = std::make_unique<SymbolDependenceMap>();192 193  auto Resolver =194      std::make_unique<JITDylibSearchOrderResolver>(*SharedR, *Deps);195  auto *ResolverPtr = Resolver.get();196 197  jitLinkForORC(198      object::OwningBinary<object::ObjectFile>(std::move(*Obj), std::move(O)),199      MemMgrRef, *ResolverPtr, ProcessAllSections,200      [this, SharedR, &MemMgrRef, InternalSymbols](201          const object::ObjectFile &Obj,202          RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,203          std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {204        return onObjLoad(*SharedR, Obj, MemMgrRef, LoadedObjInfo,205                         ResolvedSymbols, *InternalSymbols);206      },207      [this, SharedR, MemMgr = std::move(MemMgr), Deps = std::move(Deps),208       Resolver = std::move(Resolver)](209          object::OwningBinary<object::ObjectFile> Obj,210          std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,211          Error Err) mutable {212        onObjEmit(*SharedR, std::move(Obj), std::move(MemMgr),213                  std::move(LoadedObjInfo), std::move(Deps), std::move(Err));214      });215}216 217void RTDyldObjectLinkingLayer::registerJITEventListener(JITEventListener &L) {218  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);219  assert(!llvm::is_contained(EventListeners, &L) &&220         "Listener has already been registered");221  EventListeners.push_back(&L);222}223 224void RTDyldObjectLinkingLayer::unregisterJITEventListener(JITEventListener &L) {225  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);226  auto I = llvm::find(EventListeners, &L);227  assert(I != EventListeners.end() && "Listener not registered");228  EventListeners.erase(I);229}230 231Error RTDyldObjectLinkingLayer::onObjLoad(232    MaterializationResponsibility &R, const object::ObjectFile &Obj,233    RuntimeDyld::MemoryManager &MemMgr,234    RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,235    std::map<StringRef, JITEvaluatedSymbol> Resolved,236    std::set<StringRef> &InternalSymbols) {237  SymbolFlagsMap ExtraSymbolsToClaim;238  SymbolMap Symbols;239 240  // Hack to support COFF constant pool comdats introduced during compilation:241  // (See http://llvm.org/PR40074)242  if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Obj)) {243    auto &ES = getExecutionSession();244 245    // For all resolved symbols that are not already in the responsibility set:246    // check whether the symbol is in a comdat section and if so mark it as247    // weak.248    for (auto &Sym : COFFObj->symbols()) {249      // getFlags() on COFF symbols can't fail.250      uint32_t SymFlags = cantFail(Sym.getFlags());251      if (SymFlags & object::BasicSymbolRef::SF_Undefined)252        continue;253      auto Name = Sym.getName();254      if (!Name)255        return Name.takeError();256      auto I = Resolved.find(*Name);257 258      // Skip unresolved symbols, internal symbols, and symbols that are259      // already in the responsibility set.260      if (I == Resolved.end() || InternalSymbols.count(*Name) ||261          R.getSymbols().count(ES.intern(*Name)))262        continue;263      auto Sec = Sym.getSection();264      if (!Sec)265        return Sec.takeError();266      if (*Sec == COFFObj->section_end())267        continue;268      auto &COFFSec = *COFFObj->getCOFFSection(**Sec);269      if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)270        I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak);271    }272 273    // Handle any aliases.274    for (auto &Sym : COFFObj->symbols()) {275      uint32_t SymFlags = cantFail(Sym.getFlags());276      if (SymFlags & object::BasicSymbolRef::SF_Undefined)277        continue;278      auto Name = Sym.getName();279      if (!Name)280        return Name.takeError();281      auto I = Resolved.find(*Name);282 283      // Skip already-resolved symbols, and symbols that we're not responsible284      // for.285      if (I != Resolved.end() || !R.getSymbols().count(ES.intern(*Name)))286        continue;287 288      // Skip anything other than weak externals.289      auto COFFSym = COFFObj->getCOFFSymbol(Sym);290      if (!COFFSym.isWeakExternal())291        continue;292      auto *WeakExternal = COFFSym.getAux<object::coff_aux_weak_external>();293      if (WeakExternal->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)294        continue;295 296      // We found an alias. Reuse the resolution of the alias target for the297      // alias itself.298      Expected<object::COFFSymbolRef> TargetSymbol =299          COFFObj->getSymbol(WeakExternal->TagIndex);300      if (!TargetSymbol)301        return TargetSymbol.takeError();302      Expected<StringRef> TargetName = COFFObj->getSymbolName(*TargetSymbol);303      if (!TargetName)304        return TargetName.takeError();305      auto J = Resolved.find(*TargetName);306      if (J == Resolved.end())307        return make_error<StringError>("Could alias target " + *TargetName +308                                           " not resolved",309                                       inconvertibleErrorCode());310      Resolved[*Name] = J->second;311    }312  }313 314  for (auto &KV : Resolved) {315    // Scan the symbols and add them to the Symbols map for resolution.316 317    // We never claim internal symbols.318    if (InternalSymbols.count(KV.first))319      continue;320 321    auto InternedName = getExecutionSession().intern(KV.first);322    auto Flags = KV.second.getFlags();323    auto I = R.getSymbols().find(InternedName);324    if (I != R.getSymbols().end()) {325      // Override object flags and claim responsibility for symbols if326      // requested.327      if (OverrideObjectFlags)328        Flags = I->second;329      else {330        // RuntimeDyld/MCJIT's weak tracking isn't compatible with ORC's. Even331        // if we're not overriding flags in general we should set the weak flag332        // according to the MaterializationResponsibility object symbol table.333        if (I->second.isWeak())334          Flags |= JITSymbolFlags::Weak;335      }336    } else if (AutoClaimObjectSymbols)337      ExtraSymbolsToClaim[InternedName] = Flags;338 339    Symbols[InternedName] = {ExecutorAddr(KV.second.getAddress()), Flags};340  }341 342  if (!ExtraSymbolsToClaim.empty()) {343    if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))344      return Err;345 346    // If we claimed responsibility for any weak symbols but were rejected then347    // we need to remove them from the resolved set.348    for (auto &KV : ExtraSymbolsToClaim)349      if (KV.second.isWeak() && !R.getSymbols().count(KV.first))350        Symbols.erase(KV.first);351  }352 353  if (auto Err = R.notifyResolved(Symbols)) {354    R.failMaterialization();355    return Err;356  }357 358  if (NotifyLoaded)359    NotifyLoaded(R, Obj, LoadedObjInfo);360 361  return Error::success();362}363 364void RTDyldObjectLinkingLayer::onObjEmit(365    MaterializationResponsibility &R,366    object::OwningBinary<object::ObjectFile> O,367    std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,368    std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,369    std::unique_ptr<SymbolDependenceMap> Deps, Error Err) {370  if (Err) {371    getExecutionSession().reportError(std::move(Err));372    R.failMaterialization();373    return;374  }375 376  SymbolDependenceGroup SDG;377  for (auto &[Sym, Flags] : R.getSymbols())378    SDG.Symbols.insert(Sym);379  SDG.Dependencies = std::move(*Deps);380 381  if (auto Err = R.notifyEmitted(SDG)) {382    getExecutionSession().reportError(std::move(Err));383    R.failMaterialization();384    return;385  }386 387  std::unique_ptr<object::ObjectFile> Obj;388  std::unique_ptr<MemoryBuffer> ObjBuffer;389  std::tie(Obj, ObjBuffer) = O.takeBinary();390 391  // Run EventListener notifyLoaded callbacks.392  {393    std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);394    for (auto *L : EventListeners)395      L->notifyObjectLoaded(pointerToJITTargetAddress(MemMgr.get()), *Obj,396                            *LoadedObjInfo);397  }398 399  if (NotifyEmitted)400    NotifyEmitted(R, std::move(ObjBuffer));401 402  if (auto Err = R.withResourceKeyDo(403          [&](ResourceKey K) { MemMgrs[K].push_back(std::move(MemMgr)); })) {404    getExecutionSession().reportError(std::move(Err));405    R.failMaterialization();406  }407}408 409Error RTDyldObjectLinkingLayer::handleRemoveResources(JITDylib &JD,410                                                      ResourceKey K) {411 412  std::vector<MemoryManagerUP> MemMgrsToRemove;413 414  getExecutionSession().runSessionLocked([&] {415    auto I = MemMgrs.find(K);416    if (I != MemMgrs.end()) {417      std::swap(MemMgrsToRemove, I->second);418      MemMgrs.erase(I);419    }420  });421 422  {423    std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);424    for (auto &MemMgr : MemMgrsToRemove) {425      for (auto *L : EventListeners)426        L->notifyFreeingObject(pointerToJITTargetAddress(MemMgr.get()));427      MemMgr->deregisterEHFrames();428    }429  }430 431  return Error::success();432}433 434void RTDyldObjectLinkingLayer::handleTransferResources(JITDylib &JD,435                                                       ResourceKey DstKey,436                                                       ResourceKey SrcKey) {437  if (MemMgrs.contains(SrcKey)) {438    // DstKey may not be in the DenseMap yet, so the following line may resize439    // the container and invalidate iterators and value references.440    auto &DstMemMgrs = MemMgrs[DstKey];441    auto &SrcMemMgrs = MemMgrs[SrcKey];442    DstMemMgrs.reserve(DstMemMgrs.size() + SrcMemMgrs.size());443    for (auto &MemMgr : SrcMemMgrs)444      DstMemMgrs.push_back(std::move(MemMgr));445 446    MemMgrs.erase(SrcKey);447  }448}449 450} // End namespace orc.451} // End namespace llvm.452