//===-- MachOPlatform.h - Utilities for executing MachO in Orc --*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Utilities for executing JIT'd MachO in Orc. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H #define LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include #include #include namespace llvm { namespace orc { /// Enable registration of JIT'd ObjC classes and selectors. Error enableObjCRegistration(const char *PathToLibObjC); bool objCRegistrationEnabled(); class MachOJITDylibInitializers { public: struct SectionExtent { SectionExtent() = default; SectionExtent(JITTargetAddress Address, uint64_t NumPtrs) : Address(Address), NumPtrs(NumPtrs) {} JITTargetAddress Address = 0; uint64_t NumPtrs = 0; }; using RawPointerSectionList = std::vector; void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) { this->ObjCImageInfoAddr = ObjCImageInfoAddr; } void addModInitsSection(SectionExtent ModInit) { ModInitSections.push_back(std::move(ModInit)); } const RawPointerSectionList &getModInitsSections() const { return ModInitSections; } void addObjCSelRefsSection(SectionExtent ObjCSelRefs) { ObjCSelRefsSections.push_back(std::move(ObjCSelRefs)); } const RawPointerSectionList &getObjCSelRefsSections() const { return ObjCSelRefsSections; } void addObjCClassListSection(SectionExtent ObjCClassList) { ObjCClassListSections.push_back(std::move(ObjCClassList)); } const RawPointerSectionList &getObjCClassListSections() const { return ObjCClassListSections; } void runModInits() const; void registerObjCSelectors() const; Error registerObjCClasses() const; private: JITTargetAddress ObjCImageInfoAddr; RawPointerSectionList ModInitSections; RawPointerSectionList ObjCSelRefsSections; RawPointerSectionList ObjCClassListSections; }; class MachOJITDylibDeinitializers {}; /// Mediates between MachO initialization and ExecutionSession state. class MachOPlatform : public Platform { public: using InitializerSequence = std::vector>; using DeinitializerSequence = std::vector>; MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr StandardSymbolsObject); ExecutionSession &getExecutionSession() const { return ES; } Error setupJITDylib(JITDylib &JD) override; Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) override; Error notifyRemoving(ResourceTracker &RT) override; Expected getInitializerSequence(JITDylib &JD); Expected getDeinitializerSequence(JITDylib &JD); private: // This ObjectLinkingLayer plugin scans JITLink graphs for __mod_init_func, // __objc_classlist and __sel_ref sections and records their extents so that // they can be run in the target process. class InitScraperPlugin : public ObjectLinkingLayer::Plugin { public: InitScraperPlugin(MachOPlatform &MP) : MP(MP) {} void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, jitlink::PassConfiguration &Config) override; LocalDependenciesMap getSyntheticSymbolLocalDependencies( MaterializationResponsibility &MR) override; // FIXME: We should be tentatively tracking scraped sections and discarding // if the MR fails. Error notifyFailed(MaterializationResponsibility &MR) override { return Error::success(); } Error notifyRemovingResources(ResourceKey K) override { return Error::success(); } void notifyTransferringResources(ResourceKey DstKey, ResourceKey SrcKey) override {} private: using InitSymbolDepMap = DenseMap; void preserveInitSectionIfPresent(JITLinkSymbolVector &Syms, jitlink::LinkGraph &G, StringRef SectionName); Error processObjCImageInfo(jitlink::LinkGraph &G, MaterializationResponsibility &MR); std::mutex InitScraperMutex; MachOPlatform ∓ DenseMap> ObjCImageInfos; InitSymbolDepMap InitSymbolDeps; }; void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr, MachOJITDylibInitializers::SectionExtent ModInits, MachOJITDylibInitializers::SectionExtent ObjCSelRefs, MachOJITDylibInitializers::SectionExtent ObjCClassList); ExecutionSession &ES; ObjectLinkingLayer &ObjLinkingLayer; std::unique_ptr StandardSymbolsObject; DenseMap RegisteredInitSymbols; // InitSeqs gets its own mutex to avoid locking the whole session when // aggregating data from the jitlink. std::mutex InitSeqsMutex; DenseMap InitSeqs; }; } // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H