xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
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;
SectionExtentSectionExtent36     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 
setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr)44   void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) {
45     this->ObjCImageInfoAddr = ObjCImageInfoAddr;
46   }
47 
addModInitsSection(SectionExtent ModInit)48   void addModInitsSection(SectionExtent ModInit) {
49     ModInitSections.push_back(std::move(ModInit));
50   }
51 
getModInitsSections()52   const RawPointerSectionList &getModInitsSections() const {
53     return ModInitSections;
54   }
55 
addObjCSelRefsSection(SectionExtent ObjCSelRefs)56   void addObjCSelRefsSection(SectionExtent ObjCSelRefs) {
57     ObjCSelRefsSections.push_back(std::move(ObjCSelRefs));
58   }
59 
getObjCSelRefsSections()60   const RawPointerSectionList &getObjCSelRefsSections() const {
61     return ObjCSelRefsSections;
62   }
63 
addObjCClassListSection(SectionExtent ObjCClassList)64   void addObjCClassListSection(SectionExtent ObjCClassList) {
65     ObjCClassListSections.push_back(std::move(ObjCClassList));
66   }
67 
getObjCClassListSections()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 
getExecutionSession()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:
InitScraperPlugin(MachOPlatform & MP)115     InitScraperPlugin(MachOPlatform &MP) : MP(MP) {}
116 
117     void modifyPassConfig(MaterializationResponsibility &MR,
118                           jitlink::LinkGraph &G,
119                           jitlink::PassConfiguration &Config) override;
120 
121     LocalDependenciesMap getSyntheticSymbolLocalDependencies(
122         MaterializationResponsibility &MR) override;
123 
124     // FIXME: We should be tentatively tracking scraped sections and discarding
125     // if the MR fails.
notifyFailed(MaterializationResponsibility & MR)126     Error notifyFailed(MaterializationResponsibility &MR) override {
127       return Error::success();
128     }
129 
notifyRemovingResources(ResourceKey K)130     Error notifyRemovingResources(ResourceKey K) override {
131       return Error::success();
132     }
133 
notifyTransferringResources(ResourceKey DstKey,ResourceKey SrcKey)134     void notifyTransferringResources(ResourceKey DstKey,
135                                      ResourceKey SrcKey) override {}
136 
137   private:
138     using InitSymbolDepMap =
139         DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>;
140 
141     void preserveInitSectionIfPresent(JITLinkSymbolVector &Syms,
142                                       jitlink::LinkGraph &G,
143                                       StringRef SectionName);
144 
145     Error processObjCImageInfo(jitlink::LinkGraph &G,
146                                MaterializationResponsibility &MR);
147 
148     std::mutex InitScraperMutex;
149     MachOPlatform &MP;
150     DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
151     InitSymbolDepMap InitSymbolDeps;
152   };
153 
154   void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,
155                         MachOJITDylibInitializers::SectionExtent ModInits,
156                         MachOJITDylibInitializers::SectionExtent ObjCSelRefs,
157                         MachOJITDylibInitializers::SectionExtent ObjCClassList);
158 
159   ExecutionSession &ES;
160   ObjectLinkingLayer &ObjLinkingLayer;
161   std::unique_ptr<MemoryBuffer> StandardSymbolsObject;
162 
163   DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
164 
165   // InitSeqs gets its own mutex to avoid locking the whole session when
166   // aggregating data from the jitlink.
167   std::mutex InitSeqsMutex;
168   DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;
169 };
170 
171 } // end namespace orc
172 } // end namespace llvm
173 
174 #endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
175