LazyReexports.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. #include "llvm/ExecutionEngine/Orc/LazyReexports.h"
  9. #include "llvm/ADT/Triple.h"
  10. #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
  11. #define DEBUG_TYPE "orc"
  12. namespace llvm {
  13. namespace orc {
  14. LazyCallThroughManager::LazyCallThroughManager(
  15. ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP)
  16. : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}
  17. Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
  18. JITDylib &SourceJD, SymbolStringPtr SymbolName,
  19. NotifyResolvedFunction NotifyResolved) {
  20. assert(TP && "TrampolinePool not set");
  21. std::lock_guard<std::mutex> Lock(LCTMMutex);
  22. auto Trampoline = TP->getTrampoline();
  23. if (!Trampoline)
  24. return Trampoline.takeError();
  25. Reexports[*Trampoline] = ReexportsEntry{&SourceJD, std::move(SymbolName)};
  26. Notifiers[*Trampoline] = std::move(NotifyResolved);
  27. return *Trampoline;
  28. }
  29. JITTargetAddress LazyCallThroughManager::reportCallThroughError(Error Err) {
  30. ES.reportError(std::move(Err));
  31. return ErrorHandlerAddr;
  32. }
  33. Expected<LazyCallThroughManager::ReexportsEntry>
  34. LazyCallThroughManager::findReexport(JITTargetAddress TrampolineAddr) {
  35. std::lock_guard<std::mutex> Lock(LCTMMutex);
  36. auto I = Reexports.find(TrampolineAddr);
  37. if (I == Reexports.end())
  38. return createStringError(inconvertibleErrorCode(),
  39. "Missing reexport for trampoline address %p",
  40. TrampolineAddr);
  41. return I->second;
  42. }
  43. Error LazyCallThroughManager::notifyResolved(JITTargetAddress TrampolineAddr,
  44. JITTargetAddress ResolvedAddr) {
  45. NotifyResolvedFunction NotifyResolved;
  46. {
  47. std::lock_guard<std::mutex> Lock(LCTMMutex);
  48. auto I = Notifiers.find(TrampolineAddr);
  49. if (I != Notifiers.end()) {
  50. NotifyResolved = std::move(I->second);
  51. Notifiers.erase(I);
  52. }
  53. }
  54. return NotifyResolved ? NotifyResolved(ResolvedAddr) : Error::success();
  55. }
  56. void LazyCallThroughManager::resolveTrampolineLandingAddress(
  57. JITTargetAddress TrampolineAddr,
  58. NotifyLandingResolvedFunction NotifyLandingResolved) {
  59. auto Entry = findReexport(TrampolineAddr);
  60. if (!Entry)
  61. return NotifyLandingResolved(reportCallThroughError(Entry.takeError()));
  62. // Declaring SLS and the callback outside of the call to ES.lookup is a
  63. // workaround to fix build failures on AIX and on z/OS platforms.
  64. SymbolLookupSet SLS({Entry->SymbolName});
  65. auto Callback = [this, TrampolineAddr, SymbolName = Entry->SymbolName,
  66. NotifyLandingResolved = std::move(NotifyLandingResolved)](
  67. Expected<SymbolMap> Result) mutable {
  68. if (Result) {
  69. assert(Result->size() == 1 && "Unexpected result size");
  70. assert(Result->count(SymbolName) && "Unexpected result value");
  71. JITTargetAddress LandingAddr = (*Result)[SymbolName].getAddress();
  72. if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
  73. NotifyLandingResolved(reportCallThroughError(std::move(Err)));
  74. else
  75. NotifyLandingResolved(LandingAddr);
  76. } else {
  77. NotifyLandingResolved(reportCallThroughError(Result.takeError()));
  78. }
  79. };
  80. ES.lookup(LookupKind::Static,
  81. makeJITDylibSearchOrder(Entry->SourceJD,
  82. JITDylibLookupFlags::MatchAllSymbols),
  83. std::move(SLS), SymbolState::Ready, std::move(Callback),
  84. NoDependenciesToRegister);
  85. }
  86. Expected<std::unique_ptr<LazyCallThroughManager>>
  87. createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
  88. JITTargetAddress ErrorHandlerAddr) {
  89. switch (T.getArch()) {
  90. default:
  91. return make_error<StringError>(
  92. std::string("No callback manager available for ") + T.str(),
  93. inconvertibleErrorCode());
  94. case Triple::aarch64:
  95. case Triple::aarch64_32:
  96. return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
  97. ErrorHandlerAddr);
  98. case Triple::x86:
  99. return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
  100. case Triple::mips:
  101. return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
  102. ErrorHandlerAddr);
  103. case Triple::mipsel:
  104. return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
  105. ErrorHandlerAddr);
  106. case Triple::mips64:
  107. case Triple::mips64el:
  108. return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
  109. case Triple::x86_64:
  110. if (T.getOS() == Triple::OSType::Win32)
  111. return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
  112. ES, ErrorHandlerAddr);
  113. else
  114. return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
  115. ES, ErrorHandlerAddr);
  116. }
  117. }
  118. LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
  119. LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
  120. JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)
  121. : MaterializationUnit(extractFlags(CallableAliases)),
  122. LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
  123. CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}
  124. StringRef LazyReexportsMaterializationUnit::getName() const {
  125. return "<Lazy Reexports>";
  126. }
  127. void LazyReexportsMaterializationUnit::materialize(
  128. std::unique_ptr<MaterializationResponsibility> R) {
  129. auto RequestedSymbols = R->getRequestedSymbols();
  130. SymbolAliasMap RequestedAliases;
  131. for (auto &RequestedSymbol : RequestedSymbols) {
  132. auto I = CallableAliases.find(RequestedSymbol);
  133. assert(I != CallableAliases.end() && "Symbol not found in alias map?");
  134. RequestedAliases[I->first] = std::move(I->second);
  135. CallableAliases.erase(I);
  136. }
  137. if (!CallableAliases.empty())
  138. if (auto Err = R->replace(lazyReexports(LCTManager, ISManager, SourceJD,
  139. std::move(CallableAliases),
  140. AliaseeTable))) {
  141. R->getExecutionSession().reportError(std::move(Err));
  142. R->failMaterialization();
  143. return;
  144. }
  145. IndirectStubsManager::StubInitsMap StubInits;
  146. for (auto &Alias : RequestedAliases) {
  147. auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
  148. SourceJD, Alias.second.Aliasee,
  149. [&ISManager = this->ISManager,
  150. StubSym = Alias.first](JITTargetAddress ResolvedAddr) -> Error {
  151. return ISManager.updatePointer(*StubSym, ResolvedAddr);
  152. });
  153. if (!CallThroughTrampoline) {
  154. SourceJD.getExecutionSession().reportError(
  155. CallThroughTrampoline.takeError());
  156. R->failMaterialization();
  157. return;
  158. }
  159. StubInits[*Alias.first] =
  160. std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
  161. }
  162. if (AliaseeTable != nullptr && !RequestedAliases.empty())
  163. AliaseeTable->trackImpls(RequestedAliases, &SourceJD);
  164. if (auto Err = ISManager.createStubs(StubInits)) {
  165. SourceJD.getExecutionSession().reportError(std::move(Err));
  166. R->failMaterialization();
  167. return;
  168. }
  169. SymbolMap Stubs;
  170. for (auto &Alias : RequestedAliases)
  171. Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
  172. // No registered dependencies, so these calls cannot fail.
  173. cantFail(R->notifyResolved(Stubs));
  174. cantFail(R->notifyEmitted());
  175. }
  176. void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
  177. const SymbolStringPtr &Name) {
  178. assert(CallableAliases.count(Name) &&
  179. "Symbol not covered by this MaterializationUnit");
  180. CallableAliases.erase(Name);
  181. }
  182. MaterializationUnit::Interface
  183. LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
  184. SymbolFlagsMap SymbolFlags;
  185. for (auto &KV : Aliases) {
  186. assert(KV.second.AliasFlags.isCallable() &&
  187. "Lazy re-exports must be callable symbols");
  188. SymbolFlags[KV.first] = KV.second.AliasFlags;
  189. }
  190. return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
  191. }
  192. } // End namespace orc.
  193. } // End namespace llvm.