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
25namespace llvm {
26namespace orc {
27
28/// Enable registration of JIT'd ObjC classes and selectors.
29Error enableObjCRegistration(const char *PathToLibObjC);
30bool objCRegistrationEnabled();
31
32class MachOJITDylibInitializers {
33public:
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
76private:
77
78 JITTargetAddress ObjCImageInfoAddr;
79 RawPointerSectionList ModInitSections;
80 RawPointerSectionList ObjCSelRefsSections;
81 RawPointerSectionList ObjCClassListSections;
82};
83
84class MachOJITDylibDeinitializers {};
85
86/// Mediates between MachO initialization and ExecutionSession state.
87class MachOPlatform : public Platform {
88public:
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
109private:
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,
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.
126 Error notifyFailed(MaterializationResponsibility &MR) override {
127 return Error::success();
128 }
129
130 Error notifyRemovingResources(ResourceKey K) override {
131 return Error::success();
132 }
133
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