LLVM  14.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  for (auto &Sym : (*Obj)->symbols()) {
112 
113  // Skip file symbols.
114  if (auto SymType = Sym.getType()) {
115  if (*SymType == object::SymbolRef::ST_File)
116  continue;
117  } else {
118  ES.reportError(SymType.takeError());
119  R->failMaterialization();
120  return;
121  }
122 
123  Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
124  if (!SymFlagsOrErr) {
125  // TODO: Test this error.
126  ES.reportError(SymFlagsOrErr.takeError());
127  R->failMaterialization();
128  return;
129  }
130 
131  // Don't include symbols that aren't global.
132  if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) {
133  if (auto SymName = Sym.getName())
134  InternalSymbols->insert(*SymName);
135  else {
136  ES.reportError(SymName.takeError());
137  R->failMaterialization();
138  return;
139  }
140  }
141  }
142  }
143 
144  auto MemMgr = GetMemoryManager();
145  auto &MemMgrRef = *MemMgr;
146 
147  // Switch to shared ownership of MR so that it can be captured by both
148  // lambdas below.
149  std::shared_ptr<MaterializationResponsibility> SharedR(std::move(R));
150 
151  JITDylibSearchOrderResolver Resolver(*SharedR);
152 
155  MemMgrRef, Resolver, ProcessAllSections,
156  [this, SharedR, &MemMgrRef, InternalSymbols](
157  const object::ObjectFile &Obj,
158  RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
159  std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
160  return onObjLoad(*SharedR, Obj, MemMgrRef, LoadedObjInfo,
161  ResolvedSymbols, *InternalSymbols);
162  },
163  [this, SharedR, MemMgr = std::move(MemMgr)](
165  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
166  Error Err) mutable {
167  onObjEmit(*SharedR, std::move(Obj), std::move(MemMgr),
168  std::move(LoadedObjInfo), std::move(Err));
169  });
170 }
171 
173  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
174  assert(!llvm::is_contained(EventListeners, &L) &&
175  "Listener has already been registered");
176  EventListeners.push_back(&L);
177 }
178 
180  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
181  auto I = llvm::find(EventListeners, &L);
182  assert(I != EventListeners.end() && "Listener not registered");
183  EventListeners.erase(I);
184 }
185 
186 Error RTDyldObjectLinkingLayer::onObjLoad(
189  RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
190  std::map<StringRef, JITEvaluatedSymbol> Resolved,
191  std::set<StringRef> &InternalSymbols) {
192  SymbolFlagsMap ExtraSymbolsToClaim;
193  SymbolMap Symbols;
194 
195  // Hack to support COFF constant pool comdats introduced during compilation:
196  // (See http://llvm.org/PR40074)
197  if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Obj)) {
198  auto &ES = getExecutionSession();
199 
200  // For all resolved symbols that are not already in the responsibilty set:
201  // check whether the symbol is in a comdat section and if so mark it as
202  // weak.
203  for (auto &Sym : COFFObj->symbols()) {
204  // getFlags() on COFF symbols can't fail.
205  uint32_t SymFlags = cantFail(Sym.getFlags());
207  continue;
208  auto Name = Sym.getName();
209  if (!Name)
210  return Name.takeError();
211  auto I = Resolved.find(*Name);
212 
213  // Skip unresolved symbols, internal symbols, and symbols that are
214  // already in the responsibility set.
215  if (I == Resolved.end() || InternalSymbols.count(*Name) ||
216  R.getSymbols().count(ES.intern(*Name)))
217  continue;
218  auto Sec = Sym.getSection();
219  if (!Sec)
220  return Sec.takeError();
221  if (*Sec == COFFObj->section_end())
222  continue;
223  auto &COFFSec = *COFFObj->getCOFFSection(**Sec);
224  if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
225  I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak);
226  }
227  }
228 
229  for (auto &KV : Resolved) {
230  // Scan the symbols and add them to the Symbols map for resolution.
231 
232  // We never claim internal symbols.
233  if (InternalSymbols.count(KV.first))
234  continue;
235 
236  auto InternedName = getExecutionSession().intern(KV.first);
237  auto Flags = KV.second.getFlags();
238 
239  // Override object flags and claim responsibility for symbols if
240  // requested.
241  if (OverrideObjectFlags || AutoClaimObjectSymbols) {
242  auto I = R.getSymbols().find(InternedName);
243 
244  if (OverrideObjectFlags && I != R.getSymbols().end())
245  Flags = I->second;
246  else if (AutoClaimObjectSymbols && I == R.getSymbols().end())
247  ExtraSymbolsToClaim[InternedName] = Flags;
248  }
249 
250  Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
251  }
252 
253  if (!ExtraSymbolsToClaim.empty()) {
254  if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
255  return Err;
256 
257  // If we claimed responsibility for any weak symbols but were rejected then
258  // we need to remove them from the resolved set.
259  for (auto &KV : ExtraSymbolsToClaim)
260  if (KV.second.isWeak() && !R.getSymbols().count(KV.first))
261  Symbols.erase(KV.first);
262  }
263 
264  if (auto Err = R.notifyResolved(Symbols)) {
265  R.failMaterialization();
266  return Err;
267  }
268 
269  if (NotifyLoaded)
270  NotifyLoaded(R, Obj, LoadedObjInfo);
271 
272  return Error::success();
273 }
274 
275 void RTDyldObjectLinkingLayer::onObjEmit(
278  std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
279  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, Error Err) {
280  if (Err) {
281  getExecutionSession().reportError(std::move(Err));
282  R.failMaterialization();
283  return;
284  }
285 
286  if (auto Err = R.notifyEmitted()) {
287  getExecutionSession().reportError(std::move(Err));
288  R.failMaterialization();
289  return;
290  }
291 
292  std::unique_ptr<object::ObjectFile> Obj;
293  std::unique_ptr<MemoryBuffer> ObjBuffer;
294  std::tie(Obj, ObjBuffer) = O.takeBinary();
295 
296  // Run EventListener notifyLoaded callbacks.
297  {
298  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
299  for (auto *L : EventListeners)
300  L->notifyObjectLoaded(pointerToJITTargetAddress(MemMgr.get()), *Obj,
301  *LoadedObjInfo);
302  }
303 
304  if (NotifyEmitted)
305  NotifyEmitted(R, std::move(ObjBuffer));
306 
307  if (auto Err = R.withResourceKeyDo(
308  [&](ResourceKey K) { MemMgrs[K].push_back(std::move(MemMgr)); })) {
309  getExecutionSession().reportError(std::move(Err));
310  R.failMaterialization();
311  }
312 }
313 
314 Error RTDyldObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
315 
316  std::vector<MemoryManagerUP> MemMgrsToRemove;
317 
318  getExecutionSession().runSessionLocked([&] {
319  auto I = MemMgrs.find(K);
320  if (I != MemMgrs.end()) {
321  std::swap(MemMgrsToRemove, I->second);
322  MemMgrs.erase(I);
323  }
324  });
325 
326  {
327  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
328  for (auto &MemMgr : MemMgrsToRemove) {
329  for (auto *L : EventListeners)
330  L->notifyFreeingObject(pointerToJITTargetAddress(MemMgr.get()));
331  MemMgr->deregisterEHFrames();
332  }
333  }
334 
335  return Error::success();
336 }
337 
338 void RTDyldObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
339  ResourceKey SrcKey) {
340  auto I = MemMgrs.find(SrcKey);
341  if (I != MemMgrs.end()) {
342  auto &SrcMemMgrs = I->second;
343  auto &DstMemMgrs = MemMgrs[DstKey];
344  DstMemMgrs.reserve(DstMemMgrs.size() + SrcMemMgrs.size());
345  for (auto &MemMgr : SrcMemMgrs)
346  DstMemMgrs.push_back(std::move(MemMgr));
347 
348  // Erase SrcKey entry using value rather than iterator I: I may have been
349  // invalidated when we looked up DstKey.
350  MemMgrs.erase(SrcKey);
351  }
352 }
353 
354 } // End namespace orc.
355 } // 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:520
llvm::AArch64CC::LO
@ LO
Definition: AArch64BaseInfo.h:258
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
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::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
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:172
llvm::orc::ExecutionSession::registerResourceManager
void registerResourceManager(ResourceManager &RM)
Register the given ResourceManager with this ExecutionSession.
Definition: Core.cpp:1881
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::object::SymbolRef::ST_File
@ ST_File
Definition: ObjectFile.h:175
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:207
llvm::Lock
static sys::Mutex Lock
Definition: NVPTXUtilities.cpp:39
llvm::Resolver
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:2013
llvm::orc::tpctypes::LookupResult
std::vector< JITTargetAddress > LookupResult
Definition: TargetProcessControlTypes.h:162
llvm::orc
Definition: CompileOnDemandLayer.h:57
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::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:179
RTDyldObjectLinkingLayer.h
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:206
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:1620
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:59
llvm::object::BasicSymbolRef::SF_Undefined
@ SF_Undefined
Definition: SymbolicFile.h:108
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:1665
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:186
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::JITEventListener
JITEventListener - Abstract interface for use by the JIT to notify clients about significant events d...
Definition: JITEventListener.h:41
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:747
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::pointerToJITTargetAddress
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Convert a pointer to a JITTargetAddress.
Definition: JITSymbol.h:69
llvm::DenseMapBase::empty
LLVM_NODISCARD bool empty() const
Definition: DenseMap.h:97
llvm::JITSymbolResolver
Symbol resolution interface.
Definition: JITSymbol.h:371
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::object::OwningBinary
Definition: RuntimeDyld.h:36
llvm::DenseMapBase::end
iterator end()
Definition: DenseMap.h:83
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:157
llvm::orc::ExecutionSession
An ExecutionSession represents a running JIT program.
Definition: Core.h:1346
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:599
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:109
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:104
llvm::orc::SymbolState::Resolved
@ Resolved
Queried, materialization begun.
llvm::RuntimeDyld::MemoryManager
Memory Management.
Definition: RuntimeDyld.h:92