TPCIndirectionUtils.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- TPCIndirectionUtils.h - TPC based indirection utils ----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Indirection utilities (stubs, trampolines, lazy call-throughs) that use the
  15. // TargetProcessControl API to interact with the target process.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H
  19. #define LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H
  20. #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
  21. #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
  22. #include "llvm/ExecutionEngine/Orc/LazyReexports.h"
  23. #include <mutex>
  24. namespace llvm {
  25. namespace orc {
  26. class TargetProcessControl;
  27. /// Provides TargetProcessControl based indirect stubs, trampoline pool and
  28. /// lazy call through manager.
  29. class TPCIndirectionUtils {
  30. friend class TPCIndirectionUtilsAccess;
  31. public:
  32. /// ABI support base class. Used to write resolver, stub, and trampoline
  33. /// blocks.
  34. class ABISupport {
  35. protected:
  36. ABISupport(unsigned PointerSize, unsigned TrampolineSize, unsigned StubSize,
  37. unsigned StubToPointerMaxDisplacement, unsigned ResolverCodeSize)
  38. : PointerSize(PointerSize), TrampolineSize(TrampolineSize),
  39. StubSize(StubSize),
  40. StubToPointerMaxDisplacement(StubToPointerMaxDisplacement),
  41. ResolverCodeSize(ResolverCodeSize) {}
  42. public:
  43. virtual ~ABISupport();
  44. unsigned getPointerSize() const { return PointerSize; }
  45. unsigned getTrampolineSize() const { return TrampolineSize; }
  46. unsigned getStubSize() const { return StubSize; }
  47. unsigned getStubToPointerMaxDisplacement() const {
  48. return StubToPointerMaxDisplacement;
  49. }
  50. unsigned getResolverCodeSize() const { return ResolverCodeSize; }
  51. virtual void writeResolverCode(char *ResolverWorkingMem,
  52. JITTargetAddress ResolverTargetAddr,
  53. JITTargetAddress ReentryFnAddr,
  54. JITTargetAddress ReentryCtxAddr) const = 0;
  55. virtual void writeTrampolines(char *TrampolineBlockWorkingMem,
  56. JITTargetAddress TrampolineBlockTragetAddr,
  57. JITTargetAddress ResolverAddr,
  58. unsigned NumTrampolines) const = 0;
  59. virtual void
  60. writeIndirectStubsBlock(char *StubsBlockWorkingMem,
  61. JITTargetAddress StubsBlockTargetAddress,
  62. JITTargetAddress PointersBlockTargetAddress,
  63. unsigned NumStubs) const = 0;
  64. private:
  65. unsigned PointerSize = 0;
  66. unsigned TrampolineSize = 0;
  67. unsigned StubSize = 0;
  68. unsigned StubToPointerMaxDisplacement = 0;
  69. unsigned ResolverCodeSize = 0;
  70. };
  71. /// Create using the given ABI class.
  72. template <typename ORCABI>
  73. static std::unique_ptr<TPCIndirectionUtils>
  74. CreateWithABI(TargetProcessControl &TPC);
  75. /// Create based on the TargetProcessControl triple.
  76. static Expected<std::unique_ptr<TPCIndirectionUtils>>
  77. Create(TargetProcessControl &TPC);
  78. /// Return a reference to the TargetProcessControl object.
  79. TargetProcessControl &getTargetProcessControl() const { return TPC; }
  80. /// Return a reference to the ABISupport object for this instance.
  81. ABISupport &getABISupport() const { return *ABI; }
  82. /// Release memory for resources held by this instance. This *must* be called
  83. /// prior to destruction of the class.
  84. Error cleanup();
  85. /// Write resolver code to the target process and return its address.
  86. /// This must be called before any call to createTrampolinePool or
  87. /// createLazyCallThroughManager.
  88. Expected<JITTargetAddress>
  89. writeResolverBlock(JITTargetAddress ReentryFnAddr,
  90. JITTargetAddress ReentryCtxAddr);
  91. /// Returns the address of the Resolver block. Returns zero if the
  92. /// writeResolverBlock method has not previously been called.
  93. JITTargetAddress getResolverBlockAddress() const { return ResolverBlockAddr; }
  94. /// Create an IndirectStubsManager for the target process.
  95. std::unique_ptr<IndirectStubsManager> createIndirectStubsManager();
  96. /// Create a TrampolinePool for the target process.
  97. TrampolinePool &getTrampolinePool();
  98. /// Create a LazyCallThroughManager.
  99. /// This function should only be called once.
  100. LazyCallThroughManager &
  101. createLazyCallThroughManager(ExecutionSession &ES,
  102. JITTargetAddress ErrorHandlerAddr);
  103. /// Create a LazyCallThroughManager for the target process.
  104. LazyCallThroughManager &getLazyCallThroughManager() {
  105. assert(LCTM && "createLazyCallThroughManager must be called first");
  106. return *LCTM;
  107. }
  108. private:
  109. using Allocation = jitlink::JITLinkMemoryManager::Allocation;
  110. struct IndirectStubInfo {
  111. IndirectStubInfo() = default;
  112. IndirectStubInfo(JITTargetAddress StubAddress,
  113. JITTargetAddress PointerAddress)
  114. : StubAddress(StubAddress), PointerAddress(PointerAddress) {}
  115. JITTargetAddress StubAddress = 0;
  116. JITTargetAddress PointerAddress = 0;
  117. };
  118. using IndirectStubInfoVector = std::vector<IndirectStubInfo>;
  119. /// Create a TPCIndirectionUtils instance.
  120. TPCIndirectionUtils(TargetProcessControl &TPC,
  121. std::unique_ptr<ABISupport> ABI);
  122. Expected<IndirectStubInfoVector> getIndirectStubs(unsigned NumStubs);
  123. std::mutex TPCUIMutex;
  124. TargetProcessControl &TPC;
  125. std::unique_ptr<ABISupport> ABI;
  126. JITTargetAddress ResolverBlockAddr;
  127. std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation> ResolverBlock;
  128. std::unique_ptr<TrampolinePool> TP;
  129. std::unique_ptr<LazyCallThroughManager> LCTM;
  130. std::vector<IndirectStubInfo> AvailableIndirectStubs;
  131. std::vector<std::unique_ptr<Allocation>> IndirectStubAllocs;
  132. };
  133. /// This will call writeResolver on the given TPCIndirectionUtils instance
  134. /// to set up re-entry via a function that will directly return the trampoline
  135. /// landing address.
  136. ///
  137. /// The TPCIndirectionUtils' LazyCallThroughManager must have been previously
  138. /// created via TPCIndirectionUtils::createLazyCallThroughManager.
  139. ///
  140. /// The TPCIndirectionUtils' writeResolver method must not have been previously
  141. /// called.
  142. ///
  143. /// This function is experimental and likely subject to revision.
  144. Error setUpInProcessLCTMReentryViaTPCIU(TPCIndirectionUtils &TPCIU);
  145. namespace detail {
  146. template <typename ORCABI>
  147. class ABISupportImpl : public TPCIndirectionUtils::ABISupport {
  148. public:
  149. ABISupportImpl()
  150. : ABISupport(ORCABI::PointerSize, ORCABI::TrampolineSize,
  151. ORCABI::StubSize, ORCABI::StubToPointerMaxDisplacement,
  152. ORCABI::ResolverCodeSize) {}
  153. void writeResolverCode(char *ResolverWorkingMem,
  154. JITTargetAddress ResolverTargetAddr,
  155. JITTargetAddress ReentryFnAddr,
  156. JITTargetAddress ReentryCtxAddr) const override {
  157. ORCABI::writeResolverCode(ResolverWorkingMem, ResolverTargetAddr,
  158. ReentryFnAddr, ReentryCtxAddr);
  159. }
  160. void writeTrampolines(char *TrampolineBlockWorkingMem,
  161. JITTargetAddress TrampolineBlockTargetAddr,
  162. JITTargetAddress ResolverAddr,
  163. unsigned NumTrampolines) const override {
  164. ORCABI::writeTrampolines(TrampolineBlockWorkingMem,
  165. TrampolineBlockTargetAddr, ResolverAddr,
  166. NumTrampolines);
  167. }
  168. void writeIndirectStubsBlock(char *StubsBlockWorkingMem,
  169. JITTargetAddress StubsBlockTargetAddress,
  170. JITTargetAddress PointersBlockTargetAddress,
  171. unsigned NumStubs) const override {
  172. ORCABI::writeIndirectStubsBlock(StubsBlockWorkingMem,
  173. StubsBlockTargetAddress,
  174. PointersBlockTargetAddress, NumStubs);
  175. }
  176. };
  177. } // end namespace detail
  178. template <typename ORCABI>
  179. std::unique_ptr<TPCIndirectionUtils>
  180. TPCIndirectionUtils::CreateWithABI(TargetProcessControl &TPC) {
  181. return std::unique_ptr<TPCIndirectionUtils>(new TPCIndirectionUtils(
  182. TPC, std::make_unique<detail::ABISupportImpl<ORCABI>>()));
  183. }
  184. } // end namespace orc
  185. } // end namespace llvm
  186. #endif // LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H
  187. #ifdef __GNUC__
  188. #pragma GCC diagnostic pop
  189. #endif