MachOPlatform.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- MachOPlatform.h - Utilities for executing MachO in Orc --*- 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. // Utilities for executing JIT'd MachO in Orc.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
  18. #define LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
  19. #include "llvm/ADT/StringRef.h"
  20. #include "llvm/ExecutionEngine/Orc/Core.h"
  21. #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
  22. #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
  23. #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
  24. #include <future>
  25. #include <thread>
  26. #include <vector>
  27. namespace llvm {
  28. namespace orc {
  29. /// Mediates between MachO initialization and ExecutionSession state.
  30. class MachOPlatform : public Platform {
  31. public:
  32. // Used internally by MachOPlatform, but made public to enable serialization.
  33. struct MachOJITDylibDepInfo {
  34. bool Sealed = false;
  35. std::vector<ExecutorAddr> DepHeaders;
  36. };
  37. // Used internally by MachOPlatform, but made public to enable serialization.
  38. using MachOJITDylibDepInfoMap =
  39. std::vector<std::pair<ExecutorAddr, MachOJITDylibDepInfo>>;
  40. /// Try to create a MachOPlatform instance, adding the ORC runtime to the
  41. /// given JITDylib.
  42. ///
  43. /// The ORC runtime requires access to a number of symbols in libc++, and
  44. /// requires access to symbols in libobjc, and libswiftCore to support
  45. /// Objective-C and Swift code. It is up to the caller to ensure that the
  46. /// requried symbols can be referenced by code added to PlatformJD. The
  47. /// standard way to achieve this is to first attach dynamic library search
  48. /// generators for either the given process, or for the specific required
  49. /// libraries, to PlatformJD, then to create the platform instance:
  50. ///
  51. /// \code{.cpp}
  52. /// auto &PlatformJD = ES.createBareJITDylib("stdlib");
  53. /// PlatformJD.addGenerator(
  54. /// ExitOnErr(EPCDynamicLibrarySearchGenerator
  55. /// ::GetForTargetProcess(EPC)));
  56. /// ES.setPlatform(
  57. /// ExitOnErr(MachOPlatform::Create(ES, ObjLayer, EPC, PlatformJD,
  58. /// "/path/to/orc/runtime")));
  59. /// \endcode
  60. ///
  61. /// Alternatively, these symbols could be added to another JITDylib that
  62. /// PlatformJD links against.
  63. ///
  64. /// Clients are also responsible for ensuring that any JIT'd code that
  65. /// depends on runtime functions (including any code using TLV or static
  66. /// destructors) can reference the runtime symbols. This is usually achieved
  67. /// by linking any JITDylibs containing regular code against
  68. /// PlatformJD.
  69. ///
  70. /// By default, MachOPlatform will add the set of aliases returned by the
  71. /// standardPlatformAliases function. This includes both required aliases
  72. /// (e.g. __cxa_atexit -> __orc_rt_macho_cxa_atexit for static destructor
  73. /// support), and optional aliases that provide JIT versions of common
  74. /// functions (e.g. dlopen -> __orc_rt_macho_jit_dlopen). Clients can
  75. /// override these defaults by passing a non-None value for the
  76. /// RuntimeAliases function, in which case the client is responsible for
  77. /// setting up all aliases (including the required ones).
  78. static Expected<std::unique_ptr<MachOPlatform>>
  79. Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  80. JITDylib &PlatformJD, const char *OrcRuntimePath,
  81. std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
  82. ExecutionSession &getExecutionSession() const { return ES; }
  83. ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
  84. Error setupJITDylib(JITDylib &JD) override;
  85. Error teardownJITDylib(JITDylib &JD) override;
  86. Error notifyAdding(ResourceTracker &RT,
  87. const MaterializationUnit &MU) override;
  88. Error notifyRemoving(ResourceTracker &RT) override;
  89. /// Returns an AliasMap containing the default aliases for the MachOPlatform.
  90. /// This can be modified by clients when constructing the platform to add
  91. /// or remove aliases.
  92. static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES);
  93. /// Returns the array of required CXX aliases.
  94. static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
  95. /// Returns the array of standard runtime utility aliases for MachO.
  96. static ArrayRef<std::pair<const char *, const char *>>
  97. standardRuntimeUtilityAliases();
  98. /// Returns true if the given section name is an initializer section.
  99. static bool isInitializerSection(StringRef SegName, StringRef SectName);
  100. private:
  101. // Data needed for bootstrap only.
  102. struct BootstrapInfo {
  103. std::mutex Mutex;
  104. std::condition_variable CV;
  105. size_t ActiveGraphs = 0;
  106. shared::AllocActions DeferredAAs;
  107. ExecutorAddr MachOHeaderAddr;
  108. };
  109. // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
  110. // platform features including initializers, exceptions, TLV, and language
  111. // runtime registration.
  112. class MachOPlatformPlugin : public ObjectLinkingLayer::Plugin {
  113. public:
  114. MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {}
  115. void modifyPassConfig(MaterializationResponsibility &MR,
  116. jitlink::LinkGraph &G,
  117. jitlink::PassConfiguration &Config) override;
  118. SyntheticSymbolDependenciesMap
  119. getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override;
  120. // FIXME: We should be tentatively tracking scraped sections and discarding
  121. // if the MR fails.
  122. Error notifyFailed(MaterializationResponsibility &MR) override {
  123. return Error::success();
  124. }
  125. Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
  126. return Error::success();
  127. }
  128. void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
  129. ResourceKey SrcKey) override {}
  130. private:
  131. using InitSymbolDepMap =
  132. DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
  133. struct UnwindSections {
  134. SmallVector<ExecutorAddrRange> CodeRanges;
  135. ExecutorAddrRange DwarfSection;
  136. ExecutorAddrRange CompactUnwindSection;
  137. };
  138. Error bootstrapPipelineStart(jitlink::LinkGraph &G);
  139. Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
  140. Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
  141. Error recordRuntimeRegistrationFunctions(jitlink::LinkGraph &G);
  142. Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
  143. MaterializationResponsibility &MR);
  144. Error preserveInitSections(jitlink::LinkGraph &G,
  145. MaterializationResponsibility &MR);
  146. Error processObjCImageInfo(jitlink::LinkGraph &G,
  147. MaterializationResponsibility &MR);
  148. Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
  149. std::optional<UnwindSections> findUnwindSectionInfo(jitlink::LinkGraph &G);
  150. Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD,
  151. bool InBootstrapPhase);
  152. std::mutex PluginMutex;
  153. MachOPlatform &MP;
  154. // FIXME: ObjCImageInfos and HeaderAddrs need to be cleared when
  155. // JITDylibs are removed.
  156. DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
  157. DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
  158. InitSymbolDepMap InitSymbolDeps;
  159. };
  160. using GetJITDylibHeaderSendResultFn =
  161. unique_function<void(Expected<ExecutorAddr>)>;
  162. using GetJITDylibNameSendResultFn =
  163. unique_function<void(Expected<StringRef>)>;
  164. using PushInitializersSendResultFn =
  165. unique_function<void(Expected<MachOJITDylibDepInfoMap>)>;
  166. using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
  167. static bool supportedTarget(const Triple &TT);
  168. MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  169. JITDylib &PlatformJD,
  170. std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
  171. Error &Err);
  172. // Associate MachOPlatform JIT-side runtime support functions with handlers.
  173. Error associateRuntimeSupportFunctions();
  174. // Implements rt_pushInitializers by making repeat async lookups for
  175. // initializer symbols (each lookup may spawn more initializer symbols if
  176. // it pulls in new materializers, e.g. from objects in a static library).
  177. void pushInitializersLoop(PushInitializersSendResultFn SendResult,
  178. JITDylibSP JD);
  179. // Handle requests from the ORC runtime to push MachO initializer info.
  180. void rt_pushInitializers(PushInitializersSendResultFn SendResult,
  181. ExecutorAddr JDHeaderAddr);
  182. // Handle requests for symbol addresses from the ORC runtime.
  183. void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle,
  184. StringRef SymbolName);
  185. // Call the ORC runtime to create a pthread key.
  186. Expected<uint64_t> createPThreadKey();
  187. ExecutionSession &ES;
  188. JITDylib &PlatformJD;
  189. ObjectLinkingLayer &ObjLinkingLayer;
  190. SymbolStringPtr MachOHeaderStartSymbol = ES.intern("___dso_handle");
  191. struct RuntimeFunction {
  192. RuntimeFunction(SymbolStringPtr Name) : Name(std::move(Name)) {}
  193. SymbolStringPtr Name;
  194. ExecutorAddr Addr;
  195. };
  196. RuntimeFunction PlatformBootstrap{
  197. ES.intern("___orc_rt_macho_platform_bootstrap")};
  198. RuntimeFunction PlatformShutdown{
  199. ES.intern("___orc_rt_macho_platform_shutdown")};
  200. RuntimeFunction RegisterEHFrameSection{
  201. ES.intern("___orc_rt_macho_register_ehframe_section")};
  202. RuntimeFunction DeregisterEHFrameSection{
  203. ES.intern("___orc_rt_macho_deregister_ehframe_section")};
  204. RuntimeFunction RegisterJITDylib{
  205. ES.intern("___orc_rt_macho_register_jitdylib")};
  206. RuntimeFunction DeregisterJITDylib{
  207. ES.intern("___orc_rt_macho_deregister_jitdylib")};
  208. RuntimeFunction RegisterObjectPlatformSections{
  209. ES.intern("___orc_rt_macho_register_object_platform_sections")};
  210. RuntimeFunction DeregisterObjectPlatformSections{
  211. ES.intern("___orc_rt_macho_deregister_object_platform_sections")};
  212. RuntimeFunction CreatePThreadKey{
  213. ES.intern("___orc_rt_macho_create_pthread_key")};
  214. DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
  215. std::mutex PlatformMutex;
  216. DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
  217. DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
  218. DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
  219. std::atomic<BootstrapInfo *> Bootstrap;
  220. };
  221. namespace shared {
  222. using SPSNamedExecutorAddrRangeSequence =
  223. SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
  224. } // end namespace shared
  225. } // end namespace orc
  226. } // end namespace llvm
  227. #endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
  228. #ifdef __GNUC__
  229. #pragma GCC diagnostic pop
  230. #endif