MachOPlatform.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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. struct MachOJITDylibInitializers {
  30. using SectionList = std::vector<ExecutorAddrRange>;
  31. MachOJITDylibInitializers(std::string Name, ExecutorAddr MachOHeaderAddress)
  32. : Name(std::move(Name)),
  33. MachOHeaderAddress(std::move(MachOHeaderAddress)) {}
  34. std::string Name;
  35. ExecutorAddr MachOHeaderAddress;
  36. ExecutorAddr ObjCImageInfoAddress;
  37. StringMap<SectionList> InitSections;
  38. };
  39. class MachOJITDylibDeinitializers {};
  40. using MachOJITDylibInitializerSequence = std::vector<MachOJITDylibInitializers>;
  41. using MachOJITDylibDeinitializerSequence =
  42. std::vector<MachOJITDylibDeinitializers>;
  43. /// Mediates between MachO initialization and ExecutionSession state.
  44. class MachOPlatform : public Platform {
  45. public:
  46. /// Try to create a MachOPlatform instance, adding the ORC runtime to the
  47. /// given JITDylib.
  48. ///
  49. /// The ORC runtime requires access to a number of symbols in libc++, and
  50. /// requires access to symbols in libobjc, and libswiftCore to support
  51. /// Objective-C and Swift code. It is up to the caller to ensure that the
  52. /// requried symbols can be referenced by code added to PlatformJD. The
  53. /// standard way to achieve this is to first attach dynamic library search
  54. /// generators for either the given process, or for the specific required
  55. /// libraries, to PlatformJD, then to create the platform instance:
  56. ///
  57. /// \code{.cpp}
  58. /// auto &PlatformJD = ES.createBareJITDylib("stdlib");
  59. /// PlatformJD.addGenerator(
  60. /// ExitOnErr(EPCDynamicLibrarySearchGenerator
  61. /// ::GetForTargetProcess(EPC)));
  62. /// ES.setPlatform(
  63. /// ExitOnErr(MachOPlatform::Create(ES, ObjLayer, EPC, PlatformJD,
  64. /// "/path/to/orc/runtime")));
  65. /// \endcode
  66. ///
  67. /// Alternatively, these symbols could be added to another JITDylib that
  68. /// PlatformJD links against.
  69. ///
  70. /// Clients are also responsible for ensuring that any JIT'd code that
  71. /// depends on runtime functions (including any code using TLV or static
  72. /// destructors) can reference the runtime symbols. This is usually achieved
  73. /// by linking any JITDylibs containing regular code against
  74. /// PlatformJD.
  75. ///
  76. /// By default, MachOPlatform will add the set of aliases returned by the
  77. /// standardPlatformAliases function. This includes both required aliases
  78. /// (e.g. __cxa_atexit -> __orc_rt_macho_cxa_atexit for static destructor
  79. /// support), and optional aliases that provide JIT versions of common
  80. /// functions (e.g. dlopen -> __orc_rt_macho_jit_dlopen). Clients can
  81. /// override these defaults by passing a non-None value for the
  82. /// RuntimeAliases function, in which case the client is responsible for
  83. /// setting up all aliases (including the required ones).
  84. static Expected<std::unique_ptr<MachOPlatform>>
  85. Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  86. JITDylib &PlatformJD, const char *OrcRuntimePath,
  87. Optional<SymbolAliasMap> RuntimeAliases = None);
  88. ExecutionSession &getExecutionSession() const { return ES; }
  89. ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
  90. Error setupJITDylib(JITDylib &JD) override;
  91. Error teardownJITDylib(JITDylib &JD) override;
  92. Error notifyAdding(ResourceTracker &RT,
  93. const MaterializationUnit &MU) override;
  94. Error notifyRemoving(ResourceTracker &RT) override;
  95. /// Returns an AliasMap containing the default aliases for the MachOPlatform.
  96. /// This can be modified by clients when constructing the platform to add
  97. /// or remove aliases.
  98. static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES);
  99. /// Returns the array of required CXX aliases.
  100. static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
  101. /// Returns the array of standard runtime utility aliases for MachO.
  102. static ArrayRef<std::pair<const char *, const char *>>
  103. standardRuntimeUtilityAliases();
  104. /// Returns true if the given section name is an initializer section.
  105. static bool isInitializerSection(StringRef SegName, StringRef SectName);
  106. private:
  107. // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
  108. // platform features including initializers, exceptions, TLV, and language
  109. // runtime registration.
  110. class MachOPlatformPlugin : public ObjectLinkingLayer::Plugin {
  111. public:
  112. MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {}
  113. void modifyPassConfig(MaterializationResponsibility &MR,
  114. jitlink::LinkGraph &G,
  115. jitlink::PassConfiguration &Config) override;
  116. SyntheticSymbolDependenciesMap
  117. getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override;
  118. // FIXME: We should be tentatively tracking scraped sections and discarding
  119. // if the MR fails.
  120. Error notifyFailed(MaterializationResponsibility &MR) override {
  121. return Error::success();
  122. }
  123. Error notifyRemovingResources(ResourceKey K) override {
  124. return Error::success();
  125. }
  126. void notifyTransferringResources(ResourceKey DstKey,
  127. ResourceKey SrcKey) override {}
  128. private:
  129. using InitSymbolDepMap =
  130. DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
  131. void addEHAndTLVSupportPasses(MaterializationResponsibility &MR,
  132. jitlink::PassConfiguration &Config);
  133. Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
  134. MaterializationResponsibility &MR);
  135. Error preserveInitSections(jitlink::LinkGraph &G,
  136. MaterializationResponsibility &MR);
  137. Error processObjCImageInfo(jitlink::LinkGraph &G,
  138. MaterializationResponsibility &MR);
  139. Error registerInitSections(jitlink::LinkGraph &G, JITDylib &JD);
  140. Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
  141. Error registerEHAndTLVSections(jitlink::LinkGraph &G);
  142. Error registerEHSectionsPhase1(jitlink::LinkGraph &G);
  143. std::mutex PluginMutex;
  144. MachOPlatform &MP;
  145. DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
  146. InitSymbolDepMap InitSymbolDeps;
  147. };
  148. using SendInitializerSequenceFn =
  149. unique_function<void(Expected<MachOJITDylibInitializerSequence>)>;
  150. using SendDeinitializerSequenceFn =
  151. unique_function<void(Expected<MachOJITDylibDeinitializerSequence>)>;
  152. using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
  153. static bool supportedTarget(const Triple &TT);
  154. MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  155. JITDylib &PlatformJD,
  156. std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
  157. Error &Err);
  158. // Associate MachOPlatform JIT-side runtime support functions with handlers.
  159. Error associateRuntimeSupportFunctions(JITDylib &PlatformJD);
  160. void getInitializersBuildSequencePhase(SendInitializerSequenceFn SendResult,
  161. JITDylib &JD,
  162. std::vector<JITDylibSP> DFSLinkOrder);
  163. void getInitializersLookupPhase(SendInitializerSequenceFn SendResult,
  164. JITDylib &JD);
  165. void rt_getInitializers(SendInitializerSequenceFn SendResult,
  166. StringRef JDName);
  167. void rt_getDeinitializers(SendDeinitializerSequenceFn SendResult,
  168. ExecutorAddr Handle);
  169. void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle,
  170. StringRef SymbolName);
  171. // Records the addresses of runtime symbols used by the platform.
  172. Error bootstrapMachORuntime(JITDylib &PlatformJD);
  173. Error registerInitInfo(JITDylib &JD, ExecutorAddr ObjCImageInfoAddr,
  174. ArrayRef<jitlink::Section *> InitSections);
  175. Expected<uint64_t> createPThreadKey();
  176. enum PlatformState { BootstrapPhase1, BootstrapPhase2, Initialized };
  177. ExecutionSession &ES;
  178. ObjectLinkingLayer &ObjLinkingLayer;
  179. SymbolStringPtr MachOHeaderStartSymbol;
  180. std::atomic<PlatformState> State{BootstrapPhase1};
  181. ExecutorAddr orc_rt_macho_platform_bootstrap;
  182. ExecutorAddr orc_rt_macho_platform_shutdown;
  183. ExecutorAddr orc_rt_macho_register_ehframe_section;
  184. ExecutorAddr orc_rt_macho_deregister_ehframe_section;
  185. ExecutorAddr orc_rt_macho_register_thread_data_section;
  186. ExecutorAddr orc_rt_macho_deregister_thread_data_section;
  187. ExecutorAddr orc_rt_macho_create_pthread_key;
  188. DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
  189. // InitSeqs gets its own mutex to avoid locking the whole session when
  190. // aggregating data from the jitlink.
  191. std::mutex PlatformMutex;
  192. DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;
  193. DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
  194. DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
  195. };
  196. namespace shared {
  197. using SPSNamedExecutorAddrRangeSequenceMap =
  198. SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRangeSequence>>;
  199. using SPSMachOJITDylibInitializers =
  200. SPSTuple<SPSString, SPSExecutorAddr, SPSExecutorAddr,
  201. SPSNamedExecutorAddrRangeSequenceMap>;
  202. using SPSMachOJITDylibInitializerSequence =
  203. SPSSequence<SPSMachOJITDylibInitializers>;
  204. /// Serialization traits for MachOJITDylibInitializers.
  205. template <>
  206. class SPSSerializationTraits<SPSMachOJITDylibInitializers,
  207. MachOJITDylibInitializers> {
  208. public:
  209. static size_t size(const MachOJITDylibInitializers &MOJDIs) {
  210. return SPSMachOJITDylibInitializers::AsArgList::size(
  211. MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.ObjCImageInfoAddress,
  212. MOJDIs.InitSections);
  213. }
  214. static bool serialize(SPSOutputBuffer &OB,
  215. const MachOJITDylibInitializers &MOJDIs) {
  216. return SPSMachOJITDylibInitializers::AsArgList::serialize(
  217. OB, MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.ObjCImageInfoAddress,
  218. MOJDIs.InitSections);
  219. }
  220. static bool deserialize(SPSInputBuffer &IB,
  221. MachOJITDylibInitializers &MOJDIs) {
  222. return SPSMachOJITDylibInitializers::AsArgList::deserialize(
  223. IB, MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.ObjCImageInfoAddress,
  224. MOJDIs.InitSections);
  225. }
  226. };
  227. using SPSMachOJITDylibDeinitializers = SPSEmpty;
  228. using SPSMachOJITDylibDeinitializerSequence =
  229. SPSSequence<SPSMachOJITDylibDeinitializers>;
  230. template <>
  231. class SPSSerializationTraits<SPSMachOJITDylibDeinitializers,
  232. MachOJITDylibDeinitializers> {
  233. public:
  234. static size_t size(const MachOJITDylibDeinitializers &MOJDDs) { return 0; }
  235. static bool serialize(SPSOutputBuffer &OB,
  236. const MachOJITDylibDeinitializers &MOJDDs) {
  237. return true;
  238. }
  239. static bool deserialize(SPSInputBuffer &IB,
  240. MachOJITDylibDeinitializers &MOJDDs) {
  241. MOJDDs = MachOJITDylibDeinitializers();
  242. return true;
  243. }
  244. };
  245. } // end namespace shared
  246. } // end namespace orc
  247. } // end namespace llvm
  248. #endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
  249. #ifdef __GNUC__
  250. #pragma GCC diagnostic pop
  251. #endif