COFFPlatform.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- COFFPlatform.h -- Utilities for executing COFF 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 COFF in Orc.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_EXECUTIONENGINE_ORC_COFFPLATFORM_H
  18. #define LLVM_EXECUTIONENGINE_ORC_COFFPLATFORM_H
  19. #include "llvm/ADT/StringRef.h"
  20. #include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
  21. #include "llvm/ExecutionEngine/Orc/Core.h"
  22. #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
  23. #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
  24. #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
  25. #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
  26. #include <future>
  27. #include <memory>
  28. #include <thread>
  29. #include <vector>
  30. namespace llvm {
  31. namespace orc {
  32. /// Mediates between COFF initialization and ExecutionSession state.
  33. class COFFPlatform : public Platform {
  34. public:
  35. /// A function that will be called with the name of dll file that must be
  36. /// loaded.
  37. using LoadDynamicLibrary =
  38. unique_function<Error(JITDylib &JD, StringRef DLLFileName)>;
  39. /// Try to create a COFFPlatform instance, adding the ORC runtime to the
  40. /// given JITDylib.
  41. static Expected<std::unique_ptr<COFFPlatform>>
  42. Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  43. JITDylib &PlatformJD, const char *OrcRuntimePath,
  44. LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime = false,
  45. const char *VCRuntimePath = nullptr,
  46. std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
  47. ExecutionSession &getExecutionSession() const { return ES; }
  48. ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
  49. Error setupJITDylib(JITDylib &JD) override;
  50. Error teardownJITDylib(JITDylib &JD) override;
  51. Error notifyAdding(ResourceTracker &RT,
  52. const MaterializationUnit &MU) override;
  53. Error notifyRemoving(ResourceTracker &RT) override;
  54. /// Returns an AliasMap containing the default aliases for the COFFPlatform.
  55. /// This can be modified by clients when constructing the platform to add
  56. /// or remove aliases.
  57. static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES);
  58. /// Returns the array of required CXX aliases.
  59. static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
  60. /// Returns the array of standard runtime utility aliases for COFF.
  61. static ArrayRef<std::pair<const char *, const char *>>
  62. standardRuntimeUtilityAliases();
  63. static bool isInitializerSection(StringRef Name) {
  64. return Name.startswith(".CRT");
  65. }
  66. static StringRef getSEHFrameSectionName() { return ".pdata"; }
  67. private:
  68. using COFFJITDylibDepInfo = std::vector<ExecutorAddr>;
  69. using COFFJITDylibDepInfoMap =
  70. std::vector<std::pair<ExecutorAddr, COFFJITDylibDepInfo>>;
  71. using COFFObjectSectionsMap =
  72. SmallVector<std::pair<std::string, ExecutorAddrRange>>;
  73. using PushInitializersSendResultFn =
  74. unique_function<void(Expected<COFFJITDylibDepInfoMap>)>;
  75. using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
  76. using JITDylibDepMap = DenseMap<JITDylib *, SmallVector<JITDylib *>>;
  77. // The COFFPlatformPlugin scans/modifies LinkGraphs to support COFF
  78. // platform features including initializers, exceptions, and language
  79. // runtime registration.
  80. class COFFPlatformPlugin : public ObjectLinkingLayer::Plugin {
  81. public:
  82. COFFPlatformPlugin(COFFPlatform &CP) : CP(CP) {}
  83. void modifyPassConfig(MaterializationResponsibility &MR,
  84. jitlink::LinkGraph &G,
  85. jitlink::PassConfiguration &Config) override;
  86. SyntheticSymbolDependenciesMap
  87. getSyntheticSymbolDependencies(MaterializationResponsibility &MR) override;
  88. // FIXME: We should be tentatively tracking scraped sections and discarding
  89. // if the MR fails.
  90. Error notifyFailed(MaterializationResponsibility &MR) override {
  91. return Error::success();
  92. }
  93. Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
  94. return Error::success();
  95. }
  96. void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
  97. ResourceKey SrcKey) override {}
  98. private:
  99. using InitSymbolDepMap =
  100. DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
  101. Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
  102. MaterializationResponsibility &MR,
  103. bool Bootstrap);
  104. Error preserveInitializerSections(jitlink::LinkGraph &G,
  105. MaterializationResponsibility &MR);
  106. Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD);
  107. Error registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
  108. JITDylib &JD);
  109. std::mutex PluginMutex;
  110. COFFPlatform &CP;
  111. InitSymbolDepMap InitSymbolDeps;
  112. };
  113. struct JDBootstrapState {
  114. JITDylib *JD = nullptr;
  115. std::string JDName;
  116. ExecutorAddr HeaderAddr;
  117. std::list<COFFObjectSectionsMap> ObjectSectionsMaps;
  118. SmallVector<std::pair<std::string, ExecutorAddr>> Initializers;
  119. };
  120. static bool supportedTarget(const Triple &TT);
  121. COFFPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  122. JITDylib &PlatformJD, const char *OrcRuntimePath,
  123. LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
  124. const char *VCRuntimePath, Error &Err);
  125. // Associate COFFPlatform JIT-side runtime support functions with handlers.
  126. Error associateRuntimeSupportFunctions(JITDylib &PlatformJD);
  127. // Records the addresses of runtime symbols used by the platform.
  128. Error bootstrapCOFFRuntime(JITDylib &PlatformJD);
  129. // Run a specific void function if it exists.
  130. Error runSymbolIfExists(JITDylib &PlatformJD, StringRef SymbolName);
  131. // Run collected initializers in boostrap stage.
  132. Error runBootstrapInitializers(JDBootstrapState &BState);
  133. Error runBootstrapSubsectionInitializers(JDBootstrapState &BState,
  134. StringRef Start, StringRef End);
  135. // Build dependency graph of a JITDylib
  136. Expected<JITDylibDepMap> buildJDDepMap(JITDylib &JD);
  137. Expected<MemoryBufferRef> getPerJDObjectFile();
  138. // Implements rt_pushInitializers by making repeat async lookups for
  139. // initializer symbols (each lookup may spawn more initializer symbols if
  140. // it pulls in new materializers, e.g. from objects in a static library).
  141. void pushInitializersLoop(PushInitializersSendResultFn SendResult,
  142. JITDylibSP JD, JITDylibDepMap &JDDepMap);
  143. void rt_pushInitializers(PushInitializersSendResultFn SendResult,
  144. ExecutorAddr JDHeaderAddr);
  145. void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle,
  146. StringRef SymbolName);
  147. ExecutionSession &ES;
  148. ObjectLinkingLayer &ObjLinkingLayer;
  149. LoadDynamicLibrary LoadDynLibrary;
  150. std::unique_ptr<COFFVCRuntimeBootstrapper> VCRuntimeBootstrap;
  151. std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer;
  152. std::unique_ptr<object::Archive> OrcRuntimeArchive;
  153. bool StaticVCRuntime;
  154. SymbolStringPtr COFFHeaderStartSymbol;
  155. // State of bootstrap in progress
  156. std::map<JITDylib *, JDBootstrapState> JDBootstrapStates;
  157. std::atomic<bool> Bootstrapping;
  158. ExecutorAddr orc_rt_coff_platform_bootstrap;
  159. ExecutorAddr orc_rt_coff_platform_shutdown;
  160. ExecutorAddr orc_rt_coff_register_object_sections;
  161. ExecutorAddr orc_rt_coff_deregister_object_sections;
  162. ExecutorAddr orc_rt_coff_register_jitdylib;
  163. ExecutorAddr orc_rt_coff_deregister_jitdylib;
  164. DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
  165. DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
  166. DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
  167. std::set<std::string> DylibsToPreload;
  168. std::mutex PlatformMutex;
  169. };
  170. } // end namespace orc
  171. } // end namespace llvm
  172. #endif // LLVM_EXECUTIONENGINE_ORC_COFFPLATFORM_H
  173. #ifdef __GNUC__
  174. #pragma GCC diagnostic pop
  175. #endif