Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:54

0001 //===-- MachOPlatform.h - Utilities for executing MachO in Orc --*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Utilities for executing JIT'd MachO in Orc.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
0014 #define LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
0015 
0016 #include "llvm/ADT/StringRef.h"
0017 #include "llvm/ExecutionEngine/Orc/Core.h"
0018 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
0019 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
0020 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
0021 
0022 #include <future>
0023 #include <thread>
0024 #include <vector>
0025 
0026 namespace llvm {
0027 namespace orc {
0028 
0029 /// Mediates between MachO initialization and ExecutionSession state.
0030 class MachOPlatform : public Platform {
0031 public:
0032   // Used internally by MachOPlatform, but made public to enable serialization.
0033   struct MachOJITDylibDepInfo {
0034     bool Sealed = false;
0035     std::vector<ExecutorAddr> DepHeaders;
0036   };
0037 
0038   // Used internally by MachOPlatform, but made public to enable serialization.
0039   using MachOJITDylibDepInfoMap =
0040       std::vector<std::pair<ExecutorAddr, MachOJITDylibDepInfo>>;
0041 
0042   // Used internally by MachOPlatform, but made public to enable serialization.
0043   enum class MachOExecutorSymbolFlags : uint8_t {
0044     None = 0,
0045     Weak = 1U << 0,
0046     Callable = 1U << 1,
0047     LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable)
0048   };
0049 
0050   /// Configuration for the mach-o header of a JITDylib. Specify common load
0051   /// commands that should be added to the header.
0052   struct HeaderOptions {
0053     /// A dylib for use with a dylib command (e.g. LC_ID_DYLIB, LC_LOAD_DYLIB).
0054     struct Dylib {
0055       std::string Name;
0056       uint32_t Timestamp;
0057       uint32_t CurrentVersion;
0058       uint32_t CompatibilityVersion;
0059     };
0060 
0061     struct BuildVersionOpts {
0062 
0063       // Derive platform from triple if possible.
0064       static std::optional<BuildVersionOpts>
0065       fromTriple(const Triple &TT, uint32_t MinOS, uint32_t SDK);
0066 
0067       uint32_t Platform; // Platform.
0068       uint32_t MinOS;    // X.Y.Z is encoded in nibbles xxxx.yy.zz
0069       uint32_t SDK;      // X.Y.Z is encoded in nibbles xxxx.yy.zz
0070     };
0071 
0072     /// Override for LC_IC_DYLIB. If this is nullopt, {JD.getName(), 0, 0, 0}
0073     /// will be used.
0074     std::optional<Dylib> IDDylib;
0075 
0076     /// List of LC_LOAD_DYLIBs.
0077     std::vector<Dylib> LoadDylibs;
0078     /// List of LC_RPATHs.
0079     std::vector<std::string> RPaths;
0080     /// List of LC_BUILD_VERSIONs.
0081     std::vector<BuildVersionOpts> BuildVersions;
0082 
0083     HeaderOptions() = default;
0084     HeaderOptions(Dylib D) : IDDylib(std::move(D)) {}
0085   };
0086 
0087   /// Used by setupJITDylib to create MachO header MaterializationUnits for
0088   /// JITDylibs.
0089   using MachOHeaderMUBuilder =
0090       unique_function<std::unique_ptr<MaterializationUnit>(MachOPlatform &MOP,
0091                                                            HeaderOptions Opts)>;
0092 
0093   /// Simple MachO header graph builder.
0094   static inline std::unique_ptr<MaterializationUnit>
0095   buildSimpleMachOHeaderMU(MachOPlatform &MOP, HeaderOptions Opts);
0096 
0097   /// Try to create a MachOPlatform instance, adding the ORC runtime to the
0098   /// given JITDylib.
0099   ///
0100   /// The ORC runtime requires access to a number of symbols in libc++, and
0101   /// requires access to symbols in libobjc, and libswiftCore to support
0102   /// Objective-C and Swift code. It is up to the caller to ensure that the
0103   /// required symbols can be referenced by code added to PlatformJD. The
0104   /// standard way to achieve this is to first attach dynamic library search
0105   /// generators for either the given process, or for the specific required
0106   /// libraries, to PlatformJD, then to create the platform instance:
0107   ///
0108   /// \code{.cpp}
0109   ///   auto &PlatformJD = ES.createBareJITDylib("stdlib");
0110   ///   PlatformJD.addGenerator(
0111   ///     ExitOnErr(EPCDynamicLibrarySearchGenerator
0112   ///                 ::GetForTargetProcess(EPC)));
0113   ///   ES.setPlatform(
0114   ///     ExitOnErr(MachOPlatform::Create(ES, ObjLayer, EPC, PlatformJD,
0115   ///                                     "/path/to/orc/runtime")));
0116   /// \endcode
0117   ///
0118   /// Alternatively, these symbols could be added to another JITDylib that
0119   /// PlatformJD links against.
0120   ///
0121   /// Clients are also responsible for ensuring that any JIT'd code that
0122   /// depends on runtime functions (including any code using TLV or static
0123   /// destructors) can reference the runtime symbols. This is usually achieved
0124   /// by linking any JITDylibs containing regular code against
0125   /// PlatformJD.
0126   ///
0127   /// By default, MachOPlatform will add the set of aliases returned by the
0128   /// standardPlatformAliases function. This includes both required aliases
0129   /// (e.g. __cxa_atexit -> __orc_rt_macho_cxa_atexit for static destructor
0130   /// support), and optional aliases that provide JIT versions of common
0131   /// functions (e.g. dlopen -> __orc_rt_macho_jit_dlopen). Clients can
0132   /// override these defaults by passing a non-None value for the
0133   /// RuntimeAliases function, in which case the client is responsible for
0134   /// setting up all aliases (including the required ones).
0135   static Expected<std::unique_ptr<MachOPlatform>>
0136   Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
0137          std::unique_ptr<DefinitionGenerator> OrcRuntime,
0138          HeaderOptions PlatformJDOpts = {},
0139          MachOHeaderMUBuilder BuildMachOHeaderMU = buildSimpleMachOHeaderMU,
0140          std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
0141 
0142   /// Construct using a path to the ORC runtime.
0143   static Expected<std::unique_ptr<MachOPlatform>>
0144   Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
0145          const char *OrcRuntimePath, HeaderOptions PlatformJDOpts = {},
0146          MachOHeaderMUBuilder BuildMachOHeaderMU = buildSimpleMachOHeaderMU,
0147          std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
0148 
0149   ExecutionSession &getExecutionSession() const { return ES; }
0150   ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
0151 
0152   NonOwningSymbolStringPtr getMachOHeaderStartSymbol() const {
0153     return NonOwningSymbolStringPtr(MachOHeaderStartSymbol);
0154   }
0155 
0156   Error setupJITDylib(JITDylib &JD) override;
0157 
0158   /// Install any platform-specific symbols (e.g. `__dso_handle`) and create a
0159   /// mach-o header based on the given options.
0160   Error setupJITDylib(JITDylib &JD, HeaderOptions Opts);
0161 
0162   Error teardownJITDylib(JITDylib &JD) override;
0163   Error notifyAdding(ResourceTracker &RT,
0164                      const MaterializationUnit &MU) override;
0165   Error notifyRemoving(ResourceTracker &RT) override;
0166 
0167   /// Returns an AliasMap containing the default aliases for the MachOPlatform.
0168   /// This can be modified by clients when constructing the platform to add
0169   /// or remove aliases.
0170   static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES);
0171 
0172   /// Returns the array of required CXX aliases.
0173   static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
0174 
0175   /// Returns the array of standard runtime utility aliases for MachO.
0176   static ArrayRef<std::pair<const char *, const char *>>
0177   standardRuntimeUtilityAliases();
0178 
0179   /// Returns a list of aliases required to enable lazy compilation via the
0180   /// ORC runtime.
0181   static ArrayRef<std::pair<const char *, const char *>>
0182   standardLazyCompilationAliases();
0183 
0184 private:
0185   using SymbolTableVector = SmallVector<
0186       std::tuple<ExecutorAddr, ExecutorAddr, MachOExecutorSymbolFlags>>;
0187 
0188   // Data needed for bootstrap only.
0189   struct BootstrapInfo {
0190     std::mutex Mutex;
0191     std::condition_variable CV;
0192     size_t ActiveGraphs = 0;
0193     shared::AllocActions DeferredAAs;
0194     ExecutorAddr MachOHeaderAddr;
0195     SymbolTableVector SymTab;
0196   };
0197 
0198   // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
0199   // platform features including initializers, exceptions, TLV, and language
0200   // runtime registration.
0201   class MachOPlatformPlugin : public ObjectLinkingLayer::Plugin {
0202   public:
0203     MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {}
0204 
0205     void modifyPassConfig(MaterializationResponsibility &MR,
0206                           jitlink::LinkGraph &G,
0207                           jitlink::PassConfiguration &Config) override;
0208 
0209     // FIXME: We should be tentatively tracking scraped sections and discarding
0210     // if the MR fails.
0211     Error notifyFailed(MaterializationResponsibility &MR) override {
0212       return Error::success();
0213     }
0214 
0215     Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
0216       return Error::success();
0217     }
0218 
0219     void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
0220                                      ResourceKey SrcKey) override {}
0221 
0222   private:
0223     struct UnwindSections {
0224       SmallVector<ExecutorAddrRange> CodeRanges;
0225       ExecutorAddrRange DwarfSection;
0226       ExecutorAddrRange CompactUnwindSection;
0227     };
0228 
0229     struct ObjCImageInfo {
0230       uint32_t Version = 0;
0231       uint32_t Flags = 0;
0232       /// Whether this image info can no longer be mutated, as it may have been
0233       /// registered with the objc runtime.
0234       bool Finalized = false;
0235     };
0236 
0237     struct SymbolTablePair {
0238       jitlink::Symbol *OriginalSym = nullptr;
0239       jitlink::Symbol *NameSym = nullptr;
0240     };
0241     using JITSymTabVector = SmallVector<SymbolTablePair>;
0242 
0243     Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
0244     Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
0245 
0246     Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
0247                                         MaterializationResponsibility &MR);
0248 
0249     Error preserveImportantSections(jitlink::LinkGraph &G,
0250                                     MaterializationResponsibility &MR);
0251 
0252     Error processObjCImageInfo(jitlink::LinkGraph &G,
0253                                MaterializationResponsibility &MR);
0254     Error mergeImageInfoFlags(jitlink::LinkGraph &G,
0255                               MaterializationResponsibility &MR,
0256                               ObjCImageInfo &Info, uint32_t NewFlags);
0257 
0258     Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
0259 
0260     std::optional<UnwindSections> findUnwindSectionInfo(jitlink::LinkGraph &G);
0261     Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD,
0262                                          ExecutorAddr HeaderAddr,
0263                                          bool InBootstrapPhase);
0264 
0265     Error createObjCRuntimeObject(jitlink::LinkGraph &G);
0266     Error populateObjCRuntimeObject(jitlink::LinkGraph &G,
0267                                     MaterializationResponsibility &MR);
0268 
0269     Error prepareSymbolTableRegistration(jitlink::LinkGraph &G,
0270                                          JITSymTabVector &JITSymTabInfo);
0271     Error addSymbolTableRegistration(jitlink::LinkGraph &G,
0272                                      MaterializationResponsibility &MR,
0273                                      JITSymTabVector &JITSymTabInfo,
0274                                      bool InBootstrapPhase);
0275 
0276     std::mutex PluginMutex;
0277     MachOPlatform &MP;
0278 
0279     // FIXME: ObjCImageInfos and HeaderAddrs need to be cleared when
0280     // JITDylibs are removed.
0281     DenseMap<JITDylib *, ObjCImageInfo> ObjCImageInfos;
0282     DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
0283   };
0284 
0285   using GetJITDylibHeaderSendResultFn =
0286       unique_function<void(Expected<ExecutorAddr>)>;
0287   using GetJITDylibNameSendResultFn =
0288       unique_function<void(Expected<StringRef>)>;
0289   using PushInitializersSendResultFn =
0290       unique_function<void(Expected<MachOJITDylibDepInfoMap>)>;
0291   using SendSymbolAddressFn = unique_function<void(Expected<ExecutorAddr>)>;
0292   using PushSymbolsInSendResultFn = unique_function<void(Error)>;
0293 
0294   static bool supportedTarget(const Triple &TT);
0295 
0296   static jitlink::Edge::Kind getPointerEdgeKind(jitlink::LinkGraph &G);
0297 
0298   static MachOExecutorSymbolFlags flagsForSymbol(jitlink::Symbol &Sym);
0299 
0300   MachOPlatform(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
0301                 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
0302                 HeaderOptions PlatformJDOpts,
0303                 MachOHeaderMUBuilder BuildMachOHeaderMU, Error &Err);
0304 
0305   // Associate MachOPlatform JIT-side runtime support functions with handlers.
0306   Error associateRuntimeSupportFunctions();
0307 
0308   // Implements rt_pushInitializers by making repeat async lookups for
0309   // initializer symbols (each lookup may spawn more initializer symbols if
0310   // it pulls in new materializers, e.g. from objects in a static library).
0311   void pushInitializersLoop(PushInitializersSendResultFn SendResult,
0312                             JITDylibSP JD);
0313 
0314   // Handle requests from the ORC runtime to push MachO initializer info.
0315   void rt_pushInitializers(PushInitializersSendResultFn SendResult,
0316                            ExecutorAddr JDHeaderAddr);
0317 
0318   // Request that that the given symbols be materialized. The bool element of
0319   // each pair indicates whether the symbol must be initialized, or whether it
0320   // is optional. If any required symbol is not found then the pushSymbols
0321   // function will return an error.
0322   void rt_pushSymbols(PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle,
0323                       const std::vector<std::pair<StringRef, bool>> &Symbols);
0324 
0325   // Call the ORC runtime to create a pthread key.
0326   Expected<uint64_t> createPThreadKey();
0327 
0328   ExecutionSession &ES;
0329   JITDylib &PlatformJD;
0330   ObjectLinkingLayer &ObjLinkingLayer;
0331   MachOHeaderMUBuilder BuildMachOHeaderMU;
0332 
0333   SymbolStringPtr MachOHeaderStartSymbol = ES.intern("___dso_handle");
0334 
0335   struct RuntimeFunction {
0336     RuntimeFunction(SymbolStringPtr Name) : Name(std::move(Name)) {}
0337     SymbolStringPtr Name;
0338     ExecutorAddr Addr;
0339   };
0340 
0341   RuntimeFunction PlatformBootstrap{
0342       ES.intern("___orc_rt_macho_platform_bootstrap")};
0343   RuntimeFunction PlatformShutdown{
0344       ES.intern("___orc_rt_macho_platform_shutdown")};
0345   RuntimeFunction RegisterEHFrameSection{
0346       ES.intern("___orc_rt_macho_register_ehframe_section")};
0347   RuntimeFunction DeregisterEHFrameSection{
0348       ES.intern("___orc_rt_macho_deregister_ehframe_section")};
0349   RuntimeFunction RegisterJITDylib{
0350       ES.intern("___orc_rt_macho_register_jitdylib")};
0351   RuntimeFunction DeregisterJITDylib{
0352       ES.intern("___orc_rt_macho_deregister_jitdylib")};
0353   RuntimeFunction RegisterObjectSymbolTable{
0354       ES.intern("___orc_rt_macho_register_object_symbol_table")};
0355   RuntimeFunction DeregisterObjectSymbolTable{
0356       ES.intern("___orc_rt_macho_deregister_object_symbol_table")};
0357   RuntimeFunction RegisterObjectPlatformSections{
0358       ES.intern("___orc_rt_macho_register_object_platform_sections")};
0359   RuntimeFunction DeregisterObjectPlatformSections{
0360       ES.intern("___orc_rt_macho_deregister_object_platform_sections")};
0361   RuntimeFunction CreatePThreadKey{
0362       ES.intern("___orc_rt_macho_create_pthread_key")};
0363   RuntimeFunction RegisterObjCRuntimeObject{
0364       ES.intern("___orc_rt_macho_register_objc_runtime_object")};
0365   RuntimeFunction DeregisterObjCRuntimeObject{
0366       ES.intern("___orc_rt_macho_deregister_objc_runtime_object")};
0367 
0368   DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
0369 
0370   std::mutex PlatformMutex;
0371   bool ForceEHFrames = false;
0372   BootstrapInfo *Bootstrap = nullptr;
0373   DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
0374   DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
0375   DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
0376 };
0377 
0378 // Generates a MachO header.
0379 class SimpleMachOHeaderMU : public MaterializationUnit {
0380 public:
0381   SimpleMachOHeaderMU(MachOPlatform &MOP, SymbolStringPtr HeaderStartSymbol,
0382                       MachOPlatform::HeaderOptions Opts);
0383   StringRef getName() const override { return "MachOHeaderMU"; }
0384   void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
0385   void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override;
0386 
0387 protected:
0388   virtual jitlink::Block &createHeaderBlock(JITDylib &JD, jitlink::LinkGraph &G,
0389                                             jitlink::Section &HeaderSection);
0390 
0391   MachOPlatform &MOP;
0392   MachOPlatform::HeaderOptions Opts;
0393 
0394 private:
0395   struct HeaderSymbol {
0396     const char *Name;
0397     uint64_t Offset;
0398   };
0399 
0400   static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
0401       {"___mh_executable_header", 0}};
0402 
0403   void addMachOHeader(JITDylib &JD, jitlink::LinkGraph &G,
0404                       const SymbolStringPtr &InitializerSymbol);
0405   static MaterializationUnit::Interface
0406   createHeaderInterface(MachOPlatform &MOP,
0407                         const SymbolStringPtr &HeaderStartSymbol);
0408 };
0409 
0410 /// Simple MachO header graph builder.
0411 inline std::unique_ptr<MaterializationUnit>
0412 MachOPlatform::buildSimpleMachOHeaderMU(MachOPlatform &MOP,
0413                                         HeaderOptions Opts) {
0414   return std::make_unique<SimpleMachOHeaderMU>(MOP, MOP.MachOHeaderStartSymbol,
0415                                                std::move(Opts));
0416 }
0417 
0418 struct MachOHeaderInfo {
0419   size_t PageSize = 0;
0420   uint32_t CPUType = 0;
0421   uint32_t CPUSubType = 0;
0422 };
0423 MachOHeaderInfo getMachOHeaderInfoFromTriple(const Triple &TT);
0424 
0425 } // end namespace orc
0426 } // end namespace llvm
0427 
0428 #endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H