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, 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. notifyFailed(MaterializationResponsibility & MR)125 Error notifyFailed(MaterializationResponsibility &MR) override { 126 return Error::success(); 127 } 128 notifyRemovingResources(ResourceKey K)129 Error notifyRemovingResources(ResourceKey K) override { 130 return Error::success(); 131 } 132 notifyTransferringResources(ResourceKey DstKey,ResourceKey SrcKey)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