LLVM  12.0.0git
LazyReexports.cpp
Go to the documentation of this file.
1 //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
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 
11 #include "llvm/ADT/Triple.h"
13 
14 #define DEBUG_TYPE "orc"
15 
16 namespace llvm {
17 namespace orc {
18 
20  ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP)
21  : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}
22 
25  NotifyResolvedFunction NotifyResolved) {
26  assert(TP && "TrampolinePool not set");
27 
28  std::lock_guard<std::mutex> Lock(LCTMMutex);
29  auto Trampoline = TP->getTrampoline();
30 
31  if (!Trampoline)
32  return Trampoline.takeError();
33 
34  Reexports[*Trampoline] = ReexportsEntry{&SourceJD, std::move(SymbolName)};
35  Notifiers[*Trampoline] = std::move(NotifyResolved);
36  return *Trampoline;
37 }
38 
40  ES.reportError(std::move(Err));
41  return ErrorHandlerAddr;
42 }
43 
46  std::lock_guard<std::mutex> Lock(LCTMMutex);
47  auto I = Reexports.find(TrampolineAddr);
48  if (I == Reexports.end())
50  "Missing reexport for trampoline address %p",
51  TrampolineAddr);
52  return I->second;
53 }
54 
56  JITTargetAddress ResolvedAddr) {
57  NotifyResolvedFunction NotifyResolved;
58  {
59  std::lock_guard<std::mutex> Lock(LCTMMutex);
60  auto I = Notifiers.find(TrampolineAddr);
61  if (I != Notifiers.end()) {
62  NotifyResolved = std::move(I->second);
63  Notifiers.erase(I);
64  }
65  }
66 
67  return NotifyResolved ? NotifyResolved(ResolvedAddr) : Error::success();
68 }
69 
71  JITTargetAddress TrampolineAddr,
72  NotifyLandingResolvedFunction NotifyLandingResolved) {
73 
74  auto Entry = findReexport(TrampolineAddr);
75  if (!Entry)
76  return NotifyLandingResolved(reportCallThroughError(Entry.takeError()));
77 
78  // Declaring SLS outside of the call to ES.lookup is a workaround to fix build
79  // failures on AIX and on z/OS platforms.
80  SymbolLookupSet SLS({Entry->SymbolName});
81 
82  ES.lookup(
84  makeJITDylibSearchOrder(Entry->SourceJD,
86  std::move(SLS), SymbolState::Ready,
87  [this, TrampolineAddr, SymbolName = Entry->SymbolName,
88  NotifyLandingResolved = std::move(NotifyLandingResolved)](
89  Expected<SymbolMap> Result) mutable {
90  if (Result) {
91  assert(Result->size() == 1 && "Unexpected result size");
92  assert(Result->count(SymbolName) && "Unexpected result value");
93  JITTargetAddress LandingAddr = (*Result)[SymbolName].getAddress();
94 
95  if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
96  NotifyLandingResolved(reportCallThroughError(std::move(Err)));
97  else
98  NotifyLandingResolved(LandingAddr);
99  } else
100  NotifyLandingResolved(reportCallThroughError(Result.takeError()));
101  },
103 }
104 
107  JITTargetAddress ErrorHandlerAddr) {
108  switch (T.getArch()) {
109  default:
110  return make_error<StringError>(
111  std::string("No callback manager available for ") + T.str(),
113 
114  case Triple::aarch64:
115  case Triple::aarch64_32:
116  return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
117  ErrorHandlerAddr);
118 
119  case Triple::x86:
120  return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
121 
122  case Triple::mips:
123  return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
124  ErrorHandlerAddr);
125 
126  case Triple::mipsel:
127  return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
128  ErrorHandlerAddr);
129 
130  case Triple::mips64:
131  case Triple::mips64el:
132  return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
133 
134  case Triple::x86_64:
135  if (T.getOS() == Triple::OSType::Win32)
136  return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
137  ES, ErrorHandlerAddr);
138  else
139  return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
140  ES, ErrorHandlerAddr);
141  }
142 }
143 
145  LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
146  JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc,
147  VModuleKey K)
148  : MaterializationUnit(extractFlags(CallableAliases), nullptr, std::move(K)),
149  LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
150  CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}
151 
153  return "<Lazy Reexports>";
154 }
155 
156 void LazyReexportsMaterializationUnit::materialize(
158  auto RequestedSymbols = R.getRequestedSymbols();
159 
160  SymbolAliasMap RequestedAliases;
161  for (auto &RequestedSymbol : RequestedSymbols) {
162  auto I = CallableAliases.find(RequestedSymbol);
163  assert(I != CallableAliases.end() && "Symbol not found in alias map?");
164  RequestedAliases[I->first] = std::move(I->second);
165  CallableAliases.erase(I);
166  }
167 
168  if (!CallableAliases.empty())
169  R.replace(lazyReexports(LCTManager, ISManager, SourceJD,
170  std::move(CallableAliases), AliaseeTable));
171 
173  for (auto &Alias : RequestedAliases) {
174 
175  auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
176  SourceJD, Alias.second.Aliasee,
177  [&ISManager = this->ISManager,
178  StubSym = Alias.first](JITTargetAddress ResolvedAddr) -> Error {
179  return ISManager.updatePointer(*StubSym, ResolvedAddr);
180  });
181 
182  if (!CallThroughTrampoline) {
183  SourceJD.getExecutionSession().reportError(
184  CallThroughTrampoline.takeError());
186  return;
187  }
188 
189  StubInits[*Alias.first] =
190  std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
191  }
192 
193  if (AliaseeTable != nullptr && !RequestedAliases.empty())
194  AliaseeTable->trackImpls(RequestedAliases, &SourceJD);
195 
196  if (auto Err = ISManager.createStubs(StubInits)) {
197  SourceJD.getExecutionSession().reportError(std::move(Err));
199  return;
200  }
201 
202  SymbolMap Stubs;
203  for (auto &Alias : RequestedAliases)
204  Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
205 
206  // No registered dependencies, so these calls cannot fail.
207  cantFail(R.notifyResolved(Stubs));
208  cantFail(R.notifyEmitted());
209 }
210 
211 void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
212  const SymbolStringPtr &Name) {
213  assert(CallableAliases.count(Name) &&
214  "Symbol not covered by this MaterializationUnit");
215  CallableAliases.erase(Name);
216 }
217 
219 LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
221  for (auto &KV : Aliases) {
222  assert(KV.second.AliasFlags.isCallable() &&
223  "Lazy re-exports must be callable symbols");
224  SymbolFlags[KV.first] = KV.second.AliasFlags;
225  }
226  return SymbolFlags;
227 }
228 
229 } // End namespace orc.
230 } // End namespace llvm.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:708
Base class for managing collections of named indirect stubs.
Error notifyEmitted()
Notifies the target JITDylib (and any pending queries on that JITDylib) that all symbols covered by t...
Definition: Core.cpp:213
This class represents lattice values for constants.
Definition: AllocatorList.h:23
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
LazyCallThroughManager(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP)
OSType getOS() const
getOS - Get the parsed operating system type of this triple.
Definition: Triple.h:309
void replace(std::unique_ptr< MaterializationUnit > MU)
Transfers responsibility to the given MaterializationUnit for all symbols defined by that Materializa...
Definition: Core.cpp:258
Expected< JITTargetAddress > getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName, NotifyResolvedFunction NotifyResolved)
static sys::Mutex Lock
LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc, VModuleKey K)
Error takeError()
Take ownership of the stored error.
Definition: Error.h:557
JITTargetAddress reportCallThroughError(Error Err)
virtual Expected< JITTargetAddress > getTrampoline()=0
Get an available trampoline address.
Definition: BitVector.h:959
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
void resolveTrampolineLandingAddress(JITTargetAddress TrampolineAddr, TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved)
SymbolFlagsMap SymbolFlags
Definition: Core.h:590
Base class for pools of compiler re-entry trampolines.
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:410
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Definition: Triple.h:300
StringRef getName() const override
Return the name of this materialization unit.
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:42
void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD)
Definition: Speculation.cpp:28
ExecutionSession & getExecutionSession() const
Get a reference to the ExecutionSession for this JITDylib.
Definition: Core.h:814
const std::string & str() const
Definition: Triple.h:369
Pointer to a pooled string representing a symbol name.
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
bool erase(const KeyT &Val)
Definition: DenseMap.h:302
std::unique_ptr< LazyReexportsMaterializationUnit > lazyReexports(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc=nullptr, VModuleKey K=VModuleKey())
Define lazy-reexports based on the given SymbolAliasMap.
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib *> JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
Definition: Core.h:96
Error notifyResolved(const SymbolMap &Symbols)
Notifies the target JITDylib that the given symbols have been resolved.
Definition: Core.cpp:193
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group...
Definition: Core.h:552
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
Expected< std::unique_ptr< LazyCallThroughManager > > createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr)
Create a LocalLazyCallThroughManager from the given triple and execution session. ...
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:113
Emitted to memory, but waiting on transitive dependencies.
unique_function is a type-erasing functor similar to std::function.
SymbolNameSet getRequestedSymbols() const
Returns the names of any symbols covered by this MaterializationResponsibility object that have queri...
Definition: Core.cpp:189
An ExecutionSession represents a running JIT program.
Definition: Core.h:1088
Error notifyResolved(JITTargetAddress TrampolineAddr, JITTargetAddress ResolvedAddr)
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:106
void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, SymbolLookupSet Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies)
Search the given JITDylib list for the given symbols.
Definition: Core.cpp:1887
Expected< ReexportsEntry > findReexport(JITTargetAddress TrampolineAddr)
uint8_t uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:40
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:1170
#define I(x, y, z)
Definition: MD5.cpp:59
iterator end()
Definition: DenseMap.h:83
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:145
LLVM_NODISCARD bool empty() const
Definition: DenseMap.h:97
virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly)=0
Find the stub with the given name.
virtual Error createStubs(const StubInitsMap &StubInits)=0
Create StubInits.size() stubs with the given names, target addresses, and flags.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void failMaterialization()
Notify all not-yet-emitted covered by this MaterializationResponsibility instance that an error has o...
Definition: Core.cpp:242
Manages a set of &#39;lazy call-through&#39; trampolines.
Definition: LazyReexports.h:38
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
Definition: Core.cpp:32
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1202
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:779
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77