LLVM  16.0.0git
RTDyldObjectLinkingLayer.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "llvm/Object/COFF.h"
11 
12 namespace {
13 
14 using namespace llvm;
15 using namespace llvm::orc;
16 
17 class JITDylibSearchOrderResolver : public JITSymbolResolver {
18 public:
19  JITDylibSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {}
20 
21  void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override {
22  auto &ES = MR.getTargetJITDylib().getExecutionSession();
23  SymbolLookupSet InternedSymbols;
24 
25  // Intern the requested symbols: lookup takes interned strings.
26  for (auto &S : Symbols)
27  InternedSymbols.add(ES.intern(S));
28 
29  // Build an OnResolve callback to unwrap the interned strings and pass them
30  // to the OnResolved callback.
31  auto OnResolvedWithUnwrap =
32  [OnResolved = std::move(OnResolved)](
33  Expected<SymbolMap> InternedResult) mutable {
34  if (!InternedResult) {
35  OnResolved(InternedResult.takeError());
36  return;
37  }
38 
40  for (auto &KV : *InternedResult)
41  Result[*KV.first] = std::move(KV.second);
42  OnResolved(Result);
43  };
44 
45  // Register dependencies for all symbols contained in this set.
46  auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
47  MR.addDependenciesForAll(Deps);
48  };
49 
50  JITDylibSearchOrder LinkOrder;
51  MR.getTargetJITDylib().withLinkOrderDo(
52  [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
53  ES.lookup(LookupKind::Static, LinkOrder, InternedSymbols,
54  SymbolState::Resolved, std::move(OnResolvedWithUnwrap),
55  RegisterDependencies);
56  }
57 
58  Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override {
59  LookupSet Result;
60 
61  for (auto &KV : MR.getSymbols()) {
62  if (Symbols.count(*KV.first))
63  Result.insert(*KV.first);
64  }
65 
66  return Result;
67  }
68 
69 private:
71 };
72 
73 } // end anonymous namespace
74 
75 namespace llvm {
76 namespace orc {
77 
79 
81 
83  ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
84  : BaseT(ES), GetMemoryManager(GetMemoryManager) {
85  ES.registerResourceManager(*this);
86 }
87 
89  assert(MemMgrs.empty() && "Layer destroyed with resources still attached");
90 }
91 
93  std::unique_ptr<MaterializationResponsibility> R,
94  std::unique_ptr<MemoryBuffer> O) {
95  assert(O && "Object must not be null");
96 
97  auto &ES = getExecutionSession();
98 
100 
101  if (!Obj) {
102  getExecutionSession().reportError(Obj.takeError());
103  R->failMaterialization();
104  return;
105  }
106 
107  // Collect the internal symbols from the object file: We will need to
108  // filter these later.
109  auto InternalSymbols = std::make_shared<std::set<StringRef>>();
110  {
111  SymbolFlagsMap ExtraSymbolsToClaim;
112  for (auto &Sym : (*Obj)->symbols()) {
113 
114  // Skip file symbols.
115  if (auto SymType = Sym.getType()) {
116  if (*SymType == object::SymbolRef::ST_File)
117  continue;
118  } else {
119  ES.reportError(SymType.takeError());
120  R->failMaterialization();
121  return;
122  }
123 
124  Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
125  if (!SymFlagsOrErr) {
126  // TODO: Test this error.
127  ES.reportError(SymFlagsOrErr.takeError());
128  R->failMaterialization();
129  return;
130  }
131 
132  // Try to claim responsibility of weak symbols
133  // if AutoClaimObjectSymbols flag is set.
134  if (AutoClaimObjectSymbols &&
135  (*SymFlagsOrErr & object::BasicSymbolRef::SF_Weak)) {
136  auto SymName = Sym.getName();
137  if (!SymName) {
138  ES.reportError(SymName.takeError());
139  R->failMaterialization();
140  return;
141  }
142 
143  // Already included in responsibility set, skip it
144  SymbolStringPtr SymbolName = ES.intern(*SymName);
145  if (R->getSymbols().count(SymbolName))
146  continue;
147 
148  auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
149  if (!SymFlags) {
150  ES.reportError(SymFlags.takeError());
151  R->failMaterialization();
152  return;
153  }
154 
155  ExtraSymbolsToClaim[SymbolName] = *SymFlags;
156  continue;
157  }
158 
159  // Don't include symbols that aren't global.
160  if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) {
161  if (auto SymName = Sym.getName())
162  InternalSymbols->insert(*SymName);
163  else {
164  ES.reportError(SymName.takeError());
165  R->failMaterialization();
166  return;
167  }
168  }
169  }
170 
171  if (!ExtraSymbolsToClaim.empty()) {
172  if (auto Err = R->defineMaterializing(ExtraSymbolsToClaim)) {
173  ES.reportError(std::move(Err));
174  R->failMaterialization();
175  }
176  }
177  }
178 
179  auto MemMgr = GetMemoryManager();
180  auto &MemMgrRef = *MemMgr;
181 
182  // Switch to shared ownership of MR so that it can be captured by both
183  // lambdas below.
184  std::shared_ptr<MaterializationResponsibility> SharedR(std::move(R));
185 
186  JITDylibSearchOrderResolver Resolver(*SharedR);
187 
190  MemMgrRef, Resolver, ProcessAllSections,
191  [this, SharedR, &MemMgrRef, InternalSymbols](
192  const object::ObjectFile &Obj,
193  RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
194  std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
195  return onObjLoad(*SharedR, Obj, MemMgrRef, LoadedObjInfo,
196  ResolvedSymbols, *InternalSymbols);
197  },
198  [this, SharedR, MemMgr = std::move(MemMgr)](
200  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
201  Error Err) mutable {
202  onObjEmit(*SharedR, std::move(Obj), std::move(MemMgr),
203  std::move(LoadedObjInfo), std::move(Err));
204  });
205 }
206 
208  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
209  assert(!llvm::is_contained(EventListeners, &L) &&
210  "Listener has already been registered");
211  EventListeners.push_back(&L);
212 }
213 
215  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
216  auto I = llvm::find(EventListeners, &L);
217  assert(I != EventListeners.end() && "Listener not registered");
218  EventListeners.erase(I);
219 }
220 
221 Error RTDyldObjectLinkingLayer::onObjLoad(
224  RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
225  std::map<StringRef, JITEvaluatedSymbol> Resolved,
226  std::set<StringRef> &InternalSymbols) {
227  SymbolFlagsMap ExtraSymbolsToClaim;
228  SymbolMap Symbols;
229 
230  // Hack to support COFF constant pool comdats introduced during compilation:
231  // (See http://llvm.org/PR40074)
232  if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Obj)) {
233  auto &ES = getExecutionSession();
234 
235  // For all resolved symbols that are not already in the responsibilty set:
236  // check whether the symbol is in a comdat section and if so mark it as
237  // weak.
238  for (auto &Sym : COFFObj->symbols()) {
239  // getFlags() on COFF symbols can't fail.
240  uint32_t SymFlags = cantFail(Sym.getFlags());
242  continue;
243  auto Name = Sym.getName();
244  if (!Name)
245  return Name.takeError();
246  auto I = Resolved.find(*Name);
247 
248  // Skip unresolved symbols, internal symbols, and symbols that are
249  // already in the responsibility set.
250  if (I == Resolved.end() || InternalSymbols.count(*Name) ||
251  R.getSymbols().count(ES.intern(*Name)))
252  continue;
253  auto Sec = Sym.getSection();
254  if (!Sec)
255  return Sec.takeError();
256  if (*Sec == COFFObj->section_end())
257  continue;
258  auto &COFFSec = *COFFObj->getCOFFSection(**Sec);
259  if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
260  I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak);
261  }
262  }
263 
264  for (auto &KV : Resolved) {
265  // Scan the symbols and add them to the Symbols map for resolution.
266 
267  // We never claim internal symbols.
268  if (InternalSymbols.count(KV.first))
269  continue;
270 
271  auto InternedName = getExecutionSession().intern(KV.first);
272  auto Flags = KV.second.getFlags();
273  auto I = R.getSymbols().find(InternedName);
274  if (I != R.getSymbols().end()) {
275  // Override object flags and claim responsibility for symbols if
276  // requested.
277  if (OverrideObjectFlags)
278  Flags = I->second;
279  else {
280  // RuntimeDyld/MCJIT's weak tracking isn't compatible with ORC's. Even
281  // if we're not overriding flags in general we should set the weak flag
282  // according to the MaterializationResponsibility object symbol table.
283  if (I->second.isWeak())
284  Flags |= JITSymbolFlags::Weak;
285  }
286  } else if (AutoClaimObjectSymbols)
287  ExtraSymbolsToClaim[InternedName] = Flags;
288 
289  Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
290  }
291 
292  if (!ExtraSymbolsToClaim.empty()) {
293  if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
294  return Err;
295 
296  // If we claimed responsibility for any weak symbols but were rejected then
297  // we need to remove them from the resolved set.
298  for (auto &KV : ExtraSymbolsToClaim)
299  if (KV.second.isWeak() && !R.getSymbols().count(KV.first))
300  Symbols.erase(KV.first);
301  }
302 
303  if (auto Err = R.notifyResolved(Symbols)) {
304  R.failMaterialization();
305  return Err;
306  }
307 
308  if (NotifyLoaded)
309  NotifyLoaded(R, Obj, LoadedObjInfo);
310 
311  return Error::success();
312 }
313 
314 void RTDyldObjectLinkingLayer::onObjEmit(
317  std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
318  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, Error Err) {
319  if (Err) {
320  getExecutionSession().reportError(std::move(Err));
321  R.failMaterialization();
322  return;
323  }
324 
325  if (auto Err = R.notifyEmitted()) {
326  getExecutionSession().reportError(std::move(Err));
327  R.failMaterialization();
328  return;
329  }
330 
331  std::unique_ptr<object::ObjectFile> Obj;
332  std::unique_ptr<MemoryBuffer> ObjBuffer;
333  std::tie(Obj, ObjBuffer) = O.takeBinary();
334 
335  // Run EventListener notifyLoaded callbacks.
336  {
337  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
338  for (auto *L : EventListeners)
339  L->notifyObjectLoaded(pointerToJITTargetAddress(MemMgr.get()), *Obj,
340  *LoadedObjInfo);
341  }
342 
343  if (NotifyEmitted)
344  NotifyEmitted(R, std::move(ObjBuffer));
345 
346  if (auto Err = R.withResourceKeyDo(
347  [&](ResourceKey K) { MemMgrs[K].push_back(std::move(MemMgr)); })) {
348  getExecutionSession().reportError(std::move(Err));
349  R.failMaterialization();
350  }
351 }
352 
353 Error RTDyldObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
354 
355  std::vector<MemoryManagerUP> MemMgrsToRemove;
356 
357  getExecutionSession().runSessionLocked([&] {
358  auto I = MemMgrs.find(K);
359  if (I != MemMgrs.end()) {
360  std::swap(MemMgrsToRemove, I->second);
361  MemMgrs.erase(I);
362  }
363  });
364 
365  {
366  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
367  for (auto &MemMgr : MemMgrsToRemove) {
368  for (auto *L : EventListeners)
369  L->notifyFreeingObject(pointerToJITTargetAddress(MemMgr.get()));
370  MemMgr->deregisterEHFrames();
371  }
372  }
373 
374  return Error::success();
375 }
376 
377 void RTDyldObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
378  ResourceKey SrcKey) {
379  auto I = MemMgrs.find(SrcKey);
380  if (I != MemMgrs.end()) {
381  auto &SrcMemMgrs = I->second;
382  auto &DstMemMgrs = MemMgrs[DstKey];
383  DstMemMgrs.reserve(DstMemMgrs.size() + SrcMemMgrs.size());
384  for (auto &MemMgr : SrcMemMgrs)
385  DstMemMgrs.push_back(std::move(MemMgr));
386 
387  // Erase SrcKey entry using value rather than iterator I: I may have been
388  // invalidated when we looked up DstKey.
389  MemMgrs.erase(SrcKey);
390  }
391 }
392 
393 } // End namespace orc.
394 } // End namespace llvm.
llvm::orc::ResourceKey
uintptr_t ResourceKey
Definition: Core.h:50
llvm::orc::MaterializationResponsibility
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:519
llvm::AArch64CC::LO
@ LO
Definition: AArch64BaseInfo.h:258
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::orc::SymbolLookupSet
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:175
llvm::orc::LookupKind::Static
@ Static
llvm::orc::SymbolStringPtr
Pointer to a pooled string representing a symbol name.
Definition: SymbolStringPool.h:57
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::DenseMapBase::erase
bool erase(const KeyT &Val)
Definition: DenseMap.h:302
llvm::orc::RTDyldObjectLinkingLayer::registerJITEventListener
void registerJITEventListener(JITEventListener &L)
Register a JITEventListener.
Definition: RTDyldObjectLinkingLayer.cpp:207
llvm::orc::ExecutionSession::registerResourceManager
void registerResourceManager(ResourceManager &RM)
Register the given ResourceManager with this ExecutionSession.
Definition: Core.cpp:1914
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::object::SymbolRef::ST_File
@ ST_File
Definition: ObjectFile.h:176
llvm::object::BasicSymbolRef::SF_Weak
@ SF_Weak
Definition: SymbolicFile.h:112
llvm::orc::RTDyldObjectLinkingLayer::emit
void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< MemoryBuffer > O) override
Emit the object.
Definition: RTDyldObjectLinkingLayer.cpp:92
llvm::JITEvaluatedSymbol
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:229
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:265
llvm::Resolver
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:2133
llvm::orc
Definition: COFFPlatform.h:30
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::orc::SymbolLookupSet::add
SymbolLookupSet & add(SymbolStringPtr Name, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)
Add an element to the set.
Definition: Core.h:236
llvm::orc::tpctypes::LookupResult
std::vector< ExecutorAddr > LookupResult
Definition: TargetProcessControlTypes.h:90
llvm::RTTIExtends< ObjectLinkingLayer, ObjectLayer >
llvm::orc::RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer
RTDyldObjectLinkingLayer(ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
Construct an ObjectLinkingLayer with the given NotifyLoaded, and NotifyEmitted functors.
Definition: RTDyldObjectLinkingLayer.cpp:82
llvm::orc::RTDyldObjectLinkingLayer::unregisterJITEventListener
void unregisterJITEventListener(JITEventListener &L)
Unregister a JITEventListener.
Definition: RTDyldObjectLinkingLayer.cpp:214
RTDyldObjectLinkingLayer.h
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:264
llvm::find
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1754
llvm::orc::RTDyldObjectLinkingLayer::GetMemoryManagerFunction
std::function< std::unique_ptr< RuntimeDyld::MemoryManager >()> GetMemoryManagerFunction
Definition: RTDyldObjectLinkingLayer.h:53
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap< JITDylib *, SymbolNameSet >
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::object::BasicSymbolRef::SF_Undefined
@ SF_Undefined
Definition: SymbolicFile.h:110
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1868
llvm::jitLinkForORC
void jitLinkForORC(object::OwningBinary< object::ObjectFile > O, RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver, bool ProcessAllSections, unique_function< Error(const object::ObjectFile &Obj, RuntimeDyld::LoadedObjectInfo &, std::map< StringRef, JITEvaluatedSymbol >)> OnLoaded, unique_function< void(object::OwningBinary< object::ObjectFile >, std::unique_ptr< RuntimeDyld::LoadedObjectInfo >, Error)> OnEmitted)
llvm::DenseMapBase::find
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
llvm::object::ObjectFile::createObjectFile
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:194
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::COFF::IMAGE_SCN_LNK_COMDAT
@ IMAGE_SCN_LNK_COMDAT
Definition: COFF.h:294
llvm::orc::JITDylibSearchOrder
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
Definition: Core.h:154
llvm::DenseMapBase::empty
bool empty() const
Definition: DenseMap.h:98
llvm::JITEventListener
JITEventListener - Abstract interface for use by the JIT to notify clients about significant events d...
Definition: JITEventListener.h:40
llvm::JITSymbolFlags::Weak
@ Weak
Definition: JITSymbol.h:82
llvm::orc::RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer
~RTDyldObjectLinkingLayer()
Definition: RTDyldObjectLinkingLayer.cpp:88
llvm::object::ObjectFile
This class is the base class for all object file types.
Definition: ObjectFile.h:228
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:744
uint32_t
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::DenseMapBase::insert
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:207
llvm::pointerToJITTargetAddress
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Convert a pointer to a JITTargetAddress.
Definition: JITSymbol.h:69
llvm::JITSymbolResolver
Symbol resolution interface.
Definition: JITSymbol.h:371
llvm::AMDGPU::HSAMD::Kernel::Key::SymbolName
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Definition: AMDGPUMetadata.h:386
llvm::object::OwningBinary
Definition: RuntimeDyld.h:36
llvm::DenseMapBase::end
iterator end()
Definition: DenseMap.h:84
llvm::RuntimeDyld::LoadedObjectInfo
Information about the loaded object.
Definition: RuntimeDyld.h:69
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::orc::ExecutionSession
An ExecutionSession represents a running JIT program.
Definition: Core.h:1365
llvm::orc::RTDyldObjectLinkingLayer::ID
static char ID
Definition: RTDyldObjectLinkingLayer.h:41
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:596
COFF.h
lookup
static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
Definition: InlineInfo.cpp:108
llvm::object::BasicSymbolRef::SF_Global
@ SF_Global
Definition: SymbolicFile.h:111
llvm::JITSymbolFlags::fromObjectSymbol
static Expected< JITSymbolFlags > fromObjectSymbol(const object::SymbolRef &Symbol)
Construct a JITSymbolFlags value based on the flags of the given libobject symbol.
Definition: JITSymbol.cpp:69
llvm::DenseMapBase::reserve
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition: DenseMap.h:103
llvm::omp::RTLDependInfoFields::Flags
@ Flags
llvm::orc::SymbolState::Resolved
@ Resolved
Queried, materialization begun.
llvm::RuntimeDyld::MemoryManager
Memory Management.
Definition: RuntimeDyld.h:92