15ffd83dbSDimitry Andric //===------ MachOPlatform.cpp - Utilities for executing MachO in Orc ------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" 105ffd83dbSDimitry Andric 115ffd83dbSDimitry Andric #include "llvm/BinaryFormat/MachO.h" 1206c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO.h" 1306c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/aarch64.h" 14fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h" 155ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 16fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 17349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h" 185f757f3fSDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOBuilder.h" 1906c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 205ffd83dbSDimitry Andric #include "llvm/Support/BinaryByteStream.h" 215ffd83dbSDimitry Andric #include "llvm/Support/Debug.h" 22bdd1243dSDimitry Andric #include <optional> 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric #define DEBUG_TYPE "orc" 255ffd83dbSDimitry Andric 26fe6060f1SDimitry Andric using namespace llvm; 27fe6060f1SDimitry Andric using namespace llvm::orc; 28fe6060f1SDimitry Andric using namespace llvm::orc::shared; 29fe6060f1SDimitry Andric 3081ad6265SDimitry Andric namespace llvm { 3181ad6265SDimitry Andric namespace orc { 3281ad6265SDimitry Andric namespace shared { 3381ad6265SDimitry Andric 3481ad6265SDimitry Andric using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>; 3581ad6265SDimitry Andric using SPSMachOJITDylibDepInfoMap = 3681ad6265SDimitry Andric SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>; 3781ad6265SDimitry Andric 385f757f3fSDimitry Andric class SPSMachOExecutorSymbolFlags; 395f757f3fSDimitry Andric 4081ad6265SDimitry Andric template <> 4181ad6265SDimitry Andric class SPSSerializationTraits<SPSMachOJITDylibDepInfo, 4281ad6265SDimitry Andric MachOPlatform::MachOJITDylibDepInfo> { 4381ad6265SDimitry Andric public: 4481ad6265SDimitry Andric static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) { 4581ad6265SDimitry Andric return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders); 4681ad6265SDimitry Andric } 4781ad6265SDimitry Andric 4881ad6265SDimitry Andric static bool serialize(SPSOutputBuffer &OB, 4981ad6265SDimitry Andric const MachOPlatform::MachOJITDylibDepInfo &DDI) { 5081ad6265SDimitry Andric return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed, 5181ad6265SDimitry Andric DDI.DepHeaders); 5281ad6265SDimitry Andric } 5381ad6265SDimitry Andric 5481ad6265SDimitry Andric static bool deserialize(SPSInputBuffer &IB, 5581ad6265SDimitry Andric MachOPlatform::MachOJITDylibDepInfo &DDI) { 5681ad6265SDimitry Andric return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed, 5781ad6265SDimitry Andric DDI.DepHeaders); 5881ad6265SDimitry Andric } 5981ad6265SDimitry Andric }; 6081ad6265SDimitry Andric 615f757f3fSDimitry Andric template <> 625f757f3fSDimitry Andric class SPSSerializationTraits<SPSMachOExecutorSymbolFlags, 635f757f3fSDimitry Andric MachOPlatform::MachOExecutorSymbolFlags> { 645f757f3fSDimitry Andric private: 655f757f3fSDimitry Andric using UT = std::underlying_type_t<MachOPlatform::MachOExecutorSymbolFlags>; 665f757f3fSDimitry Andric 675f757f3fSDimitry Andric public: 685f757f3fSDimitry Andric static size_t size(const MachOPlatform::MachOExecutorSymbolFlags &SF) { 695f757f3fSDimitry Andric return sizeof(UT); 705f757f3fSDimitry Andric } 715f757f3fSDimitry Andric 725f757f3fSDimitry Andric static bool serialize(SPSOutputBuffer &OB, 735f757f3fSDimitry Andric const MachOPlatform::MachOExecutorSymbolFlags &SF) { 745f757f3fSDimitry Andric return SPSArgList<UT>::serialize(OB, static_cast<UT>(SF)); 755f757f3fSDimitry Andric } 765f757f3fSDimitry Andric 775f757f3fSDimitry Andric static bool deserialize(SPSInputBuffer &IB, 785f757f3fSDimitry Andric MachOPlatform::MachOExecutorSymbolFlags &SF) { 795f757f3fSDimitry Andric UT Tmp; 805f757f3fSDimitry Andric if (!SPSArgList<UT>::deserialize(IB, Tmp)) 815f757f3fSDimitry Andric return false; 825f757f3fSDimitry Andric SF = static_cast<MachOPlatform::MachOExecutorSymbolFlags>(Tmp); 835f757f3fSDimitry Andric return true; 845f757f3fSDimitry Andric } 855f757f3fSDimitry Andric }; 865f757f3fSDimitry Andric 8781ad6265SDimitry Andric } // namespace shared 8881ad6265SDimitry Andric } // namespace orc 8981ad6265SDimitry Andric } // namespace llvm 9081ad6265SDimitry Andric 915ffd83dbSDimitry Andric namespace { 925ffd83dbSDimitry Andric 935f757f3fSDimitry Andric using SPSRegisterSymbolsArgs = 945f757f3fSDimitry Andric SPSArgList<SPSExecutorAddr, 955f757f3fSDimitry Andric SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr, 965f757f3fSDimitry Andric SPSMachOExecutorSymbolFlags>>>; 975f757f3fSDimitry Andric 98bdd1243dSDimitry Andric std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP, 99bdd1243dSDimitry Andric std::string Name) { 100fe6060f1SDimitry Andric unsigned PointerSize; 1015f757f3fSDimitry Andric llvm::endianness Endianness; 10206c3fb27SDimitry Andric const auto &TT = MOP.getExecutionSession().getTargetTriple(); 1035ffd83dbSDimitry Andric 104fe6060f1SDimitry Andric switch (TT.getArch()) { 105fe6060f1SDimitry Andric case Triple::aarch64: 106fe6060f1SDimitry Andric case Triple::x86_64: 107fe6060f1SDimitry Andric PointerSize = 8; 1085f757f3fSDimitry Andric Endianness = llvm::endianness::little; 109fe6060f1SDimitry Andric break; 110fe6060f1SDimitry Andric default: 111fe6060f1SDimitry Andric llvm_unreachable("Unrecognized architecture"); 112fe6060f1SDimitry Andric } 1135ffd83dbSDimitry Andric 114bdd1243dSDimitry Andric return std::make_unique<jitlink::LinkGraph>(std::move(Name), TT, PointerSize, 115bdd1243dSDimitry Andric Endianness, 116fe6060f1SDimitry Andric jitlink::getGenericEdgeKindName); 117bdd1243dSDimitry Andric } 118fe6060f1SDimitry Andric 119bdd1243dSDimitry Andric // Creates a Bootstrap-Complete LinkGraph to run deferred actions. 120bdd1243dSDimitry Andric class MachOPlatformCompleteBootstrapMaterializationUnit 121bdd1243dSDimitry Andric : public MaterializationUnit { 122bdd1243dSDimitry Andric public: 1235f757f3fSDimitry Andric using SymbolTableVector = 1245f757f3fSDimitry Andric SmallVector<std::tuple<ExecutorAddr, ExecutorAddr, 1255f757f3fSDimitry Andric MachOPlatform::MachOExecutorSymbolFlags>>; 1265f757f3fSDimitry Andric 127bdd1243dSDimitry Andric MachOPlatformCompleteBootstrapMaterializationUnit( 128bdd1243dSDimitry Andric MachOPlatform &MOP, StringRef PlatformJDName, 1295f757f3fSDimitry Andric SymbolStringPtr CompleteBootstrapSymbol, SymbolTableVector SymTab, 1305f757f3fSDimitry Andric shared::AllocActions DeferredAAs, ExecutorAddr MachOHeaderAddr, 131bdd1243dSDimitry Andric ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown, 132bdd1243dSDimitry Andric ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib, 1335f757f3fSDimitry Andric ExecutorAddr RegisterObjectSymbolTable, 1345f757f3fSDimitry Andric ExecutorAddr DeregisterObjectSymbolTable) 135bdd1243dSDimitry Andric : MaterializationUnit( 136bdd1243dSDimitry Andric {{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}), 137bdd1243dSDimitry Andric MOP(MOP), PlatformJDName(PlatformJDName), 138bdd1243dSDimitry Andric CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)), 1395f757f3fSDimitry Andric SymTab(std::move(SymTab)), DeferredAAs(std::move(DeferredAAs)), 1405f757f3fSDimitry Andric MachOHeaderAddr(MachOHeaderAddr), PlatformBootstrap(PlatformBootstrap), 141bdd1243dSDimitry Andric PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib), 142bdd1243dSDimitry Andric DeregisterJITDylib(DeregisterJITDylib), 1435f757f3fSDimitry Andric RegisterObjectSymbolTable(RegisterObjectSymbolTable), 1445f757f3fSDimitry Andric DeregisterObjectSymbolTable(DeregisterObjectSymbolTable) {} 145bdd1243dSDimitry Andric 146bdd1243dSDimitry Andric StringRef getName() const override { 147bdd1243dSDimitry Andric return "MachOPlatformCompleteBootstrap"; 148bdd1243dSDimitry Andric } 149bdd1243dSDimitry Andric 150bdd1243dSDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> R) override { 151bdd1243dSDimitry Andric using namespace jitlink; 152bdd1243dSDimitry Andric auto G = createPlatformGraph(MOP, "<OrcRTCompleteBootstrap>"); 153bdd1243dSDimitry Andric auto &PlaceholderSection = 154bdd1243dSDimitry Andric G->createSection("__orc_rt_cplt_bs", MemProt::Read); 155bdd1243dSDimitry Andric auto &PlaceholderBlock = 156bdd1243dSDimitry Andric G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0); 157bdd1243dSDimitry Andric G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1, 158bdd1243dSDimitry Andric Linkage::Strong, Scope::Hidden, false, true); 159bdd1243dSDimitry Andric 160bdd1243dSDimitry Andric // Reserve space for the stolen actions, plus two extras. 1615f757f3fSDimitry Andric G->allocActions().reserve(DeferredAAs.size() + 3); 162bdd1243dSDimitry Andric 163bdd1243dSDimitry Andric // 1. Bootstrap the platform support code. 164bdd1243dSDimitry Andric G->allocActions().push_back( 165bdd1243dSDimitry Andric {cantFail(WrapperFunctionCall::Create<SPSArgList<>>(PlatformBootstrap)), 166bdd1243dSDimitry Andric cantFail( 167bdd1243dSDimitry Andric WrapperFunctionCall::Create<SPSArgList<>>(PlatformShutdown))}); 168bdd1243dSDimitry Andric 169bdd1243dSDimitry Andric // 2. Register the platform JITDylib. 170bdd1243dSDimitry Andric G->allocActions().push_back( 171bdd1243dSDimitry Andric {cantFail(WrapperFunctionCall::Create< 172bdd1243dSDimitry Andric SPSArgList<SPSString, SPSExecutorAddr>>( 173bdd1243dSDimitry Andric RegisterJITDylib, PlatformJDName, MachOHeaderAddr)), 174bdd1243dSDimitry Andric cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 175bdd1243dSDimitry Andric DeregisterJITDylib, MachOHeaderAddr))}); 176bdd1243dSDimitry Andric 1775f757f3fSDimitry Andric // 3. Register deferred symbols. 1785f757f3fSDimitry Andric G->allocActions().push_back( 1795f757f3fSDimitry Andric {cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>( 1805f757f3fSDimitry Andric RegisterObjectSymbolTable, MachOHeaderAddr, SymTab)), 1815f757f3fSDimitry Andric cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>( 1825f757f3fSDimitry Andric DeregisterObjectSymbolTable, MachOHeaderAddr, SymTab))}); 1835f757f3fSDimitry Andric 1845f757f3fSDimitry Andric // 4. Add the deferred actions to the graph. 185bdd1243dSDimitry Andric std::move(DeferredAAs.begin(), DeferredAAs.end(), 186bdd1243dSDimitry Andric std::back_inserter(G->allocActions())); 187bdd1243dSDimitry Andric 188bdd1243dSDimitry Andric MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 189bdd1243dSDimitry Andric } 190bdd1243dSDimitry Andric 191bdd1243dSDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 192bdd1243dSDimitry Andric 193bdd1243dSDimitry Andric private: 194bdd1243dSDimitry Andric MachOPlatform &MOP; 195bdd1243dSDimitry Andric StringRef PlatformJDName; 196bdd1243dSDimitry Andric SymbolStringPtr CompleteBootstrapSymbol; 1975f757f3fSDimitry Andric SymbolTableVector SymTab; 198bdd1243dSDimitry Andric shared::AllocActions DeferredAAs; 1995f757f3fSDimitry Andric ExecutorAddr MachOHeaderAddr; 200bdd1243dSDimitry Andric ExecutorAddr PlatformBootstrap; 201bdd1243dSDimitry Andric ExecutorAddr PlatformShutdown; 202bdd1243dSDimitry Andric ExecutorAddr RegisterJITDylib; 203bdd1243dSDimitry Andric ExecutorAddr DeregisterJITDylib; 2045f757f3fSDimitry Andric ExecutorAddr RegisterObjectSymbolTable; 2055f757f3fSDimitry Andric ExecutorAddr DeregisterObjectSymbolTable; 206bdd1243dSDimitry Andric }; 207bdd1243dSDimitry Andric 20806c3fb27SDimitry Andric static StringRef ObjCRuntimeObjectSectionsData[] = { 209*0fca6ea1SDimitry Andric MachOObjCCatListSectionName, MachOObjCCatList2SectionName, 210*0fca6ea1SDimitry Andric MachOObjCClassListSectionName, MachOObjCClassRefsSectionName, 211*0fca6ea1SDimitry Andric MachOObjCConstSectionName, MachOObjCDataSectionName, 212*0fca6ea1SDimitry Andric MachOObjCProtoListSectionName, MachOObjCProtoRefsSectionName, 213*0fca6ea1SDimitry Andric MachOObjCNLCatListSectionName, MachOObjCNLClassListSectionName, 214*0fca6ea1SDimitry Andric MachOObjCSelRefsSectionName}; 215fe6060f1SDimitry Andric 21606c3fb27SDimitry Andric static StringRef ObjCRuntimeObjectSectionsText[] = { 21706c3fb27SDimitry Andric MachOObjCClassNameSectionName, MachOObjCMethNameSectionName, 21806c3fb27SDimitry Andric MachOObjCMethTypeSectionName, MachOSwift5TypesSectionName, 21906c3fb27SDimitry Andric MachOSwift5TypeRefSectionName, MachOSwift5FieldMetadataSectionName, 22006c3fb27SDimitry Andric MachOSwift5EntrySectionName, MachOSwift5ProtoSectionName, 22106c3fb27SDimitry Andric MachOSwift5ProtosSectionName}; 22206c3fb27SDimitry Andric 22306c3fb27SDimitry Andric static StringRef ObjCRuntimeObjectSectionName = 22406c3fb27SDimitry Andric "__llvm_jitlink_ObjCRuntimeRegistrationObject"; 22506c3fb27SDimitry Andric 22606c3fb27SDimitry Andric static StringRef ObjCImageInfoSymbolName = 22706c3fb27SDimitry Andric "__llvm_jitlink_macho_objc_imageinfo"; 2285ffd83dbSDimitry Andric 2295f757f3fSDimitry Andric struct ObjCImageInfoFlags { 2305f757f3fSDimitry Andric uint16_t SwiftABIVersion; 2315f757f3fSDimitry Andric uint16_t SwiftVersion; 2325f757f3fSDimitry Andric bool HasCategoryClassProperties; 2335f757f3fSDimitry Andric bool HasSignedObjCClassROs; 2345f757f3fSDimitry Andric 2355f757f3fSDimitry Andric static constexpr uint32_t SIGNED_CLASS_RO = (1 << 4); 2365f757f3fSDimitry Andric static constexpr uint32_t HAS_CATEGORY_CLASS_PROPERTIES = (1 << 6); 2375f757f3fSDimitry Andric 2385f757f3fSDimitry Andric explicit ObjCImageInfoFlags(uint32_t RawFlags) { 2395f757f3fSDimitry Andric HasSignedObjCClassROs = RawFlags & SIGNED_CLASS_RO; 2405f757f3fSDimitry Andric HasCategoryClassProperties = RawFlags & HAS_CATEGORY_CLASS_PROPERTIES; 2415f757f3fSDimitry Andric SwiftABIVersion = (RawFlags >> 8) & 0xFF; 2425f757f3fSDimitry Andric SwiftVersion = (RawFlags >> 16) & 0xFFFF; 2435f757f3fSDimitry Andric } 2445f757f3fSDimitry Andric 2455f757f3fSDimitry Andric uint32_t rawFlags() const { 2465f757f3fSDimitry Andric uint32_t Result = 0; 2475f757f3fSDimitry Andric if (HasCategoryClassProperties) 2485f757f3fSDimitry Andric Result |= HAS_CATEGORY_CLASS_PROPERTIES; 2495f757f3fSDimitry Andric if (HasSignedObjCClassROs) 2505f757f3fSDimitry Andric Result |= SIGNED_CLASS_RO; 2515f757f3fSDimitry Andric Result |= (SwiftABIVersion << 8); 2525f757f3fSDimitry Andric Result |= (SwiftVersion << 16); 2535f757f3fSDimitry Andric return Result; 2545f757f3fSDimitry Andric } 2555f757f3fSDimitry Andric }; 2565ffd83dbSDimitry Andric } // end anonymous namespace 2575ffd83dbSDimitry Andric 2585ffd83dbSDimitry Andric namespace llvm { 2595ffd83dbSDimitry Andric namespace orc { 2605ffd83dbSDimitry Andric 261*0fca6ea1SDimitry Andric std::optional<MachOPlatform::HeaderOptions::BuildVersionOpts> 262*0fca6ea1SDimitry Andric MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple(const Triple &TT, 263*0fca6ea1SDimitry Andric uint32_t MinOS, 264*0fca6ea1SDimitry Andric uint32_t SDK) { 265*0fca6ea1SDimitry Andric 266*0fca6ea1SDimitry Andric uint32_t Platform; 267*0fca6ea1SDimitry Andric switch (TT.getOS()) { 268*0fca6ea1SDimitry Andric case Triple::IOS: 269*0fca6ea1SDimitry Andric Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR 270*0fca6ea1SDimitry Andric : MachO::PLATFORM_IOS; 271*0fca6ea1SDimitry Andric break; 272*0fca6ea1SDimitry Andric case Triple::MacOSX: 273*0fca6ea1SDimitry Andric Platform = MachO::PLATFORM_MACOS; 274*0fca6ea1SDimitry Andric break; 275*0fca6ea1SDimitry Andric case Triple::TvOS: 276*0fca6ea1SDimitry Andric Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR 277*0fca6ea1SDimitry Andric : MachO::PLATFORM_TVOS; 278*0fca6ea1SDimitry Andric break; 279*0fca6ea1SDimitry Andric case Triple::WatchOS: 280*0fca6ea1SDimitry Andric Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR 281*0fca6ea1SDimitry Andric : MachO::PLATFORM_WATCHOS; 282*0fca6ea1SDimitry Andric break; 283*0fca6ea1SDimitry Andric case Triple::XROS: 284*0fca6ea1SDimitry Andric Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR 285*0fca6ea1SDimitry Andric : MachO::PLATFORM_XROS; 286*0fca6ea1SDimitry Andric break; 287*0fca6ea1SDimitry Andric default: 288*0fca6ea1SDimitry Andric return std::nullopt; 289*0fca6ea1SDimitry Andric } 290*0fca6ea1SDimitry Andric 291*0fca6ea1SDimitry Andric return MachOPlatform::HeaderOptions::BuildVersionOpts{Platform, MinOS, SDK}; 292*0fca6ea1SDimitry Andric } 293*0fca6ea1SDimitry Andric 2947a6dacacSDimitry Andric Expected<std::unique_ptr<MachOPlatform>> MachOPlatform::Create( 2957a6dacacSDimitry Andric ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 2967a6dacacSDimitry Andric JITDylib &PlatformJD, std::unique_ptr<DefinitionGenerator> OrcRuntime, 2977a6dacacSDimitry Andric HeaderOptions PlatformJDOpts, MachOHeaderMUBuilder BuildMachOHeaderMU, 298bdd1243dSDimitry Andric std::optional<SymbolAliasMap> RuntimeAliases) { 299fe6060f1SDimitry Andric 300fe6060f1SDimitry Andric // If the target is not supported then bail out immediately. 30106c3fb27SDimitry Andric if (!supportedTarget(ES.getTargetTriple())) 302fe6060f1SDimitry Andric return make_error<StringError>("Unsupported MachOPlatform triple: " + 30306c3fb27SDimitry Andric ES.getTargetTriple().str(), 3045ffd83dbSDimitry Andric inconvertibleErrorCode()); 3055ffd83dbSDimitry Andric 30606c3fb27SDimitry Andric auto &EPC = ES.getExecutorProcessControl(); 30706c3fb27SDimitry Andric 308fe6060f1SDimitry Andric // Create default aliases if the caller didn't supply any. 309fe6060f1SDimitry Andric if (!RuntimeAliases) 310fe6060f1SDimitry Andric RuntimeAliases = standardPlatformAliases(ES); 3115ffd83dbSDimitry Andric 312fe6060f1SDimitry Andric // Define the aliases. 313fe6060f1SDimitry Andric if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases)))) 314fe6060f1SDimitry Andric return std::move(Err); 3155ffd83dbSDimitry Andric 316fe6060f1SDimitry Andric // Add JIT-dispatch function support symbols. 31706c3fb27SDimitry Andric if (auto Err = PlatformJD.define( 31806c3fb27SDimitry Andric absoluteSymbols({{ES.intern("___orc_rt_jit_dispatch"), 31906c3fb27SDimitry Andric {EPC.getJITDispatchInfo().JITDispatchFunction, 320fe6060f1SDimitry Andric JITSymbolFlags::Exported}}, 321fe6060f1SDimitry Andric {ES.intern("___orc_rt_jit_dispatch_ctx"), 32206c3fb27SDimitry Andric {EPC.getJITDispatchInfo().JITDispatchContext, 323fe6060f1SDimitry Andric JITSymbolFlags::Exported}}}))) 324fe6060f1SDimitry Andric return std::move(Err); 3255ffd83dbSDimitry Andric 326fe6060f1SDimitry Andric // Create the instance. 327fe6060f1SDimitry Andric Error Err = Error::success(); 3287a6dacacSDimitry Andric auto P = std::unique_ptr<MachOPlatform>(new MachOPlatform( 3297a6dacacSDimitry Andric ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), 3307a6dacacSDimitry Andric std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU), Err)); 331fe6060f1SDimitry Andric if (Err) 332fe6060f1SDimitry Andric return std::move(Err); 333fe6060f1SDimitry Andric return std::move(P); 3345ffd83dbSDimitry Andric } 3355ffd83dbSDimitry Andric 33606c3fb27SDimitry Andric Expected<std::unique_ptr<MachOPlatform>> 33706c3fb27SDimitry Andric MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 33806c3fb27SDimitry Andric JITDylib &PlatformJD, const char *OrcRuntimePath, 3397a6dacacSDimitry Andric HeaderOptions PlatformJDOpts, 3405f757f3fSDimitry Andric MachOHeaderMUBuilder BuildMachOHeaderMU, 34106c3fb27SDimitry Andric std::optional<SymbolAliasMap> RuntimeAliases) { 34206c3fb27SDimitry Andric 34306c3fb27SDimitry Andric // Create a generator for the ORC runtime archive. 34406c3fb27SDimitry Andric auto OrcRuntimeArchiveGenerator = 34506c3fb27SDimitry Andric StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath); 34606c3fb27SDimitry Andric if (!OrcRuntimeArchiveGenerator) 34706c3fb27SDimitry Andric return OrcRuntimeArchiveGenerator.takeError(); 34806c3fb27SDimitry Andric 34906c3fb27SDimitry Andric return Create(ES, ObjLinkingLayer, PlatformJD, 35006c3fb27SDimitry Andric std::move(*OrcRuntimeArchiveGenerator), 3517a6dacacSDimitry Andric std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU), 3527a6dacacSDimitry Andric std::move(RuntimeAliases)); 35306c3fb27SDimitry Andric } 35406c3fb27SDimitry Andric 3555ffd83dbSDimitry Andric Error MachOPlatform::setupJITDylib(JITDylib &JD) { 3567a6dacacSDimitry Andric return setupJITDylib(JD, /*Opts=*/{}); 3577a6dacacSDimitry Andric } 3587a6dacacSDimitry Andric 3597a6dacacSDimitry Andric Error MachOPlatform::setupJITDylib(JITDylib &JD, HeaderOptions Opts) { 3607a6dacacSDimitry Andric if (auto Err = JD.define(BuildMachOHeaderMU(*this, std::move(Opts)))) 36181ad6265SDimitry Andric return Err; 36281ad6265SDimitry Andric 36381ad6265SDimitry Andric return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError(); 3645ffd83dbSDimitry Andric } 3655ffd83dbSDimitry Andric 36681ad6265SDimitry Andric Error MachOPlatform::teardownJITDylib(JITDylib &JD) { 36781ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 36881ad6265SDimitry Andric auto I = JITDylibToHeaderAddr.find(&JD); 36981ad6265SDimitry Andric if (I != JITDylibToHeaderAddr.end()) { 37081ad6265SDimitry Andric assert(HeaderAddrToJITDylib.count(I->second) && 37181ad6265SDimitry Andric "HeaderAddrToJITDylib missing entry"); 37281ad6265SDimitry Andric HeaderAddrToJITDylib.erase(I->second); 37381ad6265SDimitry Andric JITDylibToHeaderAddr.erase(I); 37481ad6265SDimitry Andric } 37581ad6265SDimitry Andric JITDylibToPThreadKey.erase(&JD); 37681ad6265SDimitry Andric return Error::success(); 37781ad6265SDimitry Andric } 37804eeddc0SDimitry Andric 379e8d8bef9SDimitry Andric Error MachOPlatform::notifyAdding(ResourceTracker &RT, 380e8d8bef9SDimitry Andric const MaterializationUnit &MU) { 381e8d8bef9SDimitry Andric auto &JD = RT.getJITDylib(); 3825ffd83dbSDimitry Andric const auto &InitSym = MU.getInitializerSymbol(); 3835ffd83dbSDimitry Andric if (!InitSym) 3845ffd83dbSDimitry Andric return Error::success(); 3855ffd83dbSDimitry Andric 3865ffd83dbSDimitry Andric RegisteredInitSymbols[&JD].add(InitSym, 3875ffd83dbSDimitry Andric SymbolLookupFlags::WeaklyReferencedSymbol); 3885ffd83dbSDimitry Andric LLVM_DEBUG({ 3895ffd83dbSDimitry Andric dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU " 3905ffd83dbSDimitry Andric << MU.getName() << "\n"; 3915ffd83dbSDimitry Andric }); 3925ffd83dbSDimitry Andric return Error::success(); 3935ffd83dbSDimitry Andric } 3945ffd83dbSDimitry Andric 395e8d8bef9SDimitry Andric Error MachOPlatform::notifyRemoving(ResourceTracker &RT) { 3965ffd83dbSDimitry Andric llvm_unreachable("Not supported yet"); 3975ffd83dbSDimitry Andric } 3985ffd83dbSDimitry Andric 399fe6060f1SDimitry Andric static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, 400fe6060f1SDimitry Andric ArrayRef<std::pair<const char *, const char *>> AL) { 401fe6060f1SDimitry Andric for (auto &KV : AL) { 402fe6060f1SDimitry Andric auto AliasName = ES.intern(KV.first); 403fe6060f1SDimitry Andric assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); 404fe6060f1SDimitry Andric Aliases[std::move(AliasName)] = {ES.intern(KV.second), 405fe6060f1SDimitry Andric JITSymbolFlags::Exported}; 406fe6060f1SDimitry Andric } 407fe6060f1SDimitry Andric } 4085ffd83dbSDimitry Andric 409fe6060f1SDimitry Andric SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) { 410fe6060f1SDimitry Andric SymbolAliasMap Aliases; 411fe6060f1SDimitry Andric addAliases(ES, Aliases, requiredCXXAliases()); 412fe6060f1SDimitry Andric addAliases(ES, Aliases, standardRuntimeUtilityAliases()); 413fe6060f1SDimitry Andric return Aliases; 414fe6060f1SDimitry Andric } 415fe6060f1SDimitry Andric 416fe6060f1SDimitry Andric ArrayRef<std::pair<const char *, const char *>> 417fe6060f1SDimitry Andric MachOPlatform::requiredCXXAliases() { 418fe6060f1SDimitry Andric static const std::pair<const char *, const char *> RequiredCXXAliases[] = { 419fe6060f1SDimitry Andric {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}}; 420fe6060f1SDimitry Andric 421fe6060f1SDimitry Andric return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases); 422fe6060f1SDimitry Andric } 423fe6060f1SDimitry Andric 424fe6060f1SDimitry Andric ArrayRef<std::pair<const char *, const char *>> 425fe6060f1SDimitry Andric MachOPlatform::standardRuntimeUtilityAliases() { 426fe6060f1SDimitry Andric static const std::pair<const char *, const char *> 427fe6060f1SDimitry Andric StandardRuntimeUtilityAliases[] = { 428fe6060f1SDimitry Andric {"___orc_rt_run_program", "___orc_rt_macho_run_program"}, 42981ad6265SDimitry Andric {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"}, 43081ad6265SDimitry Andric {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"}, 43181ad6265SDimitry Andric {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"}, 43281ad6265SDimitry Andric {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"}, 433fe6060f1SDimitry Andric {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}}; 434fe6060f1SDimitry Andric 435fe6060f1SDimitry Andric return ArrayRef<std::pair<const char *, const char *>>( 436fe6060f1SDimitry Andric StandardRuntimeUtilityAliases); 437fe6060f1SDimitry Andric } 438fe6060f1SDimitry Andric 439fe6060f1SDimitry Andric bool MachOPlatform::supportedTarget(const Triple &TT) { 440fe6060f1SDimitry Andric switch (TT.getArch()) { 441349cc55cSDimitry Andric case Triple::aarch64: 442fe6060f1SDimitry Andric case Triple::x86_64: 443fe6060f1SDimitry Andric return true; 444fe6060f1SDimitry Andric default: 445fe6060f1SDimitry Andric return false; 446fe6060f1SDimitry Andric } 447fe6060f1SDimitry Andric } 448fe6060f1SDimitry Andric 4495f757f3fSDimitry Andric jitlink::Edge::Kind MachOPlatform::getPointerEdgeKind(jitlink::LinkGraph &G) { 4505f757f3fSDimitry Andric switch (G.getTargetTriple().getArch()) { 4515f757f3fSDimitry Andric case Triple::aarch64: 4525f757f3fSDimitry Andric return jitlink::aarch64::Pointer64; 4535f757f3fSDimitry Andric case Triple::x86_64: 4545f757f3fSDimitry Andric return jitlink::x86_64::Pointer64; 4555f757f3fSDimitry Andric default: 4565f757f3fSDimitry Andric llvm_unreachable("Unsupported architecture"); 4575f757f3fSDimitry Andric } 4585f757f3fSDimitry Andric } 4595f757f3fSDimitry Andric 4605f757f3fSDimitry Andric MachOPlatform::MachOExecutorSymbolFlags 4615f757f3fSDimitry Andric MachOPlatform::flagsForSymbol(jitlink::Symbol &Sym) { 4625f757f3fSDimitry Andric MachOPlatform::MachOExecutorSymbolFlags Flags{}; 4635f757f3fSDimitry Andric if (Sym.getLinkage() == jitlink::Linkage::Weak) 4645f757f3fSDimitry Andric Flags |= MachOExecutorSymbolFlags::Weak; 4655f757f3fSDimitry Andric 4665f757f3fSDimitry Andric if (Sym.isCallable()) 4675f757f3fSDimitry Andric Flags |= MachOExecutorSymbolFlags::Callable; 4685f757f3fSDimitry Andric 4695f757f3fSDimitry Andric return Flags; 4705f757f3fSDimitry Andric } 4715f757f3fSDimitry Andric 472fe6060f1SDimitry Andric MachOPlatform::MachOPlatform( 473fe6060f1SDimitry Andric ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 474fe6060f1SDimitry Andric JITDylib &PlatformJD, 4755f757f3fSDimitry Andric std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, 4767a6dacacSDimitry Andric HeaderOptions PlatformJDOpts, MachOHeaderMUBuilder BuildMachOHeaderMU, 4777a6dacacSDimitry Andric Error &Err) 4785f757f3fSDimitry Andric : ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer), 4795f757f3fSDimitry Andric BuildMachOHeaderMU(std::move(BuildMachOHeaderMU)) { 480fe6060f1SDimitry Andric ErrorAsOutParameter _(&Err); 481fe6060f1SDimitry Andric ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this)); 482fe6060f1SDimitry Andric PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); 483fe6060f1SDimitry Andric 484bdd1243dSDimitry Andric BootstrapInfo BI; 485bdd1243dSDimitry Andric Bootstrap = &BI; 486bdd1243dSDimitry Andric 487bdd1243dSDimitry Andric // Bootstrap process -- here be phase-ordering dragons. 488bdd1243dSDimitry Andric // 489bdd1243dSDimitry Andric // The MachOPlatform class uses allocation actions to register metadata 490bdd1243dSDimitry Andric // sections with the ORC runtime, however the runtime contains metadata 491bdd1243dSDimitry Andric // registration functions that have their own metadata that they need to 492bdd1243dSDimitry Andric // register (e.g. the frame-info registration functions have frame-info). 493bdd1243dSDimitry Andric // We can't use an ordinary lookup to find these registration functions 494bdd1243dSDimitry Andric // because their address is needed during the link of the containing graph 495bdd1243dSDimitry Andric // itself (to build the allocation actions that will call the registration 496bdd1243dSDimitry Andric // functions). Further complicating the situation (a) the graph containing 497bdd1243dSDimitry Andric // the registration functions is allowed to depend on other graphs (e.g. the 4985f757f3fSDimitry Andric // graph containing the ORC runtime RTTI support) so we need to handle an 4995f757f3fSDimitry Andric // unknown set of dependencies during bootstrap, and (b) these graphs may 500bdd1243dSDimitry Andric // be linked concurrently if the user has installed a concurrent dispatcher. 501bdd1243dSDimitry Andric // 5025f757f3fSDimitry Andric // We satisfy these constraints by implementing a bootstrap phase during which 503bdd1243dSDimitry Andric // allocation actions generated by MachOPlatform are appended to a list of 504bdd1243dSDimitry Andric // deferred allocation actions, rather than to the graphs themselves. At the 505bdd1243dSDimitry Andric // end of the bootstrap process the deferred actions are attached to a final 506bdd1243dSDimitry Andric // "complete-bootstrap" graph that causes them to be run. 507bdd1243dSDimitry Andric // 508bdd1243dSDimitry Andric // The bootstrap steps are as follows: 509bdd1243dSDimitry Andric // 510bdd1243dSDimitry Andric // 1. Request the graph containing the mach header. This graph is guaranteed 511bdd1243dSDimitry Andric // not to have any metadata so the fact that the registration functions 512bdd1243dSDimitry Andric // are not available yet is not a problem. 513bdd1243dSDimitry Andric // 514bdd1243dSDimitry Andric // 2. Look up the registration functions and discard the results. This will 515bdd1243dSDimitry Andric // trigger linking of the graph containing these functions, and 516bdd1243dSDimitry Andric // consequently any graphs that it depends on. We do not use the lookup 517bdd1243dSDimitry Andric // result to find the addresses of the functions requested (as described 518bdd1243dSDimitry Andric // above the lookup will return too late for that), instead we capture the 519bdd1243dSDimitry Andric // addresses in a post-allocation pass injected by the platform runtime 520bdd1243dSDimitry Andric // during bootstrap only. 521bdd1243dSDimitry Andric // 522bdd1243dSDimitry Andric // 3. During bootstrap the MachOPlatformPlugin keeps a count of the number of 523bdd1243dSDimitry Andric // graphs being linked (potentially concurrently), and we block until all 524bdd1243dSDimitry Andric // of these graphs have completed linking. This is to avoid a race on the 525bdd1243dSDimitry Andric // deferred-actions vector: the lookup for the runtime registration 526bdd1243dSDimitry Andric // functions may return while some functions (those that are being 527bdd1243dSDimitry Andric // incidentally linked in, but aren't reachable via the runtime functions) 528bdd1243dSDimitry Andric // are still being linked, and we need to capture any allocation actions 529bdd1243dSDimitry Andric // for this incidental code before we proceed. 530bdd1243dSDimitry Andric // 531bdd1243dSDimitry Andric // 4. Once all active links are complete we transfer the deferred actions to 532bdd1243dSDimitry Andric // a newly added CompleteBootstrap graph and then request a symbol from 533bdd1243dSDimitry Andric // the CompleteBootstrap graph to trigger materialization. This will cause 534bdd1243dSDimitry Andric // all deferred actions to be run, and once this lookup returns we can 535bdd1243dSDimitry Andric // proceed. 536bdd1243dSDimitry Andric // 537bdd1243dSDimitry Andric // 5. Finally, we associate runtime support methods in MachOPlatform with 538bdd1243dSDimitry Andric // the corresponding jit-dispatch tag variables in the ORC runtime to make 539bdd1243dSDimitry Andric // the support methods callable. The bootstrap is now complete. 540bdd1243dSDimitry Andric 541bdd1243dSDimitry Andric // Step (1) Add header materialization unit and request. 5427a6dacacSDimitry Andric if ((Err = PlatformJD.define( 5437a6dacacSDimitry Andric this->BuildMachOHeaderMU(*this, std::move(PlatformJDOpts))))) 544bdd1243dSDimitry Andric return; 545bdd1243dSDimitry Andric if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError())) 546bdd1243dSDimitry Andric return; 547bdd1243dSDimitry Andric 548bdd1243dSDimitry Andric // Step (2) Request runtime registration functions to trigger 549bdd1243dSDimitry Andric // materialization.. 550bdd1243dSDimitry Andric if ((Err = ES.lookup(makeJITDylibSearchOrder(&PlatformJD), 551bdd1243dSDimitry Andric SymbolLookupSet( 552bdd1243dSDimitry Andric {PlatformBootstrap.Name, PlatformShutdown.Name, 553bdd1243dSDimitry Andric RegisterJITDylib.Name, DeregisterJITDylib.Name, 5545f757f3fSDimitry Andric RegisterObjectSymbolTable.Name, 5555f757f3fSDimitry Andric DeregisterObjectSymbolTable.Name, 556bdd1243dSDimitry Andric RegisterObjectPlatformSections.Name, 557bdd1243dSDimitry Andric DeregisterObjectPlatformSections.Name, 558bdd1243dSDimitry Andric CreatePThreadKey.Name})) 559bdd1243dSDimitry Andric .takeError())) 560bdd1243dSDimitry Andric return; 561bdd1243dSDimitry Andric 562bdd1243dSDimitry Andric // Step (3) Wait for any incidental linker work to complete. 563bdd1243dSDimitry Andric { 564bdd1243dSDimitry Andric std::unique_lock<std::mutex> Lock(BI.Mutex); 565bdd1243dSDimitry Andric BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; }); 566bdd1243dSDimitry Andric Bootstrap = nullptr; 567bdd1243dSDimitry Andric } 568bdd1243dSDimitry Andric 569bdd1243dSDimitry Andric // Step (4) Add complete-bootstrap materialization unit and request. 570bdd1243dSDimitry Andric auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap"); 571bdd1243dSDimitry Andric if ((Err = PlatformJD.define( 572bdd1243dSDimitry Andric std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>( 573bdd1243dSDimitry Andric *this, PlatformJD.getName(), BootstrapCompleteSymbol, 5745f757f3fSDimitry Andric std::move(BI.SymTab), std::move(BI.DeferredAAs), 5755f757f3fSDimitry Andric BI.MachOHeaderAddr, PlatformBootstrap.Addr, 576bdd1243dSDimitry Andric PlatformShutdown.Addr, RegisterJITDylib.Addr, 5775f757f3fSDimitry Andric DeregisterJITDylib.Addr, RegisterObjectSymbolTable.Addr, 5785f757f3fSDimitry Andric DeregisterObjectSymbolTable.Addr)))) 579bdd1243dSDimitry Andric return; 580bdd1243dSDimitry Andric if ((Err = ES.lookup(makeJITDylibSearchOrder( 581bdd1243dSDimitry Andric &PlatformJD, JITDylibLookupFlags::MatchAllSymbols), 582bdd1243dSDimitry Andric std::move(BootstrapCompleteSymbol)) 583bdd1243dSDimitry Andric .takeError())) 584bdd1243dSDimitry Andric return; 585bdd1243dSDimitry Andric 586bdd1243dSDimitry Andric // (5) Associate runtime support functions. 587bdd1243dSDimitry Andric if ((Err = associateRuntimeSupportFunctions())) 588349cc55cSDimitry Andric return; 589349cc55cSDimitry Andric } 590349cc55cSDimitry Andric 591bdd1243dSDimitry Andric Error MachOPlatform::associateRuntimeSupportFunctions() { 592fe6060f1SDimitry Andric ExecutionSession::JITDispatchHandlerAssociationMap WFs; 593fe6060f1SDimitry Andric 59481ad6265SDimitry Andric using PushInitializersSPSSig = 59581ad6265SDimitry Andric SPSExpected<SPSMachOJITDylibDepInfoMap>(SPSExecutorAddr); 59681ad6265SDimitry Andric WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] = 59781ad6265SDimitry Andric ES.wrapAsyncWithSPS<PushInitializersSPSSig>( 59881ad6265SDimitry Andric this, &MachOPlatform::rt_pushInitializers); 599fe6060f1SDimitry Andric 6005f757f3fSDimitry Andric using PushSymbolsSPSSig = 6015f757f3fSDimitry Andric SPSError(SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>); 6025f757f3fSDimitry Andric WFs[ES.intern("___orc_rt_macho_push_symbols_tag")] = 6035f757f3fSDimitry Andric ES.wrapAsyncWithSPS<PushSymbolsSPSSig>(this, 6045f757f3fSDimitry Andric &MachOPlatform::rt_pushSymbols); 605fe6060f1SDimitry Andric 606fe6060f1SDimitry Andric return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs)); 607fe6060f1SDimitry Andric } 608fe6060f1SDimitry Andric 60981ad6265SDimitry Andric void MachOPlatform::pushInitializersLoop( 61081ad6265SDimitry Andric PushInitializersSendResultFn SendResult, JITDylibSP JD) { 6115ffd83dbSDimitry Andric DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols; 61281ad6265SDimitry Andric DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap; 61381ad6265SDimitry Andric SmallVector<JITDylib *, 16> Worklist({JD.get()}); 61481ad6265SDimitry Andric 6155ffd83dbSDimitry Andric ES.runSessionLocked([&]() { 61681ad6265SDimitry Andric while (!Worklist.empty()) { 61781ad6265SDimitry Andric // FIXME: Check for defunct dylibs. 61881ad6265SDimitry Andric 61981ad6265SDimitry Andric auto DepJD = Worklist.back(); 62081ad6265SDimitry Andric Worklist.pop_back(); 62181ad6265SDimitry Andric 62281ad6265SDimitry Andric // If we've already visited this JITDylib on this iteration then continue. 62381ad6265SDimitry Andric if (JDDepMap.count(DepJD)) 62481ad6265SDimitry Andric continue; 62581ad6265SDimitry Andric 62681ad6265SDimitry Andric // Add dep info. 62781ad6265SDimitry Andric auto &DM = JDDepMap[DepJD]; 62881ad6265SDimitry Andric DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) { 62981ad6265SDimitry Andric for (auto &KV : O) { 63081ad6265SDimitry Andric if (KV.first == DepJD) 63181ad6265SDimitry Andric continue; 63281ad6265SDimitry Andric DM.push_back(KV.first); 63381ad6265SDimitry Andric Worklist.push_back(KV.first); 63481ad6265SDimitry Andric } 63581ad6265SDimitry Andric }); 63681ad6265SDimitry Andric 63781ad6265SDimitry Andric // Add any registered init symbols. 63881ad6265SDimitry Andric auto RISItr = RegisteredInitSymbols.find(DepJD); 6395ffd83dbSDimitry Andric if (RISItr != RegisteredInitSymbols.end()) { 64081ad6265SDimitry Andric NewInitSymbols[DepJD] = std::move(RISItr->second); 6415ffd83dbSDimitry Andric RegisteredInitSymbols.erase(RISItr); 6425ffd83dbSDimitry Andric } 6435ffd83dbSDimitry Andric } 6445ffd83dbSDimitry Andric }); 6455ffd83dbSDimitry Andric 64681ad6265SDimitry Andric // If there are no further init symbols to look up then send the link order 64781ad6265SDimitry Andric // (as a list of header addresses) to the caller. 648fe6060f1SDimitry Andric if (NewInitSymbols.empty()) { 64981ad6265SDimitry Andric 65081ad6265SDimitry Andric // To make the list intelligible to the runtime we need to convert all 651bdd1243dSDimitry Andric // JITDylib pointers to their header addresses. Only include JITDylibs 652bdd1243dSDimitry Andric // that appear in the JITDylibToHeaderAddr map (i.e. those that have been 653bdd1243dSDimitry Andric // through setupJITDylib) -- bare JITDylibs aren't managed by the platform. 65481ad6265SDimitry Andric DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs; 65581ad6265SDimitry Andric HeaderAddrs.reserve(JDDepMap.size()); 65681ad6265SDimitry Andric { 65781ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 65881ad6265SDimitry Andric for (auto &KV : JDDepMap) { 65981ad6265SDimitry Andric auto I = JITDylibToHeaderAddr.find(KV.first); 660bdd1243dSDimitry Andric if (I != JITDylibToHeaderAddr.end()) 66181ad6265SDimitry Andric HeaderAddrs[KV.first] = I->second; 66281ad6265SDimitry Andric } 66381ad6265SDimitry Andric } 66481ad6265SDimitry Andric 66581ad6265SDimitry Andric // Build the dep info map to return. 66681ad6265SDimitry Andric MachOJITDylibDepInfoMap DIM; 66781ad6265SDimitry Andric DIM.reserve(JDDepMap.size()); 66881ad6265SDimitry Andric for (auto &KV : JDDepMap) { 669bdd1243dSDimitry Andric auto HI = HeaderAddrs.find(KV.first); 670bdd1243dSDimitry Andric // Skip unmanaged JITDylibs. 671bdd1243dSDimitry Andric if (HI == HeaderAddrs.end()) 672bdd1243dSDimitry Andric continue; 673bdd1243dSDimitry Andric auto H = HI->second; 67481ad6265SDimitry Andric MachOJITDylibDepInfo DepInfo; 67581ad6265SDimitry Andric for (auto &Dep : KV.second) { 676bdd1243dSDimitry Andric auto HJ = HeaderAddrs.find(Dep); 677bdd1243dSDimitry Andric if (HJ != HeaderAddrs.end()) 678bdd1243dSDimitry Andric DepInfo.DepHeaders.push_back(HJ->second); 67981ad6265SDimitry Andric } 68081ad6265SDimitry Andric DIM.push_back(std::make_pair(H, std::move(DepInfo))); 68181ad6265SDimitry Andric } 68281ad6265SDimitry Andric SendResult(DIM); 683e8d8bef9SDimitry Andric return; 6845ffd83dbSDimitry Andric } 6855ffd83dbSDimitry Andric 686fe6060f1SDimitry Andric // Otherwise issue a lookup and re-run this phase when it completes. 687fe6060f1SDimitry Andric lookupInitSymbolsAsync( 688bdd1243dSDimitry Andric [this, SendResult = std::move(SendResult), JD](Error Err) mutable { 689fe6060f1SDimitry Andric if (Err) 690fe6060f1SDimitry Andric SendResult(std::move(Err)); 691fe6060f1SDimitry Andric else 69281ad6265SDimitry Andric pushInitializersLoop(std::move(SendResult), JD); 693fe6060f1SDimitry Andric }, 694fe6060f1SDimitry Andric ES, std::move(NewInitSymbols)); 695fe6060f1SDimitry Andric } 696fe6060f1SDimitry Andric 69781ad6265SDimitry Andric void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult, 69881ad6265SDimitry Andric ExecutorAddr JDHeaderAddr) { 69981ad6265SDimitry Andric JITDylibSP JD; 700fe6060f1SDimitry Andric { 701fe6060f1SDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 70281ad6265SDimitry Andric auto I = HeaderAddrToJITDylib.find(JDHeaderAddr); 703fe6060f1SDimitry Andric if (I != HeaderAddrToJITDylib.end()) 704fe6060f1SDimitry Andric JD = I->second; 705fe6060f1SDimitry Andric } 706fe6060f1SDimitry Andric 707fe6060f1SDimitry Andric LLVM_DEBUG({ 70881ad6265SDimitry Andric dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") "; 70981ad6265SDimitry Andric if (JD) 71081ad6265SDimitry Andric dbgs() << "pushing initializers for " << JD->getName() << "\n"; 71181ad6265SDimitry Andric else 71281ad6265SDimitry Andric dbgs() << "No JITDylib for header address.\n"; 713fe6060f1SDimitry Andric }); 71481ad6265SDimitry Andric 71581ad6265SDimitry Andric if (!JD) { 71606c3fb27SDimitry Andric SendResult(make_error<StringError>("No JITDylib with header addr " + 71706c3fb27SDimitry Andric formatv("{0:x}", JDHeaderAddr), 718fe6060f1SDimitry Andric inconvertibleErrorCode())); 719fe6060f1SDimitry Andric return; 720fe6060f1SDimitry Andric } 721fe6060f1SDimitry Andric 72281ad6265SDimitry Andric pushInitializersLoop(std::move(SendResult), JD); 723fe6060f1SDimitry Andric } 724fe6060f1SDimitry Andric 7255f757f3fSDimitry Andric void MachOPlatform::rt_pushSymbols( 7265f757f3fSDimitry Andric PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle, 7275f757f3fSDimitry Andric const std::vector<std::pair<StringRef, bool>> &SymbolNames) { 728fe6060f1SDimitry Andric 729fe6060f1SDimitry Andric JITDylib *JD = nullptr; 730fe6060f1SDimitry Andric 731fe6060f1SDimitry Andric { 732fe6060f1SDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 73304eeddc0SDimitry Andric auto I = HeaderAddrToJITDylib.find(Handle); 734fe6060f1SDimitry Andric if (I != HeaderAddrToJITDylib.end()) 735fe6060f1SDimitry Andric JD = I->second; 736fe6060f1SDimitry Andric } 7375f757f3fSDimitry Andric LLVM_DEBUG({ 7385f757f3fSDimitry Andric dbgs() << "MachOPlatform::rt_pushSymbols("; 7395f757f3fSDimitry Andric if (JD) 7405f757f3fSDimitry Andric dbgs() << "\"" << JD->getName() << "\", [ "; 7415f757f3fSDimitry Andric else 7425f757f3fSDimitry Andric dbgs() << "<invalid handle " << Handle << ">, [ "; 7435f757f3fSDimitry Andric for (auto &Name : SymbolNames) 7445f757f3fSDimitry Andric dbgs() << "\"" << Name.first << "\" "; 7455f757f3fSDimitry Andric dbgs() << "])\n"; 7465f757f3fSDimitry Andric }); 747fe6060f1SDimitry Andric 748fe6060f1SDimitry Andric if (!JD) { 749fe6060f1SDimitry Andric SendResult(make_error<StringError>("No JITDylib associated with handle " + 75006c3fb27SDimitry Andric formatv("{0:x}", Handle), 751fe6060f1SDimitry Andric inconvertibleErrorCode())); 752fe6060f1SDimitry Andric return; 753fe6060f1SDimitry Andric } 754fe6060f1SDimitry Andric 7555f757f3fSDimitry Andric SymbolLookupSet LS; 7565f757f3fSDimitry Andric for (auto &[Name, Required] : SymbolNames) 7575f757f3fSDimitry Andric LS.add(ES.intern(Name), Required 7585f757f3fSDimitry Andric ? SymbolLookupFlags::RequiredSymbol 7595f757f3fSDimitry Andric : SymbolLookupFlags::WeaklyReferencedSymbol); 760fe6060f1SDimitry Andric 761fe6060f1SDimitry Andric ES.lookup( 762fe6060f1SDimitry Andric LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 7635f757f3fSDimitry Andric std::move(LS), SymbolState::Ready, 7645f757f3fSDimitry Andric [SendResult = std::move(SendResult)](Expected<SymbolMap> Result) mutable { 7655f757f3fSDimitry Andric SendResult(Result.takeError()); 7665f757f3fSDimitry Andric }, 7675f757f3fSDimitry Andric NoDependenciesToRegister); 768fe6060f1SDimitry Andric } 769fe6060f1SDimitry Andric 770fe6060f1SDimitry Andric Expected<uint64_t> MachOPlatform::createPThreadKey() { 771bdd1243dSDimitry Andric if (!CreatePThreadKey.Addr) 772fe6060f1SDimitry Andric return make_error<StringError>( 773fe6060f1SDimitry Andric "Attempting to create pthread key in target, but runtime support has " 774fe6060f1SDimitry Andric "not been loaded yet", 775fe6060f1SDimitry Andric inconvertibleErrorCode()); 776fe6060f1SDimitry Andric 777fe6060f1SDimitry Andric Expected<uint64_t> Result(0); 778fe6060f1SDimitry Andric if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>( 779bdd1243dSDimitry Andric CreatePThreadKey.Addr, Result)) 780fe6060f1SDimitry Andric return std::move(Err); 781fe6060f1SDimitry Andric return Result; 782fe6060f1SDimitry Andric } 783fe6060f1SDimitry Andric 784fe6060f1SDimitry Andric void MachOPlatform::MachOPlatformPlugin::modifyPassConfig( 785fe6060f1SDimitry Andric MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 786fe6060f1SDimitry Andric jitlink::PassConfiguration &Config) { 787fe6060f1SDimitry Andric 788bdd1243dSDimitry Andric using namespace jitlink; 789bdd1243dSDimitry Andric 790bdd1243dSDimitry Andric bool InBootstrapPhase = 791bdd1243dSDimitry Andric &MR.getTargetJITDylib() == &MP.PlatformJD && MP.Bootstrap; 792bdd1243dSDimitry Andric 793bdd1243dSDimitry Andric // If we're in the bootstrap phase then increment the active graphs. 794bdd1243dSDimitry Andric if (InBootstrapPhase) { 795bdd1243dSDimitry Andric Config.PrePrunePasses.push_back( 796bdd1243dSDimitry Andric [this](LinkGraph &G) { return bootstrapPipelineStart(G); }); 797bdd1243dSDimitry Andric Config.PostAllocationPasses.push_back([this](LinkGraph &G) { 798bdd1243dSDimitry Andric return bootstrapPipelineRecordRuntimeFunctions(G); 799bdd1243dSDimitry Andric }); 800bdd1243dSDimitry Andric } 801349cc55cSDimitry Andric 802349cc55cSDimitry Andric // --- Handle Initializers --- 803349cc55cSDimitry Andric if (auto InitSymbol = MR.getInitializerSymbol()) { 804349cc55cSDimitry Andric 805349cc55cSDimitry Andric // If the initializer symbol is the MachOHeader start symbol then just 806349cc55cSDimitry Andric // register it and then bail out -- the header materialization unit 807349cc55cSDimitry Andric // definitely doesn't need any other passes. 808bdd1243dSDimitry Andric if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) { 809bdd1243dSDimitry Andric Config.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) { 810349cc55cSDimitry Andric return associateJITDylibHeaderSymbol(G, MR); 811349cc55cSDimitry Andric }); 812fe6060f1SDimitry Andric return; 813fe6060f1SDimitry Andric } 814fe6060f1SDimitry Andric 815349cc55cSDimitry Andric // If the object contains an init symbol other than the header start symbol 816349cc55cSDimitry Andric // then add passes to preserve, process and register the init 817349cc55cSDimitry Andric // sections/symbols. 818bdd1243dSDimitry Andric Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) { 81906c3fb27SDimitry Andric if (auto Err = preserveImportantSections(G, MR)) 820349cc55cSDimitry Andric return Err; 821349cc55cSDimitry Andric return processObjCImageInfo(G, MR); 822349cc55cSDimitry Andric }); 82306c3fb27SDimitry Andric Config.PostPrunePasses.push_back( 82406c3fb27SDimitry Andric [this](LinkGraph &G) { return createObjCRuntimeObject(G); }); 82506c3fb27SDimitry Andric Config.PostAllocationPasses.push_back( 82606c3fb27SDimitry Andric [this, &MR](LinkGraph &G) { return populateObjCRuntimeObject(G, MR); }); 827349cc55cSDimitry Andric } 828349cc55cSDimitry Andric 829349cc55cSDimitry Andric // Insert TLV lowering at the start of the PostPrunePasses, since we want 830349cc55cSDimitry Andric // it to run before GOT/PLT lowering. 831349cc55cSDimitry Andric Config.PostPrunePasses.insert( 832349cc55cSDimitry Andric Config.PostPrunePasses.begin(), 833bdd1243dSDimitry Andric [this, &JD = MR.getTargetJITDylib()](LinkGraph &G) { 834349cc55cSDimitry Andric return fixTLVSectionsAndEdges(G, JD); 835349cc55cSDimitry Andric }); 836349cc55cSDimitry Andric 8375f757f3fSDimitry Andric // Add symbol table prepare and register passes: These will add strings for 8385f757f3fSDimitry Andric // all symbols to the c-strings section, and build a symbol table registration 8395f757f3fSDimitry Andric // call. 8405f757f3fSDimitry Andric auto JITSymTabInfo = std::make_shared<JITSymTabVector>(); 8415f757f3fSDimitry Andric Config.PostPrunePasses.push_back([this, JITSymTabInfo](LinkGraph &G) { 8425f757f3fSDimitry Andric return prepareSymbolTableRegistration(G, *JITSymTabInfo); 8435f757f3fSDimitry Andric }); 8445f757f3fSDimitry Andric Config.PostFixupPasses.push_back([this, &MR, JITSymTabInfo, 8455f757f3fSDimitry Andric InBootstrapPhase](LinkGraph &G) { 8465f757f3fSDimitry Andric return addSymbolTableRegistration(G, MR, *JITSymTabInfo, InBootstrapPhase); 8475f757f3fSDimitry Andric }); 8485f757f3fSDimitry Andric 84981ad6265SDimitry Andric // Add a pass to register the final addresses of any special sections in the 85081ad6265SDimitry Andric // object with the runtime. 85181ad6265SDimitry Andric Config.PostAllocationPasses.push_back( 852bdd1243dSDimitry Andric [this, &JD = MR.getTargetJITDylib(), InBootstrapPhase](LinkGraph &G) { 853bdd1243dSDimitry Andric return registerObjectPlatformSections(G, JD, InBootstrapPhase); 85481ad6265SDimitry Andric }); 855bdd1243dSDimitry Andric 856bdd1243dSDimitry Andric // If we're in the bootstrap phase then steal allocation actions and then 857bdd1243dSDimitry Andric // decrement the active graphs. 858bdd1243dSDimitry Andric if (InBootstrapPhase) 859bdd1243dSDimitry Andric Config.PostFixupPasses.push_back( 860bdd1243dSDimitry Andric [this](LinkGraph &G) { return bootstrapPipelineEnd(G); }); 861fe6060f1SDimitry Andric } 862fe6060f1SDimitry Andric 863fe6060f1SDimitry Andric ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap 864fe6060f1SDimitry Andric MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies( 8655ffd83dbSDimitry Andric MaterializationResponsibility &MR) { 866fe6060f1SDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex); 8675ffd83dbSDimitry Andric auto I = InitSymbolDeps.find(&MR); 8685ffd83dbSDimitry Andric if (I != InitSymbolDeps.end()) { 869fe6060f1SDimitry Andric SyntheticSymbolDependenciesMap Result; 8705ffd83dbSDimitry Andric Result[MR.getInitializerSymbol()] = std::move(I->second); 8715ffd83dbSDimitry Andric InitSymbolDeps.erase(&MR); 8725ffd83dbSDimitry Andric return Result; 8735ffd83dbSDimitry Andric } 874fe6060f1SDimitry Andric return SyntheticSymbolDependenciesMap(); 8755ffd83dbSDimitry Andric } 8765ffd83dbSDimitry Andric 877bdd1243dSDimitry Andric Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineStart( 878bdd1243dSDimitry Andric jitlink::LinkGraph &G) { 879bdd1243dSDimitry Andric // Increment the active graphs count in BootstrapInfo. 880bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex); 881bdd1243dSDimitry Andric ++MP.Bootstrap.load()->ActiveGraphs; 882bdd1243dSDimitry Andric return Error::success(); 883bdd1243dSDimitry Andric } 884bdd1243dSDimitry Andric 885bdd1243dSDimitry Andric Error MachOPlatform::MachOPlatformPlugin:: 886bdd1243dSDimitry Andric bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) { 887bdd1243dSDimitry Andric // Record bootstrap function names. 888bdd1243dSDimitry Andric std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = { 889bdd1243dSDimitry Andric {*MP.MachOHeaderStartSymbol, &MP.Bootstrap.load()->MachOHeaderAddr}, 890bdd1243dSDimitry Andric {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr}, 891bdd1243dSDimitry Andric {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr}, 892bdd1243dSDimitry Andric {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr}, 893bdd1243dSDimitry Andric {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr}, 8945f757f3fSDimitry Andric {*MP.RegisterObjectSymbolTable.Name, &MP.RegisterObjectSymbolTable.Addr}, 8955f757f3fSDimitry Andric {*MP.DeregisterObjectSymbolTable.Name, 8965f757f3fSDimitry Andric &MP.DeregisterObjectSymbolTable.Addr}, 897bdd1243dSDimitry Andric {*MP.RegisterObjectPlatformSections.Name, 898bdd1243dSDimitry Andric &MP.RegisterObjectPlatformSections.Addr}, 899bdd1243dSDimitry Andric {*MP.DeregisterObjectPlatformSections.Name, 900bdd1243dSDimitry Andric &MP.DeregisterObjectPlatformSections.Addr}, 90106c3fb27SDimitry Andric {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr}, 90206c3fb27SDimitry Andric {*MP.RegisterObjCRuntimeObject.Name, &MP.RegisterObjCRuntimeObject.Addr}, 90306c3fb27SDimitry Andric {*MP.DeregisterObjCRuntimeObject.Name, 90406c3fb27SDimitry Andric &MP.DeregisterObjCRuntimeObject.Addr}}; 905bdd1243dSDimitry Andric 906bdd1243dSDimitry Andric bool RegisterMachOHeader = false; 907bdd1243dSDimitry Andric 908bdd1243dSDimitry Andric for (auto *Sym : G.defined_symbols()) { 909bdd1243dSDimitry Andric for (auto &RTSym : RuntimeSymbols) { 910bdd1243dSDimitry Andric if (Sym->hasName() && Sym->getName() == RTSym.first) { 911bdd1243dSDimitry Andric if (*RTSym.second) 912bdd1243dSDimitry Andric return make_error<StringError>( 913bdd1243dSDimitry Andric "Duplicate " + RTSym.first + 914bdd1243dSDimitry Andric " detected during MachOPlatform bootstrap", 915bdd1243dSDimitry Andric inconvertibleErrorCode()); 916bdd1243dSDimitry Andric 917bdd1243dSDimitry Andric if (Sym->getName() == *MP.MachOHeaderStartSymbol) 918bdd1243dSDimitry Andric RegisterMachOHeader = true; 919bdd1243dSDimitry Andric 920bdd1243dSDimitry Andric *RTSym.second = Sym->getAddress(); 921bdd1243dSDimitry Andric } 922bdd1243dSDimitry Andric } 923bdd1243dSDimitry Andric } 924bdd1243dSDimitry Andric 925bdd1243dSDimitry Andric if (RegisterMachOHeader) { 926bdd1243dSDimitry Andric // If this graph defines the macho header symbol then create the internal 927bdd1243dSDimitry Andric // mapping between it and PlatformJD. 928bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 929bdd1243dSDimitry Andric MP.JITDylibToHeaderAddr[&MP.PlatformJD] = 930bdd1243dSDimitry Andric MP.Bootstrap.load()->MachOHeaderAddr; 931bdd1243dSDimitry Andric MP.HeaderAddrToJITDylib[MP.Bootstrap.load()->MachOHeaderAddr] = 932bdd1243dSDimitry Andric &MP.PlatformJD; 933bdd1243dSDimitry Andric } 934bdd1243dSDimitry Andric 935bdd1243dSDimitry Andric return Error::success(); 936bdd1243dSDimitry Andric } 937bdd1243dSDimitry Andric 938bdd1243dSDimitry Andric Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd( 939bdd1243dSDimitry Andric jitlink::LinkGraph &G) { 940bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex); 941bdd1243dSDimitry Andric assert(MP.Bootstrap && "DeferredAAs reset before bootstrap completed"); 942bdd1243dSDimitry Andric --MP.Bootstrap.load()->ActiveGraphs; 943bdd1243dSDimitry Andric // Notify Bootstrap->CV while holding the mutex because the mutex is 944bdd1243dSDimitry Andric // also keeping Bootstrap->CV alive. 945bdd1243dSDimitry Andric if (MP.Bootstrap.load()->ActiveGraphs == 0) 946bdd1243dSDimitry Andric MP.Bootstrap.load()->CV.notify_all(); 947bdd1243dSDimitry Andric return Error::success(); 948bdd1243dSDimitry Andric } 949bdd1243dSDimitry Andric 950349cc55cSDimitry Andric Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol( 951349cc55cSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 952fe6060f1SDimitry Andric auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 953fe6060f1SDimitry Andric return Sym->getName() == *MP.MachOHeaderStartSymbol; 954fe6060f1SDimitry Andric }); 955349cc55cSDimitry Andric assert(I != G.defined_symbols().end() && "Missing MachO header start symbol"); 956349cc55cSDimitry Andric 957349cc55cSDimitry Andric auto &JD = MR.getTargetJITDylib(); 958fe6060f1SDimitry Andric std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 95904eeddc0SDimitry Andric auto HeaderAddr = (*I)->getAddress(); 96081ad6265SDimitry Andric MP.JITDylibToHeaderAddr[&JD] = HeaderAddr; 961fe6060f1SDimitry Andric MP.HeaderAddrToJITDylib[HeaderAddr] = &JD; 962bdd1243dSDimitry Andric // We can unconditionally add these actions to the Graph because this pass 963bdd1243dSDimitry Andric // isn't used during bootstrap. 96481ad6265SDimitry Andric G.allocActions().push_back( 96581ad6265SDimitry Andric {cantFail( 96681ad6265SDimitry Andric WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>( 967bdd1243dSDimitry Andric MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)), 96881ad6265SDimitry Andric cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 969bdd1243dSDimitry Andric MP.DeregisterJITDylib.Addr, HeaderAddr))}); 970fe6060f1SDimitry Andric return Error::success(); 971fe6060f1SDimitry Andric } 972fe6060f1SDimitry Andric 97306c3fb27SDimitry Andric Error MachOPlatform::MachOPlatformPlugin::preserveImportantSections( 974fe6060f1SDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 97506c3fb27SDimitry Andric // __objc_imageinfo is "important": we want to preserve it and record its 97606c3fb27SDimitry Andric // address in the first graph that it appears in, then verify and discard it 97706c3fb27SDimitry Andric // in all subsequent graphs. In this pass we preserve unconditionally -- we'll 97806c3fb27SDimitry Andric // manually throw it away in the processObjCImageInfo pass. 97906c3fb27SDimitry Andric if (auto *ObjCImageInfoSec = 98006c3fb27SDimitry Andric G.findSectionByName(MachOObjCImageInfoSectionName)) { 98106c3fb27SDimitry Andric if (ObjCImageInfoSec->blocks_size() != 1) 98206c3fb27SDimitry Andric return make_error<StringError>( 98306c3fb27SDimitry Andric "In " + G.getName() + 98406c3fb27SDimitry Andric "__DATA,__objc_imageinfo contains multiple blocks", 98506c3fb27SDimitry Andric inconvertibleErrorCode()); 98606c3fb27SDimitry Andric G.addAnonymousSymbol(**ObjCImageInfoSec->blocks().begin(), 0, 0, false, 98706c3fb27SDimitry Andric true); 988fe6060f1SDimitry Andric 98906c3fb27SDimitry Andric for (auto *B : ObjCImageInfoSec->blocks()) 99006c3fb27SDimitry Andric if (!B->edges_empty()) 99106c3fb27SDimitry Andric return make_error<StringError>("In " + G.getName() + ", " + 99206c3fb27SDimitry Andric MachOObjCImageInfoSectionName + 99306c3fb27SDimitry Andric " contains references to symbols", 99406c3fb27SDimitry Andric inconvertibleErrorCode()); 99506c3fb27SDimitry Andric } 99606c3fb27SDimitry Andric 99706c3fb27SDimitry Andric // Init sections are important: We need to preserve them and so that their 99806c3fb27SDimitry Andric // addresses can be captured and reported to the ORC runtime in 99906c3fb27SDimitry Andric // registerObjectPlatformSections. 1000fe6060f1SDimitry Andric JITLinkSymbolSet InitSectionSymbols; 100106c3fb27SDimitry Andric for (auto &InitSectionName : MachOInitSectionNames) { 100206c3fb27SDimitry Andric // Skip ObjCImageInfo -- this shouldn't have any dependencies, and we may 100306c3fb27SDimitry Andric // remove it later. 100406c3fb27SDimitry Andric if (InitSectionName == MachOObjCImageInfoSectionName) 100506c3fb27SDimitry Andric continue; 100606c3fb27SDimitry Andric 1007fe6060f1SDimitry Andric // Skip non-init sections. 1008fe6060f1SDimitry Andric auto *InitSection = G.findSectionByName(InitSectionName); 1009fe6060f1SDimitry Andric if (!InitSection) 1010fe6060f1SDimitry Andric continue; 1011fe6060f1SDimitry Andric 1012fe6060f1SDimitry Andric // Make a pass over live symbols in the section: those blocks are already 1013fe6060f1SDimitry Andric // preserved. 1014fe6060f1SDimitry Andric DenseSet<jitlink::Block *> AlreadyLiveBlocks; 1015fe6060f1SDimitry Andric for (auto &Sym : InitSection->symbols()) { 1016fe6060f1SDimitry Andric auto &B = Sym->getBlock(); 1017fe6060f1SDimitry Andric if (Sym->isLive() && Sym->getOffset() == 0 && 1018fe6060f1SDimitry Andric Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) { 1019fe6060f1SDimitry Andric InitSectionSymbols.insert(Sym); 1020fe6060f1SDimitry Andric AlreadyLiveBlocks.insert(&B); 10215ffd83dbSDimitry Andric } 10225ffd83dbSDimitry Andric } 10235ffd83dbSDimitry Andric 1024fe6060f1SDimitry Andric // Add anonymous symbols to preserve any not-already-preserved blocks. 1025fe6060f1SDimitry Andric for (auto *B : InitSection->blocks()) 1026fe6060f1SDimitry Andric if (!AlreadyLiveBlocks.count(B)) 1027fe6060f1SDimitry Andric InitSectionSymbols.insert( 1028fe6060f1SDimitry Andric &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true)); 1029fe6060f1SDimitry Andric } 1030fe6060f1SDimitry Andric 1031fe6060f1SDimitry Andric if (!InitSectionSymbols.empty()) { 1032fe6060f1SDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex); 1033fe6060f1SDimitry Andric InitSymbolDeps[&MR] = std::move(InitSectionSymbols); 1034fe6060f1SDimitry Andric } 1035fe6060f1SDimitry Andric 1036fe6060f1SDimitry Andric return Error::success(); 1037fe6060f1SDimitry Andric } 1038fe6060f1SDimitry Andric 1039fe6060f1SDimitry Andric Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo( 10405ffd83dbSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 10415ffd83dbSDimitry Andric 10425ffd83dbSDimitry Andric // If there's an ObjC imagine info then either 10435ffd83dbSDimitry Andric // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In 10445ffd83dbSDimitry Andric // this case we name and record it. 10455ffd83dbSDimitry Andric // OR 10465ffd83dbSDimitry Andric // (2) We already have a recorded __objc_imageinfo for this JITDylib, 10475ffd83dbSDimitry Andric // in which case we just verify it. 104806c3fb27SDimitry Andric auto *ObjCImageInfo = G.findSectionByName(MachOObjCImageInfoSectionName); 10495ffd83dbSDimitry Andric if (!ObjCImageInfo) 10505ffd83dbSDimitry Andric return Error::success(); 10515ffd83dbSDimitry Andric 10525ffd83dbSDimitry Andric auto ObjCImageInfoBlocks = ObjCImageInfo->blocks(); 10535ffd83dbSDimitry Andric 10545ffd83dbSDimitry Andric // Check that the section is not empty if present. 1055bdd1243dSDimitry Andric if (ObjCImageInfoBlocks.empty()) 105606c3fb27SDimitry Andric return make_error<StringError>("Empty " + MachOObjCImageInfoSectionName + 1057fe6060f1SDimitry Andric " section in " + G.getName(), 10585ffd83dbSDimitry Andric inconvertibleErrorCode()); 10595ffd83dbSDimitry Andric 10605ffd83dbSDimitry Andric // Check that there's only one block in the section. 10615ffd83dbSDimitry Andric if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end()) 1062fe6060f1SDimitry Andric return make_error<StringError>("Multiple blocks in " + 106306c3fb27SDimitry Andric MachOObjCImageInfoSectionName + 1064fe6060f1SDimitry Andric " section in " + G.getName(), 10655ffd83dbSDimitry Andric inconvertibleErrorCode()); 10665ffd83dbSDimitry Andric 10675ffd83dbSDimitry Andric // Check that the __objc_imageinfo section is unreferenced. 10685ffd83dbSDimitry Andric // FIXME: We could optimize this check if Symbols had a ref-count. 10695ffd83dbSDimitry Andric for (auto &Sec : G.sections()) { 10705ffd83dbSDimitry Andric if (&Sec != ObjCImageInfo) 10715ffd83dbSDimitry Andric for (auto *B : Sec.blocks()) 10725ffd83dbSDimitry Andric for (auto &E : B->edges()) 10735ffd83dbSDimitry Andric if (E.getTarget().isDefined() && 10745ffd83dbSDimitry Andric &E.getTarget().getBlock().getSection() == ObjCImageInfo) 107506c3fb27SDimitry Andric return make_error<StringError>(MachOObjCImageInfoSectionName + 1076fe6060f1SDimitry Andric " is referenced within file " + 10775ffd83dbSDimitry Andric G.getName(), 10785ffd83dbSDimitry Andric inconvertibleErrorCode()); 10795ffd83dbSDimitry Andric } 10805ffd83dbSDimitry Andric 10815ffd83dbSDimitry Andric auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin(); 10825ffd83dbSDimitry Andric auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data(); 10835ffd83dbSDimitry Andric auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness()); 10845ffd83dbSDimitry Andric auto Flags = 10855ffd83dbSDimitry Andric support::endian::read32(ObjCImageInfoData + 4, G.getEndianness()); 10865ffd83dbSDimitry Andric 10875ffd83dbSDimitry Andric // Lock the mutex while we verify / update the ObjCImageInfos map. 1088fe6060f1SDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex); 10895ffd83dbSDimitry Andric 10905ffd83dbSDimitry Andric auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib()); 10915ffd83dbSDimitry Andric if (ObjCImageInfoItr != ObjCImageInfos.end()) { 10925ffd83dbSDimitry Andric // We've already registered an __objc_imageinfo section. Verify the 10935ffd83dbSDimitry Andric // content of this new section matches, then delete it. 109406c3fb27SDimitry Andric if (ObjCImageInfoItr->second.Version != Version) 10955ffd83dbSDimitry Andric return make_error<StringError>( 10965ffd83dbSDimitry Andric "ObjC version in " + G.getName() + 10975ffd83dbSDimitry Andric " does not match first registered version", 10985ffd83dbSDimitry Andric inconvertibleErrorCode()); 109906c3fb27SDimitry Andric if (ObjCImageInfoItr->second.Flags != Flags) 11005f757f3fSDimitry Andric if (Error E = mergeImageInfoFlags(G, MR, ObjCImageInfoItr->second, Flags)) 11015f757f3fSDimitry Andric return E; 11025ffd83dbSDimitry Andric 11035ffd83dbSDimitry Andric // __objc_imageinfo is valid. Delete the block. 11045ffd83dbSDimitry Andric for (auto *S : ObjCImageInfo->symbols()) 11055ffd83dbSDimitry Andric G.removeDefinedSymbol(*S); 11065ffd83dbSDimitry Andric G.removeBlock(ObjCImageInfoBlock); 11075ffd83dbSDimitry Andric } else { 11085f757f3fSDimitry Andric LLVM_DEBUG({ 11095f757f3fSDimitry Andric dbgs() << "MachOPlatform: Registered __objc_imageinfo for " 11105f757f3fSDimitry Andric << MR.getTargetJITDylib().getName() << " in " << G.getName() 11115f757f3fSDimitry Andric << "; flags = " << formatv("{0:x4}", Flags) << "\n"; 11125f757f3fSDimitry Andric }); 11135ffd83dbSDimitry Andric // We haven't registered an __objc_imageinfo section yet. Register and 11145ffd83dbSDimitry Andric // move on. The section should already be marked no-dead-strip. 111506c3fb27SDimitry Andric G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName, 111606c3fb27SDimitry Andric ObjCImageInfoBlock.getSize(), jitlink::Linkage::Strong, 111706c3fb27SDimitry Andric jitlink::Scope::Hidden, false, true); 111806c3fb27SDimitry Andric if (auto Err = MR.defineMaterializing( 111906c3fb27SDimitry Andric {{MR.getExecutionSession().intern(ObjCImageInfoSymbolName), 112006c3fb27SDimitry Andric JITSymbolFlags()}})) 112106c3fb27SDimitry Andric return Err; 11225f757f3fSDimitry Andric ObjCImageInfos[&MR.getTargetJITDylib()] = {Version, Flags, false}; 11235ffd83dbSDimitry Andric } 11245ffd83dbSDimitry Andric 11255ffd83dbSDimitry Andric return Error::success(); 11265ffd83dbSDimitry Andric } 11275ffd83dbSDimitry Andric 11285f757f3fSDimitry Andric Error MachOPlatform::MachOPlatformPlugin::mergeImageInfoFlags( 11295f757f3fSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR, 11305f757f3fSDimitry Andric ObjCImageInfo &Info, uint32_t NewFlags) { 11315f757f3fSDimitry Andric if (Info.Flags == NewFlags) 11325f757f3fSDimitry Andric return Error::success(); 11335f757f3fSDimitry Andric 11345f757f3fSDimitry Andric ObjCImageInfoFlags Old(Info.Flags); 11355f757f3fSDimitry Andric ObjCImageInfoFlags New(NewFlags); 11365f757f3fSDimitry Andric 11375f757f3fSDimitry Andric // Check for incompatible flags. 11385f757f3fSDimitry Andric if (Old.SwiftABIVersion && New.SwiftABIVersion && 11395f757f3fSDimitry Andric Old.SwiftABIVersion != New.SwiftABIVersion) 11405f757f3fSDimitry Andric return make_error<StringError>("Swift ABI version in " + G.getName() + 11415f757f3fSDimitry Andric " does not match first registered flags", 11425f757f3fSDimitry Andric inconvertibleErrorCode()); 11435f757f3fSDimitry Andric 1144*0fca6ea1SDimitry Andric // HasCategoryClassProperties and HasSignedObjCClassROs can be disabled before 1145*0fca6ea1SDimitry Andric // they are registered, if necessary, but once they are in use must be 1146*0fca6ea1SDimitry Andric // supported by subsequent objects. 1147*0fca6ea1SDimitry Andric if (Info.Finalized && Old.HasCategoryClassProperties && 1148*0fca6ea1SDimitry Andric !New.HasCategoryClassProperties) 11495f757f3fSDimitry Andric return make_error<StringError>("ObjC category class property support in " + 11505f757f3fSDimitry Andric G.getName() + 11515f757f3fSDimitry Andric " does not match first registered flags", 11525f757f3fSDimitry Andric inconvertibleErrorCode()); 1153*0fca6ea1SDimitry Andric if (Info.Finalized && Old.HasSignedObjCClassROs && !New.HasSignedObjCClassROs) 11545f757f3fSDimitry Andric return make_error<StringError>("ObjC class_ro_t pointer signing in " + 11555f757f3fSDimitry Andric G.getName() + 11565f757f3fSDimitry Andric " does not match first registered flags", 11575f757f3fSDimitry Andric inconvertibleErrorCode()); 11585f757f3fSDimitry Andric 11595f757f3fSDimitry Andric // If we cannot change the flags, ignore any remaining differences. Adding 11605f757f3fSDimitry Andric // Swift or changing its version are unlikely to cause problems in practice. 11615f757f3fSDimitry Andric if (Info.Finalized) 11625f757f3fSDimitry Andric return Error::success(); 11635f757f3fSDimitry Andric 11645f757f3fSDimitry Andric // Use the minimum Swift version. 11655f757f3fSDimitry Andric if (Old.SwiftVersion && New.SwiftVersion) 11665f757f3fSDimitry Andric New.SwiftVersion = std::min(Old.SwiftVersion, New.SwiftVersion); 11675f757f3fSDimitry Andric else if (Old.SwiftVersion) 11685f757f3fSDimitry Andric New.SwiftVersion = Old.SwiftVersion; 11695f757f3fSDimitry Andric // Add a Swift ABI version if it was pure objc before. 11705f757f3fSDimitry Andric if (!New.SwiftABIVersion) 11715f757f3fSDimitry Andric New.SwiftABIVersion = Old.SwiftABIVersion; 1172*0fca6ea1SDimitry Andric // Disable class properties if any object does not support it. 1173*0fca6ea1SDimitry Andric if (Old.HasCategoryClassProperties != New.HasCategoryClassProperties) 1174*0fca6ea1SDimitry Andric New.HasCategoryClassProperties = false; 1175*0fca6ea1SDimitry Andric // Disable signed class ro data if any object does not support it. 1176*0fca6ea1SDimitry Andric if (Old.HasSignedObjCClassROs != New.HasSignedObjCClassROs) 1177*0fca6ea1SDimitry Andric New.HasSignedObjCClassROs = false; 11785f757f3fSDimitry Andric 11795f757f3fSDimitry Andric LLVM_DEBUG({ 11805f757f3fSDimitry Andric dbgs() << "MachOPlatform: Merging __objc_imageinfo flags for " 11815f757f3fSDimitry Andric << MR.getTargetJITDylib().getName() << " (was " 11825f757f3fSDimitry Andric << formatv("{0:x4}", Old.rawFlags()) << ")" 11835f757f3fSDimitry Andric << " with " << G.getName() << " (" << formatv("{0:x4}", NewFlags) 11845f757f3fSDimitry Andric << ")" 11855f757f3fSDimitry Andric << " -> " << formatv("{0:x4}", New.rawFlags()) << "\n"; 11865f757f3fSDimitry Andric }); 11875f757f3fSDimitry Andric 11885f757f3fSDimitry Andric Info.Flags = New.rawFlags(); 11895f757f3fSDimitry Andric return Error::success(); 11905f757f3fSDimitry Andric } 11915f757f3fSDimitry Andric 1192fe6060f1SDimitry Andric Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges( 1193fe6060f1SDimitry Andric jitlink::LinkGraph &G, JITDylib &JD) { 1194fe6060f1SDimitry Andric 1195fe6060f1SDimitry Andric // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr. 1196fe6060f1SDimitry Andric for (auto *Sym : G.external_symbols()) 1197fe6060f1SDimitry Andric if (Sym->getName() == "__tlv_bootstrap") { 1198fe6060f1SDimitry Andric Sym->setName("___orc_rt_macho_tlv_get_addr"); 1199fe6060f1SDimitry Andric break; 1200fe6060f1SDimitry Andric } 1201fe6060f1SDimitry Andric 1202fe6060f1SDimitry Andric // Store key in __thread_vars struct fields. 120306c3fb27SDimitry Andric if (auto *ThreadDataSec = G.findSectionByName(MachOThreadVarsSectionName)) { 1204bdd1243dSDimitry Andric std::optional<uint64_t> Key; 1205fe6060f1SDimitry Andric { 1206fe6060f1SDimitry Andric std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 1207fe6060f1SDimitry Andric auto I = MP.JITDylibToPThreadKey.find(&JD); 1208fe6060f1SDimitry Andric if (I != MP.JITDylibToPThreadKey.end()) 1209fe6060f1SDimitry Andric Key = I->second; 1210fe6060f1SDimitry Andric } 1211fe6060f1SDimitry Andric 1212fe6060f1SDimitry Andric if (!Key) { 1213fe6060f1SDimitry Andric if (auto KeyOrErr = MP.createPThreadKey()) 1214fe6060f1SDimitry Andric Key = *KeyOrErr; 1215fe6060f1SDimitry Andric else 1216fe6060f1SDimitry Andric return KeyOrErr.takeError(); 1217fe6060f1SDimitry Andric } 1218fe6060f1SDimitry Andric 1219fe6060f1SDimitry Andric uint64_t PlatformKeyBits = 1220fe6060f1SDimitry Andric support::endian::byte_swap(*Key, G.getEndianness()); 1221fe6060f1SDimitry Andric 1222fe6060f1SDimitry Andric for (auto *B : ThreadDataSec->blocks()) { 1223fe6060f1SDimitry Andric if (B->getSize() != 3 * G.getPointerSize()) 1224fe6060f1SDimitry Andric return make_error<StringError>("__thread_vars block at " + 1225fe6060f1SDimitry Andric formatv("{0:x}", B->getAddress()) + 1226fe6060f1SDimitry Andric " has unexpected size", 1227fe6060f1SDimitry Andric inconvertibleErrorCode()); 1228fe6060f1SDimitry Andric 1229fe6060f1SDimitry Andric auto NewBlockContent = G.allocateBuffer(B->getSize()); 1230fe6060f1SDimitry Andric llvm::copy(B->getContent(), NewBlockContent.data()); 1231fe6060f1SDimitry Andric memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits, 1232fe6060f1SDimitry Andric G.getPointerSize()); 1233fe6060f1SDimitry Andric B->setContent(NewBlockContent); 1234fe6060f1SDimitry Andric } 1235fe6060f1SDimitry Andric } 1236fe6060f1SDimitry Andric 1237fe6060f1SDimitry Andric // Transform any TLV edges into GOT edges. 1238fe6060f1SDimitry Andric for (auto *B : G.blocks()) 1239fe6060f1SDimitry Andric for (auto &E : B->edges()) 1240fe6060f1SDimitry Andric if (E.getKind() == 1241349cc55cSDimitry Andric jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable) 1242349cc55cSDimitry Andric E.setKind(jitlink::x86_64:: 1243349cc55cSDimitry Andric RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable); 1244349cc55cSDimitry Andric 1245349cc55cSDimitry Andric return Error::success(); 1246349cc55cSDimitry Andric } 1247349cc55cSDimitry Andric 1248bdd1243dSDimitry Andric std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections> 1249bdd1243dSDimitry Andric MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo( 1250bdd1243dSDimitry Andric jitlink::LinkGraph &G) { 1251bdd1243dSDimitry Andric using namespace jitlink; 1252349cc55cSDimitry Andric 1253bdd1243dSDimitry Andric UnwindSections US; 1254bdd1243dSDimitry Andric 1255bdd1243dSDimitry Andric // ScanSection records a section range and adds any executable blocks that 1256bdd1243dSDimitry Andric // that section points to to the CodeBlocks vector. 1257bdd1243dSDimitry Andric SmallVector<Block *> CodeBlocks; 1258bdd1243dSDimitry Andric auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) { 1259bdd1243dSDimitry Andric if (Sec.blocks().empty()) 1260bdd1243dSDimitry Andric return; 1261bdd1243dSDimitry Andric SecRange = (*Sec.blocks().begin())->getRange(); 1262bdd1243dSDimitry Andric for (auto *B : Sec.blocks()) { 1263bdd1243dSDimitry Andric auto R = B->getRange(); 1264bdd1243dSDimitry Andric SecRange.Start = std::min(SecRange.Start, R.Start); 1265bdd1243dSDimitry Andric SecRange.End = std::max(SecRange.End, R.End); 1266bdd1243dSDimitry Andric for (auto &E : B->edges()) { 1267bdd1243dSDimitry Andric if (!E.getTarget().isDefined()) 1268bdd1243dSDimitry Andric continue; 1269bdd1243dSDimitry Andric auto &TargetBlock = E.getTarget().getBlock(); 1270bdd1243dSDimitry Andric auto &TargetSection = TargetBlock.getSection(); 1271bdd1243dSDimitry Andric if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec) 1272bdd1243dSDimitry Andric CodeBlocks.push_back(&TargetBlock); 1273349cc55cSDimitry Andric } 1274bdd1243dSDimitry Andric } 1275bdd1243dSDimitry Andric }; 1276bdd1243dSDimitry Andric 127706c3fb27SDimitry Andric if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName)) 1278bdd1243dSDimitry Andric ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection); 1279bdd1243dSDimitry Andric 128006c3fb27SDimitry Andric if (Section *CUInfoSec = 128106c3fb27SDimitry Andric G.findSectionByName(MachOCompactUnwindInfoSectionName)) 1282bdd1243dSDimitry Andric ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection); 1283bdd1243dSDimitry Andric 1284bdd1243dSDimitry Andric // If we didn't find any pointed-to code-blocks then there's no need to 1285bdd1243dSDimitry Andric // register any info. 1286bdd1243dSDimitry Andric if (CodeBlocks.empty()) 1287bdd1243dSDimitry Andric return std::nullopt; 1288bdd1243dSDimitry Andric 1289bdd1243dSDimitry Andric // We have info to register. Sort the code blocks into address order and 1290bdd1243dSDimitry Andric // build a list of contiguous address ranges covering them all. 1291bdd1243dSDimitry Andric llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) { 1292bdd1243dSDimitry Andric return LHS->getAddress() < RHS->getAddress(); 1293bdd1243dSDimitry Andric }); 1294bdd1243dSDimitry Andric for (auto *B : CodeBlocks) { 1295bdd1243dSDimitry Andric if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress()) 1296bdd1243dSDimitry Andric US.CodeRanges.push_back(B->getRange()); 1297bdd1243dSDimitry Andric else 1298bdd1243dSDimitry Andric US.CodeRanges.back().End = B->getRange().End; 1299bdd1243dSDimitry Andric } 1300bdd1243dSDimitry Andric 1301bdd1243dSDimitry Andric LLVM_DEBUG({ 1302bdd1243dSDimitry Andric dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n" 1303bdd1243dSDimitry Andric << " DWARF: "; 1304bdd1243dSDimitry Andric if (US.DwarfSection.Start) 1305bdd1243dSDimitry Andric dbgs() << US.DwarfSection << "\n"; 1306bdd1243dSDimitry Andric else 1307bdd1243dSDimitry Andric dbgs() << "none\n"; 1308bdd1243dSDimitry Andric dbgs() << " Compact-unwind: "; 1309bdd1243dSDimitry Andric if (US.CompactUnwindSection.Start) 1310bdd1243dSDimitry Andric dbgs() << US.CompactUnwindSection << "\n"; 1311bdd1243dSDimitry Andric else 1312bdd1243dSDimitry Andric dbgs() << "none\n" 1313bdd1243dSDimitry Andric << "for code ranges:\n"; 1314bdd1243dSDimitry Andric for (auto &CR : US.CodeRanges) 1315bdd1243dSDimitry Andric dbgs() << " " << CR << "\n"; 1316bdd1243dSDimitry Andric if (US.CodeRanges.size() >= G.sections_size()) 1317bdd1243dSDimitry Andric dbgs() << "WARNING: High number of discontiguous code ranges! " 1318bdd1243dSDimitry Andric "Padding may be interfering with coalescing.\n"; 1319bdd1243dSDimitry Andric }); 1320bdd1243dSDimitry Andric 1321bdd1243dSDimitry Andric return US; 1322bdd1243dSDimitry Andric } 1323bdd1243dSDimitry Andric 1324bdd1243dSDimitry Andric Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections( 1325bdd1243dSDimitry Andric jitlink::LinkGraph &G, JITDylib &JD, bool InBootstrapPhase) { 1326349cc55cSDimitry Andric 1327349cc55cSDimitry Andric // Get a pointer to the thread data section if there is one. It will be used 1328349cc55cSDimitry Andric // below. 1329349cc55cSDimitry Andric jitlink::Section *ThreadDataSection = 133006c3fb27SDimitry Andric G.findSectionByName(MachOThreadDataSectionName); 1331349cc55cSDimitry Andric 1332349cc55cSDimitry Andric // Handle thread BSS section if there is one. 133306c3fb27SDimitry Andric if (auto *ThreadBSSSection = G.findSectionByName(MachOThreadBSSSectionName)) { 1334349cc55cSDimitry Andric // If there's already a thread data section in this graph then merge the 1335349cc55cSDimitry Andric // thread BSS section content into it, otherwise just treat the thread 1336349cc55cSDimitry Andric // BSS section as the thread data section. 1337349cc55cSDimitry Andric if (ThreadDataSection) 1338349cc55cSDimitry Andric G.mergeSections(*ThreadDataSection, *ThreadBSSSection); 1339349cc55cSDimitry Andric else 1340349cc55cSDimitry Andric ThreadDataSection = ThreadBSSSection; 1341349cc55cSDimitry Andric } 1342349cc55cSDimitry Andric 134381ad6265SDimitry Andric SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs; 134481ad6265SDimitry Andric 1345bdd1243dSDimitry Andric // Collect data sections to register. 134606c3fb27SDimitry Andric StringRef DataSections[] = {MachODataDataSectionName, 134706c3fb27SDimitry Andric MachODataCommonSectionName, 134806c3fb27SDimitry Andric MachOEHFrameSectionName}; 1349bdd1243dSDimitry Andric for (auto &SecName : DataSections) { 1350bdd1243dSDimitry Andric if (auto *Sec = G.findSectionByName(SecName)) { 1351bdd1243dSDimitry Andric jitlink::SectionRange R(*Sec); 1352bdd1243dSDimitry Andric if (!R.empty()) 1353bdd1243dSDimitry Andric MachOPlatformSecs.push_back({SecName, R.getRange()}); 1354bdd1243dSDimitry Andric } 1355bdd1243dSDimitry Andric } 1356bdd1243dSDimitry Andric 1357349cc55cSDimitry Andric // Having merged thread BSS (if present) and thread data (if present), 1358349cc55cSDimitry Andric // record the resulting section range. 1359349cc55cSDimitry Andric if (ThreadDataSection) { 1360349cc55cSDimitry Andric jitlink::SectionRange R(*ThreadDataSection); 1361bdd1243dSDimitry Andric if (!R.empty()) 136206c3fb27SDimitry Andric MachOPlatformSecs.push_back({MachOThreadDataSectionName, R.getRange()}); 136381ad6265SDimitry Andric } 136481ad6265SDimitry Andric 136581ad6265SDimitry Andric // If any platform sections were found then add an allocation action to call 136681ad6265SDimitry Andric // the registration function. 136706c3fb27SDimitry Andric StringRef PlatformSections[] = {MachOModInitFuncSectionName, 136806c3fb27SDimitry Andric ObjCRuntimeObjectSectionName}; 136981ad6265SDimitry Andric 137081ad6265SDimitry Andric for (auto &SecName : PlatformSections) { 137181ad6265SDimitry Andric auto *Sec = G.findSectionByName(SecName); 137281ad6265SDimitry Andric if (!Sec) 137381ad6265SDimitry Andric continue; 137481ad6265SDimitry Andric jitlink::SectionRange R(*Sec); 137581ad6265SDimitry Andric if (R.empty()) 137681ad6265SDimitry Andric continue; 137781ad6265SDimitry Andric 137881ad6265SDimitry Andric MachOPlatformSecs.push_back({SecName, R.getRange()}); 137981ad6265SDimitry Andric } 138081ad6265SDimitry Andric 1381bdd1243dSDimitry Andric std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange, 1382bdd1243dSDimitry Andric ExecutorAddrRange>> 1383bdd1243dSDimitry Andric UnwindInfo; 1384bdd1243dSDimitry Andric if (auto UI = findUnwindSectionInfo(G)) 1385bdd1243dSDimitry Andric UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection, 1386bdd1243dSDimitry Andric UI->CompactUnwindSection); 1387bdd1243dSDimitry Andric 1388bdd1243dSDimitry Andric if (!MachOPlatformSecs.empty() || UnwindInfo) { 138981ad6265SDimitry Andric // Dump the scraped inits. 139081ad6265SDimitry Andric LLVM_DEBUG({ 139181ad6265SDimitry Andric dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; 139281ad6265SDimitry Andric for (auto &KV : MachOPlatformSecs) 139381ad6265SDimitry Andric dbgs() << " " << KV.first << ": " << KV.second << "\n"; 139481ad6265SDimitry Andric }); 139581ad6265SDimitry Andric 1396bdd1243dSDimitry Andric using SPSRegisterObjectPlatformSectionsArgs = SPSArgList< 1397bdd1243dSDimitry Andric SPSExecutorAddr, 1398bdd1243dSDimitry Andric SPSOptional<SPSTuple<SPSSequence<SPSExecutorAddrRange>, 1399bdd1243dSDimitry Andric SPSExecutorAddrRange, SPSExecutorAddrRange>>, 140081ad6265SDimitry Andric SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>; 1401bdd1243dSDimitry Andric 1402bdd1243dSDimitry Andric shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase) 1403bdd1243dSDimitry Andric ? G.allocActions() 1404bdd1243dSDimitry Andric : MP.Bootstrap.load()->DeferredAAs; 1405bdd1243dSDimitry Andric 14065f757f3fSDimitry Andric ExecutorAddr HeaderAddr; 14075f757f3fSDimitry Andric { 14085f757f3fSDimitry Andric std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 14095f757f3fSDimitry Andric auto I = MP.JITDylibToHeaderAddr.find(&JD); 14105f757f3fSDimitry Andric assert(I != MP.JITDylibToHeaderAddr.end() && 14115f757f3fSDimitry Andric "No header registered for JD"); 14125f757f3fSDimitry Andric assert(I->second && "Null header registered for JD"); 14135f757f3fSDimitry Andric HeaderAddr = I->second; 14145f757f3fSDimitry Andric } 1415bdd1243dSDimitry Andric allocActions.push_back( 141604eeddc0SDimitry Andric {cantFail( 141781ad6265SDimitry Andric WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>( 1418bdd1243dSDimitry Andric MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo, 141981ad6265SDimitry Andric MachOPlatformSecs)), 142004eeddc0SDimitry Andric cantFail( 142181ad6265SDimitry Andric WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>( 1422bdd1243dSDimitry Andric MP.DeregisterObjectPlatformSections.Addr, HeaderAddr, 1423bdd1243dSDimitry Andric UnwindInfo, MachOPlatformSecs))}); 1424349cc55cSDimitry Andric } 142581ad6265SDimitry Andric 1426349cc55cSDimitry Andric return Error::success(); 1427349cc55cSDimitry Andric } 1428349cc55cSDimitry Andric 142906c3fb27SDimitry Andric Error MachOPlatform::MachOPlatformPlugin::createObjCRuntimeObject( 143006c3fb27SDimitry Andric jitlink::LinkGraph &G) { 143106c3fb27SDimitry Andric 143206c3fb27SDimitry Andric bool NeedTextSegment = false; 143306c3fb27SDimitry Andric size_t NumRuntimeSections = 0; 143406c3fb27SDimitry Andric 143506c3fb27SDimitry Andric for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) 143606c3fb27SDimitry Andric if (G.findSectionByName(ObjCRuntimeSectionName)) 143706c3fb27SDimitry Andric ++NumRuntimeSections; 143806c3fb27SDimitry Andric 143906c3fb27SDimitry Andric for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) { 144006c3fb27SDimitry Andric if (G.findSectionByName(ObjCRuntimeSectionName)) { 144106c3fb27SDimitry Andric ++NumRuntimeSections; 144206c3fb27SDimitry Andric NeedTextSegment = true; 144306c3fb27SDimitry Andric } 144406c3fb27SDimitry Andric } 144506c3fb27SDimitry Andric 144606c3fb27SDimitry Andric // Early out for no runtime sections. 144706c3fb27SDimitry Andric if (NumRuntimeSections == 0) 144806c3fb27SDimitry Andric return Error::success(); 144906c3fb27SDimitry Andric 145006c3fb27SDimitry Andric // If there were any runtime sections then we need to add an __objc_imageinfo 145106c3fb27SDimitry Andric // section. 145206c3fb27SDimitry Andric ++NumRuntimeSections; 145306c3fb27SDimitry Andric 145406c3fb27SDimitry Andric size_t MachOSize = sizeof(MachO::mach_header_64) + 145506c3fb27SDimitry Andric (NeedTextSegment + 1) * sizeof(MachO::segment_command_64) + 145606c3fb27SDimitry Andric NumRuntimeSections * sizeof(MachO::section_64); 145706c3fb27SDimitry Andric 145806c3fb27SDimitry Andric auto &Sec = G.createSection(ObjCRuntimeObjectSectionName, 145906c3fb27SDimitry Andric MemProt::Read | MemProt::Write); 146006c3fb27SDimitry Andric G.createMutableContentBlock(Sec, MachOSize, ExecutorAddr(), 16, 0, true); 146106c3fb27SDimitry Andric 146206c3fb27SDimitry Andric return Error::success(); 146306c3fb27SDimitry Andric } 146406c3fb27SDimitry Andric 146506c3fb27SDimitry Andric Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject( 146606c3fb27SDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 146706c3fb27SDimitry Andric 146806c3fb27SDimitry Andric auto *ObjCRuntimeObjectSec = 146906c3fb27SDimitry Andric G.findSectionByName(ObjCRuntimeObjectSectionName); 147006c3fb27SDimitry Andric 147106c3fb27SDimitry Andric if (!ObjCRuntimeObjectSec) 147206c3fb27SDimitry Andric return Error::success(); 147306c3fb27SDimitry Andric 147406c3fb27SDimitry Andric switch (G.getTargetTriple().getArch()) { 147506c3fb27SDimitry Andric case Triple::aarch64: 147606c3fb27SDimitry Andric case Triple::x86_64: 147706c3fb27SDimitry Andric // Supported. 147806c3fb27SDimitry Andric break; 147906c3fb27SDimitry Andric default: 148006c3fb27SDimitry Andric return make_error<StringError>("Unrecognized MachO arch in triple " + 148106c3fb27SDimitry Andric G.getTargetTriple().str(), 148206c3fb27SDimitry Andric inconvertibleErrorCode()); 148306c3fb27SDimitry Andric } 148406c3fb27SDimitry Andric 148506c3fb27SDimitry Andric auto &SecBlock = **ObjCRuntimeObjectSec->blocks().begin(); 148606c3fb27SDimitry Andric 148706c3fb27SDimitry Andric struct SecDesc { 148806c3fb27SDimitry Andric MachO::section_64 Sec; 148906c3fb27SDimitry Andric unique_function<void(size_t RecordOffset)> AddFixups; 149006c3fb27SDimitry Andric }; 149106c3fb27SDimitry Andric 149206c3fb27SDimitry Andric std::vector<SecDesc> TextSections, DataSections; 149306c3fb27SDimitry Andric auto AddSection = [&](SecDesc &SD, jitlink::Section &GraphSec) { 149406c3fb27SDimitry Andric jitlink::SectionRange SR(GraphSec); 149506c3fb27SDimitry Andric StringRef FQName = GraphSec.getName(); 149606c3fb27SDimitry Andric memset(&SD.Sec, 0, sizeof(MachO::section_64)); 149706c3fb27SDimitry Andric memcpy(SD.Sec.sectname, FQName.drop_front(7).data(), FQName.size() - 7); 149806c3fb27SDimitry Andric memcpy(SD.Sec.segname, FQName.data(), 6); 149906c3fb27SDimitry Andric SD.Sec.addr = SR.getStart() - SecBlock.getAddress(); 150006c3fb27SDimitry Andric SD.Sec.size = SR.getSize(); 150106c3fb27SDimitry Andric SD.Sec.flags = MachO::S_REGULAR; 150206c3fb27SDimitry Andric }; 150306c3fb27SDimitry Andric 150406c3fb27SDimitry Andric // Add the __objc_imageinfo section. 150506c3fb27SDimitry Andric { 150606c3fb27SDimitry Andric DataSections.push_back({}); 150706c3fb27SDimitry Andric auto &SD = DataSections.back(); 150806c3fb27SDimitry Andric memset(&SD.Sec, 0, sizeof(SD.Sec)); 150906c3fb27SDimitry Andric memcpy(SD.Sec.sectname, "__objc_imageinfo", 16); 151006c3fb27SDimitry Andric strcpy(SD.Sec.segname, "__DATA"); 151106c3fb27SDimitry Andric SD.Sec.size = 8; 151206c3fb27SDimitry Andric SD.AddFixups = [&](size_t RecordOffset) { 15135f757f3fSDimitry Andric auto PointerEdge = getPointerEdgeKind(G); 151406c3fb27SDimitry Andric 151506c3fb27SDimitry Andric // Look for an existing __objc_imageinfo symbol. 151606c3fb27SDimitry Andric jitlink::Symbol *ObjCImageInfoSym = nullptr; 151706c3fb27SDimitry Andric for (auto *Sym : G.external_symbols()) 151806c3fb27SDimitry Andric if (Sym->getName() == ObjCImageInfoSymbolName) { 151906c3fb27SDimitry Andric ObjCImageInfoSym = Sym; 152006c3fb27SDimitry Andric break; 152106c3fb27SDimitry Andric } 152206c3fb27SDimitry Andric if (!ObjCImageInfoSym) 152306c3fb27SDimitry Andric for (auto *Sym : G.absolute_symbols()) 152406c3fb27SDimitry Andric if (Sym->getName() == ObjCImageInfoSymbolName) { 152506c3fb27SDimitry Andric ObjCImageInfoSym = Sym; 152606c3fb27SDimitry Andric break; 152706c3fb27SDimitry Andric } 152806c3fb27SDimitry Andric if (!ObjCImageInfoSym) 152906c3fb27SDimitry Andric for (auto *Sym : G.defined_symbols()) 153006c3fb27SDimitry Andric if (Sym->hasName() && Sym->getName() == ObjCImageInfoSymbolName) { 153106c3fb27SDimitry Andric ObjCImageInfoSym = Sym; 15325f757f3fSDimitry Andric std::optional<uint32_t> Flags; 15335f757f3fSDimitry Andric { 15345f757f3fSDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex); 15355f757f3fSDimitry Andric auto It = ObjCImageInfos.find(&MR.getTargetJITDylib()); 15365f757f3fSDimitry Andric if (It != ObjCImageInfos.end()) { 15375f757f3fSDimitry Andric It->second.Finalized = true; 15385f757f3fSDimitry Andric Flags = It->second.Flags; 15395f757f3fSDimitry Andric } 15405f757f3fSDimitry Andric } 15415f757f3fSDimitry Andric 15425f757f3fSDimitry Andric if (Flags) { 15435f757f3fSDimitry Andric // We own the definition of __objc_image_info; write the final 15445f757f3fSDimitry Andric // merged flags value. 15455f757f3fSDimitry Andric auto Content = Sym->getBlock().getMutableContent(G); 15465f757f3fSDimitry Andric assert(Content.size() == 8 && 15475f757f3fSDimitry Andric "__objc_image_info size should have been verified already"); 15485f757f3fSDimitry Andric support::endian::write32(&Content[4], *Flags, G.getEndianness()); 15495f757f3fSDimitry Andric } 155006c3fb27SDimitry Andric break; 155106c3fb27SDimitry Andric } 155206c3fb27SDimitry Andric if (!ObjCImageInfoSym) 155306c3fb27SDimitry Andric ObjCImageInfoSym = 155406c3fb27SDimitry Andric &G.addExternalSymbol(ObjCImageInfoSymbolName, 8, false); 155506c3fb27SDimitry Andric 155606c3fb27SDimitry Andric SecBlock.addEdge(PointerEdge, 155706c3fb27SDimitry Andric RecordOffset + ((char *)&SD.Sec.addr - (char *)&SD.Sec), 155806c3fb27SDimitry Andric *ObjCImageInfoSym, -SecBlock.getAddress().getValue()); 155906c3fb27SDimitry Andric }; 156006c3fb27SDimitry Andric } 156106c3fb27SDimitry Andric 156206c3fb27SDimitry Andric for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) { 156306c3fb27SDimitry Andric if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) { 156406c3fb27SDimitry Andric DataSections.push_back({}); 156506c3fb27SDimitry Andric AddSection(DataSections.back(), *GraphSec); 156606c3fb27SDimitry Andric } 156706c3fb27SDimitry Andric } 156806c3fb27SDimitry Andric 156906c3fb27SDimitry Andric for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) { 157006c3fb27SDimitry Andric if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) { 157106c3fb27SDimitry Andric TextSections.push_back({}); 157206c3fb27SDimitry Andric AddSection(TextSections.back(), *GraphSec); 157306c3fb27SDimitry Andric } 157406c3fb27SDimitry Andric } 157506c3fb27SDimitry Andric 157606c3fb27SDimitry Andric assert(ObjCRuntimeObjectSec->blocks_size() == 1 && 157706c3fb27SDimitry Andric "Unexpected number of blocks in runtime sections object"); 157806c3fb27SDimitry Andric 157906c3fb27SDimitry Andric // Build the header struct up-front. This also gives us a chance to check 158006c3fb27SDimitry Andric // that the triple is supported, which we'll assume below. 158106c3fb27SDimitry Andric MachO::mach_header_64 Hdr; 158206c3fb27SDimitry Andric Hdr.magic = MachO::MH_MAGIC_64; 158306c3fb27SDimitry Andric switch (G.getTargetTriple().getArch()) { 158406c3fb27SDimitry Andric case Triple::aarch64: 158506c3fb27SDimitry Andric Hdr.cputype = MachO::CPU_TYPE_ARM64; 158606c3fb27SDimitry Andric Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL; 158706c3fb27SDimitry Andric break; 158806c3fb27SDimitry Andric case Triple::x86_64: 158906c3fb27SDimitry Andric Hdr.cputype = MachO::CPU_TYPE_X86_64; 159006c3fb27SDimitry Andric Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL; 159106c3fb27SDimitry Andric break; 159206c3fb27SDimitry Andric default: 159306c3fb27SDimitry Andric llvm_unreachable("Unsupported architecture"); 159406c3fb27SDimitry Andric } 159506c3fb27SDimitry Andric 159606c3fb27SDimitry Andric Hdr.filetype = MachO::MH_DYLIB; 159706c3fb27SDimitry Andric Hdr.ncmds = 1 + !TextSections.empty(); 159806c3fb27SDimitry Andric Hdr.sizeofcmds = 159906c3fb27SDimitry Andric Hdr.ncmds * sizeof(MachO::segment_command_64) + 160006c3fb27SDimitry Andric (TextSections.size() + DataSections.size()) * sizeof(MachO::section_64); 160106c3fb27SDimitry Andric Hdr.flags = 0; 160206c3fb27SDimitry Andric Hdr.reserved = 0; 160306c3fb27SDimitry Andric 160406c3fb27SDimitry Andric auto SecContent = SecBlock.getAlreadyMutableContent(); 160506c3fb27SDimitry Andric char *P = SecContent.data(); 160606c3fb27SDimitry Andric auto WriteMachOStruct = [&](auto S) { 16075f757f3fSDimitry Andric if (G.getEndianness() != llvm::endianness::native) 160806c3fb27SDimitry Andric MachO::swapStruct(S); 160906c3fb27SDimitry Andric memcpy(P, &S, sizeof(S)); 161006c3fb27SDimitry Andric P += sizeof(S); 161106c3fb27SDimitry Andric }; 161206c3fb27SDimitry Andric 161306c3fb27SDimitry Andric auto WriteSegment = [&](StringRef Name, std::vector<SecDesc> &Secs) { 161406c3fb27SDimitry Andric MachO::segment_command_64 SegLC; 161506c3fb27SDimitry Andric memset(&SegLC, 0, sizeof(SegLC)); 161606c3fb27SDimitry Andric memcpy(SegLC.segname, Name.data(), Name.size()); 161706c3fb27SDimitry Andric SegLC.cmd = MachO::LC_SEGMENT_64; 161806c3fb27SDimitry Andric SegLC.cmdsize = sizeof(MachO::segment_command_64) + 161906c3fb27SDimitry Andric Secs.size() * sizeof(MachO::section_64); 162006c3fb27SDimitry Andric SegLC.nsects = Secs.size(); 162106c3fb27SDimitry Andric WriteMachOStruct(SegLC); 162206c3fb27SDimitry Andric for (auto &SD : Secs) { 162306c3fb27SDimitry Andric if (SD.AddFixups) 162406c3fb27SDimitry Andric SD.AddFixups(P - SecContent.data()); 162506c3fb27SDimitry Andric WriteMachOStruct(SD.Sec); 162606c3fb27SDimitry Andric } 162706c3fb27SDimitry Andric }; 162806c3fb27SDimitry Andric 162906c3fb27SDimitry Andric WriteMachOStruct(Hdr); 163006c3fb27SDimitry Andric if (!TextSections.empty()) 163106c3fb27SDimitry Andric WriteSegment("__TEXT", TextSections); 163206c3fb27SDimitry Andric if (!DataSections.empty()) 163306c3fb27SDimitry Andric WriteSegment("__DATA", DataSections); 163406c3fb27SDimitry Andric 163506c3fb27SDimitry Andric assert(P == SecContent.end() && "Underflow writing ObjC runtime object"); 163606c3fb27SDimitry Andric return Error::success(); 163706c3fb27SDimitry Andric } 163806c3fb27SDimitry Andric 16395f757f3fSDimitry Andric Error MachOPlatform::MachOPlatformPlugin::prepareSymbolTableRegistration( 16405f757f3fSDimitry Andric jitlink::LinkGraph &G, JITSymTabVector &JITSymTabInfo) { 16415f757f3fSDimitry Andric 16425f757f3fSDimitry Andric auto *CStringSec = G.findSectionByName(MachOCStringSectionName); 16435f757f3fSDimitry Andric if (!CStringSec) 16445f757f3fSDimitry Andric CStringSec = &G.createSection(MachOCStringSectionName, 16455f757f3fSDimitry Andric MemProt::Read | MemProt::Exec); 16465f757f3fSDimitry Andric 16475f757f3fSDimitry Andric // Make a map of existing strings so that we can re-use them: 16485f757f3fSDimitry Andric DenseMap<StringRef, jitlink::Symbol *> ExistingStrings; 16495f757f3fSDimitry Andric for (auto *Sym : CStringSec->symbols()) { 16505f757f3fSDimitry Andric 16515f757f3fSDimitry Andric // The LinkGraph builder should have created single strings blocks, and all 16525f757f3fSDimitry Andric // plugins should have maintained this invariant. 16535f757f3fSDimitry Andric auto Content = Sym->getBlock().getContent(); 16545f757f3fSDimitry Andric ExistingStrings.insert( 16555f757f3fSDimitry Andric std::make_pair(StringRef(Content.data(), Content.size()), Sym)); 16565f757f3fSDimitry Andric } 16575f757f3fSDimitry Andric 16585f757f3fSDimitry Andric // Add all symbol names to the string section, and record the symbols for 16595f757f3fSDimitry Andric // those names. 16605f757f3fSDimitry Andric { 16615f757f3fSDimitry Andric SmallVector<jitlink::Symbol *> SymsToProcess; 16625f757f3fSDimitry Andric for (auto *Sym : G.defined_symbols()) 16635f757f3fSDimitry Andric SymsToProcess.push_back(Sym); 16641db9f3b2SDimitry Andric for (auto *Sym : G.absolute_symbols()) 16651db9f3b2SDimitry Andric SymsToProcess.push_back(Sym); 16665f757f3fSDimitry Andric 16675f757f3fSDimitry Andric for (auto *Sym : SymsToProcess) { 16685f757f3fSDimitry Andric if (!Sym->hasName()) 16695f757f3fSDimitry Andric continue; 16705f757f3fSDimitry Andric 16715f757f3fSDimitry Andric auto I = ExistingStrings.find(Sym->getName()); 16725f757f3fSDimitry Andric if (I == ExistingStrings.end()) { 16735f757f3fSDimitry Andric auto &NameBlock = G.createMutableContentBlock( 16745f757f3fSDimitry Andric *CStringSec, G.allocateCString(Sym->getName()), orc::ExecutorAddr(), 16755f757f3fSDimitry Andric 1, 0); 16765f757f3fSDimitry Andric auto &SymbolNameSym = G.addAnonymousSymbol( 16775f757f3fSDimitry Andric NameBlock, 0, NameBlock.getSize(), false, true); 16785f757f3fSDimitry Andric JITSymTabInfo.push_back({Sym, &SymbolNameSym}); 16795f757f3fSDimitry Andric } else 16805f757f3fSDimitry Andric JITSymTabInfo.push_back({Sym, I->second}); 16815f757f3fSDimitry Andric } 16825f757f3fSDimitry Andric } 16835f757f3fSDimitry Andric 16845f757f3fSDimitry Andric return Error::success(); 16855f757f3fSDimitry Andric } 16865f757f3fSDimitry Andric 16875f757f3fSDimitry Andric Error MachOPlatform::MachOPlatformPlugin::addSymbolTableRegistration( 16885f757f3fSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR, 16895f757f3fSDimitry Andric JITSymTabVector &JITSymTabInfo, bool InBootstrapPhase) { 16905f757f3fSDimitry Andric 16915f757f3fSDimitry Andric ExecutorAddr HeaderAddr; 16925f757f3fSDimitry Andric { 16935f757f3fSDimitry Andric std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 16945f757f3fSDimitry Andric auto I = MP.JITDylibToHeaderAddr.find(&MR.getTargetJITDylib()); 16955f757f3fSDimitry Andric assert(I != MP.JITDylibToHeaderAddr.end() && "No header registered for JD"); 16965f757f3fSDimitry Andric assert(I->second && "Null header registered for JD"); 16975f757f3fSDimitry Andric HeaderAddr = I->second; 16985f757f3fSDimitry Andric } 16995f757f3fSDimitry Andric 17005f757f3fSDimitry Andric SymbolTableVector LocalSymTab; 17015f757f3fSDimitry Andric auto &SymTab = LLVM_LIKELY(!InBootstrapPhase) ? LocalSymTab 17025f757f3fSDimitry Andric : MP.Bootstrap.load()->SymTab; 17035f757f3fSDimitry Andric for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo) 17045f757f3fSDimitry Andric SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(), 17055f757f3fSDimitry Andric flagsForSymbol(*OriginalSymbol)}); 17065f757f3fSDimitry Andric 17075f757f3fSDimitry Andric // Bail out if we're in the bootstrap phase -- registration of thees symbols 17085f757f3fSDimitry Andric // will be attached to the bootstrap graph. 17095f757f3fSDimitry Andric if (LLVM_UNLIKELY(InBootstrapPhase)) 17105f757f3fSDimitry Andric return Error::success(); 17115f757f3fSDimitry Andric 17125f757f3fSDimitry Andric shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase) 17135f757f3fSDimitry Andric ? G.allocActions() 17145f757f3fSDimitry Andric : MP.Bootstrap.load()->DeferredAAs; 17155f757f3fSDimitry Andric allocActions.push_back( 17165f757f3fSDimitry Andric {cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>( 17175f757f3fSDimitry Andric MP.RegisterObjectSymbolTable.Addr, HeaderAddr, SymTab)), 17185f757f3fSDimitry Andric cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>( 17195f757f3fSDimitry Andric MP.DeregisterObjectSymbolTable.Addr, HeaderAddr, SymTab))}); 17205f757f3fSDimitry Andric 17215f757f3fSDimitry Andric return Error::success(); 17225f757f3fSDimitry Andric } 17235f757f3fSDimitry Andric 17245f757f3fSDimitry Andric template <typename MachOTraits> 17257a6dacacSDimitry Andric jitlink::Block &createHeaderBlock(MachOPlatform &MOP, 17267a6dacacSDimitry Andric const MachOPlatform::HeaderOptions &Opts, 17277a6dacacSDimitry Andric JITDylib &JD, jitlink::LinkGraph &G, 17285f757f3fSDimitry Andric jitlink::Section &HeaderSection) { 17295f757f3fSDimitry Andric auto HdrInfo = 17305f757f3fSDimitry Andric getMachOHeaderInfoFromTriple(MOP.getExecutionSession().getTargetTriple()); 17315f757f3fSDimitry Andric MachOBuilder<MachOTraits> B(HdrInfo.PageSize); 17325f757f3fSDimitry Andric 17335f757f3fSDimitry Andric B.Header.filetype = MachO::MH_DYLIB; 17345f757f3fSDimitry Andric B.Header.cputype = HdrInfo.CPUType; 17355f757f3fSDimitry Andric B.Header.cpusubtype = HdrInfo.CPUSubType; 17365f757f3fSDimitry Andric 17377a6dacacSDimitry Andric if (Opts.IDDylib) 17387a6dacacSDimitry Andric B.template addLoadCommand<MachO::LC_ID_DYLIB>( 17397a6dacacSDimitry Andric Opts.IDDylib->Name, Opts.IDDylib->Timestamp, 17407a6dacacSDimitry Andric Opts.IDDylib->CurrentVersion, Opts.IDDylib->CompatibilityVersion); 17417a6dacacSDimitry Andric else 17427a6dacacSDimitry Andric B.template addLoadCommand<MachO::LC_ID_DYLIB>(JD.getName(), 0, 0, 0); 17437a6dacacSDimitry Andric 1744*0fca6ea1SDimitry Andric for (auto &BV : Opts.BuildVersions) 1745*0fca6ea1SDimitry Andric B.template addLoadCommand<MachO::LC_BUILD_VERSION>( 1746*0fca6ea1SDimitry Andric BV.Platform, BV.MinOS, BV.SDK, static_cast<uint32_t>(0)); 17477a6dacacSDimitry Andric for (auto &D : Opts.LoadDylibs) 17487a6dacacSDimitry Andric B.template addLoadCommand<MachO::LC_LOAD_DYLIB>( 17497a6dacacSDimitry Andric D.Name, D.Timestamp, D.CurrentVersion, D.CompatibilityVersion); 17507a6dacacSDimitry Andric for (auto &P : Opts.RPaths) 17517a6dacacSDimitry Andric B.template addLoadCommand<MachO::LC_RPATH>(P); 17527a6dacacSDimitry Andric 17535f757f3fSDimitry Andric auto HeaderContent = G.allocateBuffer(B.layout()); 17545f757f3fSDimitry Andric B.write(HeaderContent); 17555f757f3fSDimitry Andric 17565f757f3fSDimitry Andric return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8, 17575f757f3fSDimitry Andric 0); 17585f757f3fSDimitry Andric } 17595f757f3fSDimitry Andric 17605f757f3fSDimitry Andric SimpleMachOHeaderMU::SimpleMachOHeaderMU(MachOPlatform &MOP, 17617a6dacacSDimitry Andric SymbolStringPtr HeaderStartSymbol, 17627a6dacacSDimitry Andric MachOPlatform::HeaderOptions Opts) 17635f757f3fSDimitry Andric : MaterializationUnit( 17645f757f3fSDimitry Andric createHeaderInterface(MOP, std::move(HeaderStartSymbol))), 17657a6dacacSDimitry Andric MOP(MOP), Opts(std::move(Opts)) {} 17665f757f3fSDimitry Andric 17675f757f3fSDimitry Andric void SimpleMachOHeaderMU::materialize( 17685f757f3fSDimitry Andric std::unique_ptr<MaterializationResponsibility> R) { 17695f757f3fSDimitry Andric auto G = createPlatformGraph(MOP, "<MachOHeaderMU>"); 17705f757f3fSDimitry Andric addMachOHeader(R->getTargetJITDylib(), *G, R->getInitializerSymbol()); 17715f757f3fSDimitry Andric MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 17725f757f3fSDimitry Andric } 17735f757f3fSDimitry Andric 17745f757f3fSDimitry Andric void SimpleMachOHeaderMU::discard(const JITDylib &JD, 17755f757f3fSDimitry Andric const SymbolStringPtr &Sym) {} 17765f757f3fSDimitry Andric 17775f757f3fSDimitry Andric void SimpleMachOHeaderMU::addMachOHeader( 17785f757f3fSDimitry Andric JITDylib &JD, jitlink::LinkGraph &G, 17795f757f3fSDimitry Andric const SymbolStringPtr &InitializerSymbol) { 17805f757f3fSDimitry Andric auto &HeaderSection = G.createSection("__header", MemProt::Read); 17815f757f3fSDimitry Andric auto &HeaderBlock = createHeaderBlock(JD, G, HeaderSection); 17825f757f3fSDimitry Andric 17835f757f3fSDimitry Andric // Init symbol is header-start symbol. 17845f757f3fSDimitry Andric G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol, HeaderBlock.getSize(), 17855f757f3fSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, false, 17865f757f3fSDimitry Andric true); 17875f757f3fSDimitry Andric for (auto &HS : AdditionalHeaderSymbols) 17885f757f3fSDimitry Andric G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(), 17895f757f3fSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, false, 17905f757f3fSDimitry Andric true); 17915f757f3fSDimitry Andric } 17925f757f3fSDimitry Andric 17935f757f3fSDimitry Andric jitlink::Block & 17945f757f3fSDimitry Andric SimpleMachOHeaderMU::createHeaderBlock(JITDylib &JD, jitlink::LinkGraph &G, 17955f757f3fSDimitry Andric jitlink::Section &HeaderSection) { 17965f757f3fSDimitry Andric switch (MOP.getExecutionSession().getTargetTriple().getArch()) { 17975f757f3fSDimitry Andric case Triple::aarch64: 17985f757f3fSDimitry Andric case Triple::x86_64: 17997a6dacacSDimitry Andric return ::createHeaderBlock<MachO64LE>(MOP, Opts, JD, G, HeaderSection); 18005f757f3fSDimitry Andric default: 18015f757f3fSDimitry Andric llvm_unreachable("Unsupported architecture"); 18025f757f3fSDimitry Andric } 18035f757f3fSDimitry Andric } 18045f757f3fSDimitry Andric 18055f757f3fSDimitry Andric MaterializationUnit::Interface SimpleMachOHeaderMU::createHeaderInterface( 18065f757f3fSDimitry Andric MachOPlatform &MOP, const SymbolStringPtr &HeaderStartSymbol) { 18075f757f3fSDimitry Andric SymbolFlagsMap HeaderSymbolFlags; 18085f757f3fSDimitry Andric 18095f757f3fSDimitry Andric HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported; 18105f757f3fSDimitry Andric for (auto &HS : AdditionalHeaderSymbols) 18115f757f3fSDimitry Andric HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] = 18125f757f3fSDimitry Andric JITSymbolFlags::Exported; 18135f757f3fSDimitry Andric 18145f757f3fSDimitry Andric return MaterializationUnit::Interface(std::move(HeaderSymbolFlags), 18155f757f3fSDimitry Andric HeaderStartSymbol); 18165f757f3fSDimitry Andric } 18175f757f3fSDimitry Andric 18185f757f3fSDimitry Andric MachOHeaderInfo getMachOHeaderInfoFromTriple(const Triple &TT) { 18195f757f3fSDimitry Andric switch (TT.getArch()) { 18205f757f3fSDimitry Andric case Triple::aarch64: 18215f757f3fSDimitry Andric return {/* PageSize = */ 16 * 1024, 18225f757f3fSDimitry Andric /* CPUType = */ MachO::CPU_TYPE_ARM64, 18235f757f3fSDimitry Andric /* CPUSubType = */ MachO::CPU_SUBTYPE_ARM64_ALL}; 18245f757f3fSDimitry Andric case Triple::x86_64: 18255f757f3fSDimitry Andric return {/* PageSize = */ 4 * 1024, 18265f757f3fSDimitry Andric /* CPUType = */ MachO::CPU_TYPE_X86_64, 18275f757f3fSDimitry Andric /* CPUSubType = */ MachO::CPU_SUBTYPE_X86_64_ALL}; 18285f757f3fSDimitry Andric default: 18295f757f3fSDimitry Andric llvm_unreachable("Unrecognized architecture"); 18305f757f3fSDimitry Andric } 18315f757f3fSDimitry Andric } 18325f757f3fSDimitry Andric 18335ffd83dbSDimitry Andric } // End namespace orc. 18345ffd83dbSDimitry Andric } // End namespace llvm. 1835