xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
size(const MachOPlatform::MachOJITDylibDepInfo & DDI)4481ad6265SDimitry Andric   static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) {
4581ad6265SDimitry Andric     return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders);
4681ad6265SDimitry Andric   }
4781ad6265SDimitry Andric 
serialize(SPSOutputBuffer & OB,const MachOPlatform::MachOJITDylibDepInfo & DDI)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 
deserialize(SPSInputBuffer & IB,MachOPlatform::MachOJITDylibDepInfo & DDI)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:
size(const MachOPlatform::MachOExecutorSymbolFlags & SF)685f757f3fSDimitry Andric   static size_t size(const MachOPlatform::MachOExecutorSymbolFlags &SF) {
695f757f3fSDimitry Andric     return sizeof(UT);
705f757f3fSDimitry Andric   }
715f757f3fSDimitry Andric 
serialize(SPSOutputBuffer & OB,const MachOPlatform::MachOExecutorSymbolFlags & SF)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 
deserialize(SPSInputBuffer & IB,MachOPlatform::MachOExecutorSymbolFlags & SF)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 
createPlatformGraph(MachOPlatform & MOP,std::string Name)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 
MachOPlatformCompleteBootstrapMaterializationUnit(MachOPlatform & MOP,StringRef PlatformJDName,SymbolStringPtr CompleteBootstrapSymbol,SymbolTableVector SymTab,shared::AllocActions DeferredAAs,ExecutorAddr MachOHeaderAddr,ExecutorAddr PlatformBootstrap,ExecutorAddr PlatformShutdown,ExecutorAddr RegisterJITDylib,ExecutorAddr DeregisterJITDylib,ExecutorAddr RegisterObjectSymbolTable,ExecutorAddr DeregisterObjectSymbolTable)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 
getName() const146bdd1243dSDimitry Andric   StringRef getName() const override {
147bdd1243dSDimitry Andric     return "MachOPlatformCompleteBootstrap";
148bdd1243dSDimitry Andric   }
149bdd1243dSDimitry Andric 
materialize(std::unique_ptr<MaterializationResponsibility> R)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 
discard(const JITDylib & JD,const SymbolStringPtr & Sym)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 
ObjCImageInfoFlags__anon04a50ca90111::ObjCImageInfoFlags2385f757f3fSDimitry 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 
rawFlags__anon04a50ca90111::ObjCImageInfoFlags2455f757f3fSDimitry 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>
fromTriple(const Triple & TT,uint32_t MinOS,uint32_t SDK)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 
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,std::unique_ptr<DefinitionGenerator> OrcRuntime,HeaderOptions PlatformJDOpts,MachOHeaderMUBuilder BuildMachOHeaderMU,std::optional<SymbolAliasMap> RuntimeAliases)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>>
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,const char * OrcRuntimePath,HeaderOptions PlatformJDOpts,MachOHeaderMUBuilder BuildMachOHeaderMU,std::optional<SymbolAliasMap> RuntimeAliases)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 
setupJITDylib(JITDylib & JD)3555ffd83dbSDimitry Andric Error MachOPlatform::setupJITDylib(JITDylib &JD) {
3567a6dacacSDimitry Andric   return setupJITDylib(JD, /*Opts=*/{});
3577a6dacacSDimitry Andric }
3587a6dacacSDimitry Andric 
setupJITDylib(JITDylib & JD,HeaderOptions Opts)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 
teardownJITDylib(JITDylib & JD)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 
notifyAdding(ResourceTracker & RT,const MaterializationUnit & MU)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 
notifyRemoving(ResourceTracker & RT)395e8d8bef9SDimitry Andric Error MachOPlatform::notifyRemoving(ResourceTracker &RT) {
3965ffd83dbSDimitry Andric   llvm_unreachable("Not supported yet");
3975ffd83dbSDimitry Andric }
3985ffd83dbSDimitry Andric 
addAliases(ExecutionSession & ES,SymbolAliasMap & Aliases,ArrayRef<std::pair<const char *,const char * >> AL)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 
standardPlatformAliases(ExecutionSession & ES)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 *>>
requiredCXXAliases()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 *>>
standardRuntimeUtilityAliases()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 
supportedTarget(const Triple & TT)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 
getPointerEdgeKind(jitlink::LinkGraph & G)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
flagsForSymbol(jitlink::Symbol & Sym)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 
MachOPlatform(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,HeaderOptions PlatformJDOpts,MachOHeaderMUBuilder BuildMachOHeaderMU,Error & Err)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 
associateRuntimeSupportFunctions()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 
pushInitializersLoop(PushInitializersSendResultFn SendResult,JITDylibSP JD)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 
rt_pushInitializers(PushInitializersSendResultFn SendResult,ExecutorAddr JDHeaderAddr)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 
rt_pushSymbols(PushSymbolsInSendResultFn SendResult,ExecutorAddr Handle,const std::vector<std::pair<StringRef,bool>> & SymbolNames)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 
createPThreadKey()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 
modifyPassConfig(MaterializationResponsibility & MR,jitlink::LinkGraph & LG,jitlink::PassConfiguration & Config)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
getSyntheticSymbolDependencies(MaterializationResponsibility & MR)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 
bootstrapPipelineStart(jitlink::LinkGraph & G)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::
bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph & G)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 
bootstrapPipelineEnd(jitlink::LinkGraph & G)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 
associateJITDylibHeaderSymbol(jitlink::LinkGraph & G,MaterializationResponsibility & MR)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 
preserveImportantSections(jitlink::LinkGraph & G,MaterializationResponsibility & MR)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 
processObjCImageInfo(jitlink::LinkGraph & G,MaterializationResponsibility & MR)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 
mergeImageInfoFlags(jitlink::LinkGraph & G,MaterializationResponsibility & MR,ObjCImageInfo & Info,uint32_t NewFlags)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 
fixTLVSectionsAndEdges(jitlink::LinkGraph & G,JITDylib & JD)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>
findUnwindSectionInfo(jitlink::LinkGraph & G)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 
registerObjectPlatformSections(jitlink::LinkGraph & G,JITDylib & JD,bool InBootstrapPhase)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 
createObjCRuntimeObject(jitlink::LinkGraph & G)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 
populateObjCRuntimeObject(jitlink::LinkGraph & G,MaterializationResponsibility & MR)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 
prepareSymbolTableRegistration(jitlink::LinkGraph & G,JITSymTabVector & JITSymTabInfo)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 
addSymbolTableRegistration(jitlink::LinkGraph & G,MaterializationResponsibility & MR,JITSymTabVector & JITSymTabInfo,bool InBootstrapPhase)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>
createHeaderBlock(MachOPlatform & MOP,const MachOPlatform::HeaderOptions & Opts,JITDylib & JD,jitlink::LinkGraph & G,jitlink::Section & HeaderSection)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 
SimpleMachOHeaderMU(MachOPlatform & MOP,SymbolStringPtr HeaderStartSymbol,MachOPlatform::HeaderOptions Opts)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 
materialize(std::unique_ptr<MaterializationResponsibility> R)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 
discard(const JITDylib & JD,const SymbolStringPtr & Sym)17745f757f3fSDimitry Andric void SimpleMachOHeaderMU::discard(const JITDylib &JD,
17755f757f3fSDimitry Andric                                   const SymbolStringPtr &Sym) {}
17765f757f3fSDimitry Andric 
addMachOHeader(JITDylib & JD,jitlink::LinkGraph & G,const SymbolStringPtr & InitializerSymbol)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 &
createHeaderBlock(JITDylib & JD,jitlink::LinkGraph & G,jitlink::Section & HeaderSection)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 
createHeaderInterface(MachOPlatform & MOP,const SymbolStringPtr & HeaderStartSymbol)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 
getMachOHeaderInfoFromTriple(const Triple & TT)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