1 //===-- MachOPlatform.h - Utilities for executing MachO in Orc --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Utilities for executing JIT'd MachO in Orc.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
14 #define LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
15 
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ExecutionEngine/Orc/Core.h"
18 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
19 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
20 
21 #include <future>
22 #include <thread>
23 #include <vector>
24 
25 namespace llvm {
26 namespace orc {
27 
28 /// Enable registration of JIT'd ObjC classes and selectors.
29 Error enableObjCRegistration(const char *PathToLibObjC);
30 bool objCRegistrationEnabled();
31 
32 class MachOJITDylibInitializers {
33 public:
34   struct SectionExtent {
35     SectionExtent() = default;
36     SectionExtent(JITTargetAddress Address, uint64_t NumPtrs)
37         : Address(Address), NumPtrs(NumPtrs) {}
38     JITTargetAddress Address = 0;
39     uint64_t NumPtrs = 0;
40   };
41 
42   using RawPointerSectionList = std::vector<SectionExtent>;
43 
44   void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) {
45     this->ObjCImageInfoAddr = ObjCImageInfoAddr;
46   }
47 
48   void addModInitsSection(SectionExtent ModInit) {
49     ModInitSections.push_back(std::move(ModInit));
50   }
51 
52   const RawPointerSectionList &getModInitsSections() const {
53     return ModInitSections;
54   }
55 
56   void addObjCSelRefsSection(SectionExtent ObjCSelRefs) {
57     ObjCSelRefsSections.push_back(std::move(ObjCSelRefs));
58   }
59 
60   const RawPointerSectionList &getObjCSelRefsSections() const {
61     return ObjCSelRefsSections;
62   }
63 
64   void addObjCClassListSection(SectionExtent ObjCClassList) {
65     ObjCClassListSections.push_back(std::move(ObjCClassList));
66   }
67 
68   const RawPointerSectionList &getObjCClassListSections() const {
69     return ObjCClassListSections;
70   }
71 
72   void runModInits() const;
73   void registerObjCSelectors() const;
74   Error registerObjCClasses() const;
75 
76 private:
77 
78   JITTargetAddress ObjCImageInfoAddr;
79   RawPointerSectionList ModInitSections;
80   RawPointerSectionList ObjCSelRefsSections;
81   RawPointerSectionList ObjCClassListSections;
82 };
83 
84 class MachOJITDylibDeinitializers {};
85 
86 /// Mediates between MachO initialization and ExecutionSession state.
87 class MachOPlatform : public Platform {
88 public:
89   using InitializerSequence =
90       std::vector<std::pair<JITDylib *, MachOJITDylibInitializers>>;
91 
92   using DeinitializerSequence =
93       std::vector<std::pair<JITDylib *, MachOJITDylibDeinitializers>>;
94 
95   MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
96                 std::unique_ptr<MemoryBuffer> StandardSymbolsObject);
97 
98   ExecutionSession &getExecutionSession() const { return ES; }
99 
100   Error setupJITDylib(JITDylib &JD) override;
101   Error notifyAdding(ResourceTracker &RT,
102                      const MaterializationUnit &MU) override;
103   Error notifyRemoving(ResourceTracker &RT) override;
104 
105   Expected<InitializerSequence> getInitializerSequence(JITDylib &JD);
106 
107   Expected<DeinitializerSequence> getDeinitializerSequence(JITDylib &JD);
108 
109 private:
110   // This ObjectLinkingLayer plugin scans JITLink graphs for __mod_init_func,
111   // __objc_classlist and __sel_ref sections and records their extents so that
112   // they can be run in the target process.
113   class InitScraperPlugin : public ObjectLinkingLayer::Plugin {
114   public:
115     InitScraperPlugin(MachOPlatform &MP) : MP(MP) {}
116 
117     void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
118                           jitlink::PassConfiguration &Config) override;
119 
120     LocalDependenciesMap getSyntheticSymbolLocalDependencies(
121         MaterializationResponsibility &MR) override;
122 
123     // FIXME: We should be tentatively tracking scraped sections and discarding
124     // if the MR fails.
125     Error notifyFailed(MaterializationResponsibility &MR) override {
126       return Error::success();
127     }
128 
129     Error notifyRemovingResources(ResourceKey K) override {
130       return Error::success();
131     }
132 
133     void notifyTransferringResources(ResourceKey DstKey,
134                                      ResourceKey SrcKey) override {}
135 
136   private:
137     using InitSymbolDepMap =
138         DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>;
139 
140     void preserveInitSectionIfPresent(JITLinkSymbolVector &Syms,
141                                       jitlink::LinkGraph &G,
142                                       StringRef SectionName);
143 
144     Error processObjCImageInfo(jitlink::LinkGraph &G,
145                                MaterializationResponsibility &MR);
146 
147     std::mutex InitScraperMutex;
148     MachOPlatform &MP;
149     DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
150     InitSymbolDepMap InitSymbolDeps;
151   };
152 
153   void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,
154                         MachOJITDylibInitializers::SectionExtent ModInits,
155                         MachOJITDylibInitializers::SectionExtent ObjCSelRefs,
156                         MachOJITDylibInitializers::SectionExtent ObjCClassList);
157 
158   ExecutionSession &ES;
159   ObjectLinkingLayer &ObjLinkingLayer;
160   std::unique_ptr<MemoryBuffer> StandardSymbolsObject;
161 
162   DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
163 
164   // InitSeqs gets its own mutex to avoid locking the whole session when
165   // aggregating data from the jitlink.
166   std::mutex InitSeqsMutex;
167   DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;
168 };
169 
170 } // end namespace orc
171 } // end namespace llvm
172 
173 #endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
174