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