185fb9976SLang Hames //===------ MachOPlatform.cpp - Utilities for executing MachO in Orc ------===//
285fb9976SLang Hames //
385fb9976SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
485fb9976SLang Hames // See https://llvm.org/LICENSE.txt for license information.
585fb9976SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
685fb9976SLang Hames //
785fb9976SLang Hames //===----------------------------------------------------------------------===//
885fb9976SLang Hames 
985fb9976SLang Hames #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
1085fb9976SLang Hames 
1185fb9976SLang Hames #include "llvm/BinaryFormat/MachO.h"
12bb5f97e3SLang Hames #include "llvm/ExecutionEngine/JITLink/x86_64.h"
1338a8760bSLang Hames #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
14bb5f97e3SLang Hames #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
1564288571SLang Hames #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
1685fb9976SLang Hames #include "llvm/Support/BinaryByteStream.h"
178363ff04SLang Hames #include "llvm/Support/Debug.h"
188363ff04SLang Hames 
198363ff04SLang Hames #define DEBUG_TYPE "orc"
2085fb9976SLang Hames 
21bb5f97e3SLang Hames using namespace llvm;
22bb5f97e3SLang Hames using namespace llvm::orc;
23bb5f97e3SLang Hames using namespace llvm::orc::shared;
24bb5f97e3SLang Hames 
25f9aef477SLang Hames namespace llvm {
26f9aef477SLang Hames namespace orc {
27f9aef477SLang Hames namespace shared {
28f9aef477SLang Hames 
29f9aef477SLang Hames using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>;
30f9aef477SLang Hames using SPSMachOJITDylibDepInfoMap =
31f9aef477SLang Hames     SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>;
32f9aef477SLang Hames 
33f9aef477SLang Hames template <>
34f9aef477SLang Hames class SPSSerializationTraits<SPSMachOJITDylibDepInfo,
35f9aef477SLang Hames                              MachOPlatform::MachOJITDylibDepInfo> {
36f9aef477SLang Hames public:
size(const MachOPlatform::MachOJITDylibDepInfo & DDI)37f9aef477SLang Hames   static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) {
38f9aef477SLang Hames     return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders);
39f9aef477SLang Hames   }
40f9aef477SLang Hames 
serialize(SPSOutputBuffer & OB,const MachOPlatform::MachOJITDylibDepInfo & DDI)41f9aef477SLang Hames   static bool serialize(SPSOutputBuffer &OB,
42f9aef477SLang Hames                         const MachOPlatform::MachOJITDylibDepInfo &DDI) {
43f9aef477SLang Hames     return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed,
44f9aef477SLang Hames                                                          DDI.DepHeaders);
45f9aef477SLang Hames   }
46f9aef477SLang Hames 
deserialize(SPSInputBuffer & IB,MachOPlatform::MachOJITDylibDepInfo & DDI)47f9aef477SLang Hames   static bool deserialize(SPSInputBuffer &IB,
48f9aef477SLang Hames                           MachOPlatform::MachOJITDylibDepInfo &DDI) {
49f9aef477SLang Hames     return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed,
50f9aef477SLang Hames                                                            DDI.DepHeaders);
51f9aef477SLang Hames   }
52f9aef477SLang Hames };
53f9aef477SLang Hames 
54f9aef477SLang Hames } // namespace shared
55f9aef477SLang Hames } // namespace orc
56f9aef477SLang Hames } // namespace llvm
57f9aef477SLang Hames 
58bb5f97e3SLang Hames namespace {
59bb5f97e3SLang Hames 
60bb5f97e3SLang Hames class MachOHeaderMaterializationUnit : public MaterializationUnit {
61bb5f97e3SLang Hames public:
MachOHeaderMaterializationUnit(MachOPlatform & MOP,const SymbolStringPtr & HeaderStartSymbol)62bb5f97e3SLang Hames   MachOHeaderMaterializationUnit(MachOPlatform &MOP,
63bb5f97e3SLang Hames                                  const SymbolStringPtr &HeaderStartSymbol)
64ae73f3fdSLang Hames       : MaterializationUnit(createHeaderInterface(MOP, HeaderStartSymbol)),
65bb5f97e3SLang Hames         MOP(MOP) {}
66bb5f97e3SLang Hames 
getName() const67bb5f97e3SLang Hames   StringRef getName() const override { return "MachOHeaderMU"; }
68bb5f97e3SLang Hames 
materialize(std::unique_ptr<MaterializationResponsibility> R)69bb5f97e3SLang Hames   void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
70bb5f97e3SLang Hames     unsigned PointerSize;
71bb5f97e3SLang Hames     support::endianness Endianness;
722487db1fSLang Hames     const auto &TT =
732487db1fSLang Hames         MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
74bb5f97e3SLang Hames 
752487db1fSLang Hames     switch (TT.getArch()) {
76bb5f97e3SLang Hames     case Triple::aarch64:
77bb5f97e3SLang Hames     case Triple::x86_64:
78bb5f97e3SLang Hames       PointerSize = 8;
79bb5f97e3SLang Hames       Endianness = support::endianness::little;
80bb5f97e3SLang Hames       break;
81bb5f97e3SLang Hames     default:
82bb5f97e3SLang Hames       llvm_unreachable("Unrecognized architecture");
83bb5f97e3SLang Hames     }
84bb5f97e3SLang Hames 
85bb5f97e3SLang Hames     auto G = std::make_unique<jitlink::LinkGraph>(
862487db1fSLang Hames         "<MachOHeaderMU>", TT, PointerSize, Endianness,
872487db1fSLang Hames         jitlink::getGenericEdgeKindName);
88962a2479SLang Hames     auto &HeaderSection = G->createSection("__header", jitlink::MemProt::Read);
89bb5f97e3SLang Hames     auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
90bb5f97e3SLang Hames 
91bb5f97e3SLang Hames     // Init symbol is header-start symbol.
92bb5f97e3SLang Hames     G->addDefinedSymbol(HeaderBlock, 0, *R->getInitializerSymbol(),
93bb5f97e3SLang Hames                         HeaderBlock.getSize(), jitlink::Linkage::Strong,
94bb5f97e3SLang Hames                         jitlink::Scope::Default, false, true);
95bb5f97e3SLang Hames     for (auto &HS : AdditionalHeaderSymbols)
96bb5f97e3SLang Hames       G->addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name,
97bb5f97e3SLang Hames                           HeaderBlock.getSize(), jitlink::Linkage::Strong,
98bb5f97e3SLang Hames                           jitlink::Scope::Default, false, true);
99bb5f97e3SLang Hames 
100bb5f97e3SLang Hames     MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
101bb5f97e3SLang Hames   }
102bb5f97e3SLang Hames 
discard(const JITDylib & JD,const SymbolStringPtr & Sym)103bb5f97e3SLang Hames   void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
104bb5f97e3SLang Hames 
105bb5f97e3SLang Hames private:
106bb5f97e3SLang Hames   struct HeaderSymbol {
107bb5f97e3SLang Hames     const char *Name;
108bb5f97e3SLang Hames     uint64_t Offset;
109bb5f97e3SLang Hames   };
110bb5f97e3SLang Hames 
111bb5f97e3SLang Hames   static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
112bb5f97e3SLang Hames       {"___mh_executable_header", 0}};
113bb5f97e3SLang Hames 
createHeaderBlock(jitlink::LinkGraph & G,jitlink::Section & HeaderSection)114bb5f97e3SLang Hames   static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
115bb5f97e3SLang Hames                                            jitlink::Section &HeaderSection) {
116bb5f97e3SLang Hames     MachO::mach_header_64 Hdr;
117bb5f97e3SLang Hames     Hdr.magic = MachO::MH_MAGIC_64;
118bb5f97e3SLang Hames     switch (G.getTargetTriple().getArch()) {
119bb5f97e3SLang Hames     case Triple::aarch64:
120bb5f97e3SLang Hames       Hdr.cputype = MachO::CPU_TYPE_ARM64;
121bb5f97e3SLang Hames       Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
122bb5f97e3SLang Hames       break;
123bb5f97e3SLang Hames     case Triple::x86_64:
124bb5f97e3SLang Hames       Hdr.cputype = MachO::CPU_TYPE_X86_64;
125bb5f97e3SLang Hames       Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
126bb5f97e3SLang Hames       break;
127bb5f97e3SLang Hames     default:
128bb5f97e3SLang Hames       llvm_unreachable("Unrecognized architecture");
129bb5f97e3SLang Hames     }
130bb5f97e3SLang Hames     Hdr.filetype = MachO::MH_DYLIB; // Custom file type?
131bb5f97e3SLang Hames     Hdr.ncmds = 0;
132bb5f97e3SLang Hames     Hdr.sizeofcmds = 0;
133bb5f97e3SLang Hames     Hdr.flags = 0;
134bb5f97e3SLang Hames     Hdr.reserved = 0;
135bb5f97e3SLang Hames 
136bb5f97e3SLang Hames     if (G.getEndianness() != support::endian::system_endianness())
137bb5f97e3SLang Hames       MachO::swapStruct(Hdr);
138bb5f97e3SLang Hames 
139bb5f97e3SLang Hames     auto HeaderContent = G.allocateString(
140bb5f97e3SLang Hames         StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
141bb5f97e3SLang Hames 
142089acf25SLang Hames     return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
143089acf25SLang Hames                                 0);
144bb5f97e3SLang Hames   }
145bb5f97e3SLang Hames 
146ae73f3fdSLang Hames   static MaterializationUnit::Interface
createHeaderInterface(MachOPlatform & MOP,const SymbolStringPtr & HeaderStartSymbol)147ae73f3fdSLang Hames   createHeaderInterface(MachOPlatform &MOP,
148bb5f97e3SLang Hames                         const SymbolStringPtr &HeaderStartSymbol) {
149bb5f97e3SLang Hames     SymbolFlagsMap HeaderSymbolFlags;
150bb5f97e3SLang Hames 
151bb5f97e3SLang Hames     HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
152bb5f97e3SLang Hames     for (auto &HS : AdditionalHeaderSymbols)
153bb5f97e3SLang Hames       HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =
154bb5f97e3SLang Hames           JITSymbolFlags::Exported;
155bb5f97e3SLang Hames 
156ae73f3fdSLang Hames     return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
157ae73f3fdSLang Hames                                           HeaderStartSymbol);
158bb5f97e3SLang Hames   }
159bb5f97e3SLang Hames 
160bb5f97e3SLang Hames   MachOPlatform &MOP;
161bb5f97e3SLang Hames };
162bb5f97e3SLang Hames 
163bb5f97e3SLang Hames constexpr MachOHeaderMaterializationUnit::HeaderSymbol
164bb5f97e3SLang Hames     MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[];
165bb5f97e3SLang Hames 
166bb5f97e3SLang Hames StringRef EHFrameSectionName = "__TEXT,__eh_frame";
167bb5f97e3SLang Hames StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
168cdcc3547SLang Hames StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
169cdcc3547SLang Hames StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
170cdcc3547SLang Hames StringRef ObjCSelRefsSectionName = "__DATA,__objc_selrefs";
171cdcc3547SLang Hames StringRef Swift5ProtoSectionName = "__TEXT,__swift5_proto";
172cdcc3547SLang Hames StringRef Swift5ProtosSectionName = "__TEXT,__swift5_protos";
1732a739f27SBen Langmuir StringRef Swift5TypesSectionName = "__TEXT,__swift5_types";
174eda6afdaSLang Hames StringRef ThreadBSSSectionName = "__DATA,__thread_bss";
175eda6afdaSLang Hames StringRef ThreadDataSectionName = "__DATA,__thread_data";
176eda6afdaSLang Hames StringRef ThreadVarsSectionName = "__DATA,__thread_vars";
177bb5f97e3SLang Hames 
178cdcc3547SLang Hames StringRef InitSectionNames[] = {
179cdcc3547SLang Hames     ModInitFuncSectionName, ObjCSelRefsSectionName, ObjCClassListSectionName,
1802a739f27SBen Langmuir     Swift5ProtosSectionName, Swift5ProtoSectionName, Swift5TypesSectionName};
181bb5f97e3SLang Hames 
182bb5f97e3SLang Hames } // end anonymous namespace
183bb5f97e3SLang Hames 
18485fb9976SLang Hames namespace llvm {
18585fb9976SLang Hames namespace orc {
18685fb9976SLang Hames 
187bb5f97e3SLang Hames Expected<std::unique_ptr<MachOPlatform>>
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,const char * OrcRuntimePath,Optional<SymbolAliasMap> RuntimeAliases)188bb5f97e3SLang Hames MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
1892487db1fSLang Hames                       JITDylib &PlatformJD, const char *OrcRuntimePath,
190bb5f97e3SLang Hames                       Optional<SymbolAliasMap> RuntimeAliases) {
191bb5f97e3SLang Hames 
1922487db1fSLang Hames   auto &EPC = ES.getExecutorProcessControl();
1932487db1fSLang Hames 
194bb5f97e3SLang Hames   // If the target is not supported then bail out immediately.
195bb5f97e3SLang Hames   if (!supportedTarget(EPC.getTargetTriple()))
196bb5f97e3SLang Hames     return make_error<StringError>("Unsupported MachOPlatform triple: " +
197bb5f97e3SLang Hames                                        EPC.getTargetTriple().str(),
198bb5f97e3SLang Hames                                    inconvertibleErrorCode());
199bb5f97e3SLang Hames 
200bb5f97e3SLang Hames   // Create default aliases if the caller didn't supply any.
201bb5f97e3SLang Hames   if (!RuntimeAliases)
202bb5f97e3SLang Hames     RuntimeAliases = standardPlatformAliases(ES);
203bb5f97e3SLang Hames 
204bb5f97e3SLang Hames   // Define the aliases.
205bb5f97e3SLang Hames   if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
206bb5f97e3SLang Hames     return std::move(Err);
207bb5f97e3SLang Hames 
208bb5f97e3SLang Hames   // Add JIT-dispatch function support symbols.
209bb5f97e3SLang Hames   if (auto Err = PlatformJD.define(absoluteSymbols(
210bb5f97e3SLang Hames           {{ES.intern("___orc_rt_jit_dispatch"),
211ef391df2SLang Hames             {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
212bb5f97e3SLang Hames              JITSymbolFlags::Exported}},
213bb5f97e3SLang Hames            {ES.intern("___orc_rt_jit_dispatch_ctx"),
214ef391df2SLang Hames             {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
215bb5f97e3SLang Hames              JITSymbolFlags::Exported}}})))
216bb5f97e3SLang Hames     return std::move(Err);
217bb5f97e3SLang Hames 
218bb5f97e3SLang Hames   // Create a generator for the ORC runtime archive.
219bb5f97e3SLang Hames   auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
220bb5f97e3SLang Hames       ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
221bb5f97e3SLang Hames   if (!OrcRuntimeArchiveGenerator)
222bb5f97e3SLang Hames     return OrcRuntimeArchiveGenerator.takeError();
223bb5f97e3SLang Hames 
224bb5f97e3SLang Hames   // Create the instance.
225bb5f97e3SLang Hames   Error Err = Error::success();
226bb5f97e3SLang Hames   auto P = std::unique_ptr<MachOPlatform>(
2272487db1fSLang Hames       new MachOPlatform(ES, ObjLinkingLayer, PlatformJD,
228bb5f97e3SLang Hames                         std::move(*OrcRuntimeArchiveGenerator), Err));
229bb5f97e3SLang Hames   if (Err)
230bb5f97e3SLang Hames     return std::move(Err);
231bb5f97e3SLang Hames   return std::move(P);
23285fb9976SLang Hames }
23385fb9976SLang Hames 
setupJITDylib(JITDylib & JD)23485fb9976SLang Hames Error MachOPlatform::setupJITDylib(JITDylib &JD) {
235f9aef477SLang Hames   if (auto Err = JD.define(std::make_unique<MachOHeaderMaterializationUnit>(
236f9aef477SLang Hames           *this, MachOHeaderStartSymbol)))
237f9aef477SLang Hames     return Err;
238f9aef477SLang Hames 
239f9aef477SLang Hames   return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();
24085fb9976SLang Hames }
24185fb9976SLang Hames 
teardownJITDylib(JITDylib & JD)242f9aef477SLang Hames Error MachOPlatform::teardownJITDylib(JITDylib &JD) {
243f9aef477SLang Hames   std::lock_guard<std::mutex> Lock(PlatformMutex);
244f9aef477SLang Hames   auto I = JITDylibToHeaderAddr.find(&JD);
245f9aef477SLang Hames   if (I != JITDylibToHeaderAddr.end()) {
246f9aef477SLang Hames     assert(HeaderAddrToJITDylib.count(I->second) &&
247f9aef477SLang Hames            "HeaderAddrToJITDylib missing entry");
248f9aef477SLang Hames     HeaderAddrToJITDylib.erase(I->second);
249f9aef477SLang Hames     JITDylibToHeaderAddr.erase(I);
250f9aef477SLang Hames   }
251f9aef477SLang Hames   JITDylibToPThreadKey.erase(&JD);
252f9aef477SLang Hames   return Error::success();
253f9aef477SLang Hames }
254ade71641SLang Hames 
notifyAdding(ResourceTracker & RT,const MaterializationUnit & MU)2550aec49c8SLang Hames Error MachOPlatform::notifyAdding(ResourceTracker &RT,
2560aec49c8SLang Hames                                   const MaterializationUnit &MU) {
2570aec49c8SLang Hames   auto &JD = RT.getJITDylib();
25885fb9976SLang Hames   const auto &InitSym = MU.getInitializerSymbol();
25985fb9976SLang Hames   if (!InitSym)
26085fb9976SLang Hames     return Error::success();
26185fb9976SLang Hames 
262cb84e482SLang Hames   RegisteredInitSymbols[&JD].add(InitSym,
263cb84e482SLang Hames                                  SymbolLookupFlags::WeaklyReferencedSymbol);
2648363ff04SLang Hames   LLVM_DEBUG({
2658363ff04SLang Hames     dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
2668363ff04SLang Hames            << MU.getName() << "\n";
2678363ff04SLang Hames   });
26885fb9976SLang Hames   return Error::success();
26985fb9976SLang Hames }
27085fb9976SLang Hames 
notifyRemoving(ResourceTracker & RT)2710aec49c8SLang Hames Error MachOPlatform::notifyRemoving(ResourceTracker &RT) {
27285fb9976SLang Hames   llvm_unreachable("Not supported yet");
27385fb9976SLang Hames }
27485fb9976SLang Hames 
addAliases(ExecutionSession & ES,SymbolAliasMap & Aliases,ArrayRef<std::pair<const char *,const char * >> AL)275bb5f97e3SLang Hames static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
276bb5f97e3SLang Hames                        ArrayRef<std::pair<const char *, const char *>> AL) {
277bb5f97e3SLang Hames   for (auto &KV : AL) {
278bb5f97e3SLang Hames     auto AliasName = ES.intern(KV.first);
279bb5f97e3SLang Hames     assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
280bb5f97e3SLang Hames     Aliases[std::move(AliasName)] = {ES.intern(KV.second),
281bb5f97e3SLang Hames                                      JITSymbolFlags::Exported};
282bb5f97e3SLang Hames   }
283bb5f97e3SLang Hames }
28485fb9976SLang Hames 
standardPlatformAliases(ExecutionSession & ES)285bb5f97e3SLang Hames SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) {
286bb5f97e3SLang Hames   SymbolAliasMap Aliases;
287bb5f97e3SLang Hames   addAliases(ES, Aliases, requiredCXXAliases());
288bb5f97e3SLang Hames   addAliases(ES, Aliases, standardRuntimeUtilityAliases());
289bb5f97e3SLang Hames   return Aliases;
290bb5f97e3SLang Hames }
291bb5f97e3SLang Hames 
292bb5f97e3SLang Hames ArrayRef<std::pair<const char *, const char *>>
requiredCXXAliases()293bb5f97e3SLang Hames MachOPlatform::requiredCXXAliases() {
294bb5f97e3SLang Hames   static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
295bb5f97e3SLang Hames       {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}};
296bb5f97e3SLang Hames 
297df477706SLang Hames   return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
298bb5f97e3SLang Hames }
299bb5f97e3SLang Hames 
300bb5f97e3SLang Hames ArrayRef<std::pair<const char *, const char *>>
standardRuntimeUtilityAliases()301bb5f97e3SLang Hames MachOPlatform::standardRuntimeUtilityAliases() {
302bb5f97e3SLang Hames   static const std::pair<const char *, const char *>
303bb5f97e3SLang Hames       StandardRuntimeUtilityAliases[] = {
304bb5f97e3SLang Hames           {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
305*1aa71f86SPeter S. Housel           {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
306*1aa71f86SPeter S. Housel           {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
307*1aa71f86SPeter S. Housel           {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
308*1aa71f86SPeter S. Housel           {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
309bb5f97e3SLang Hames           {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
310bb5f97e3SLang Hames 
311df477706SLang Hames   return ArrayRef<std::pair<const char *, const char *>>(
312df477706SLang Hames       StandardRuntimeUtilityAliases);
313bb5f97e3SLang Hames }
314bb5f97e3SLang Hames 
isInitializerSection(StringRef SegName,StringRef SectName)315cdcc3547SLang Hames bool MachOPlatform::isInitializerSection(StringRef SegName,
316cdcc3547SLang Hames                                          StringRef SectName) {
317cdcc3547SLang Hames   for (auto &Name : InitSectionNames) {
318cdcc3547SLang Hames     if (Name.startswith(SegName) && Name.substr(7) == SectName)
319cdcc3547SLang Hames       return true;
320cdcc3547SLang Hames   }
321cdcc3547SLang Hames   return false;
322cdcc3547SLang Hames }
323cdcc3547SLang Hames 
supportedTarget(const Triple & TT)324bb5f97e3SLang Hames bool MachOPlatform::supportedTarget(const Triple &TT) {
325bb5f97e3SLang Hames   switch (TT.getArch()) {
3263d13ee28SBen Langmuir   case Triple::aarch64:
327bb5f97e3SLang Hames   case Triple::x86_64:
328bb5f97e3SLang Hames     return true;
329bb5f97e3SLang Hames   default:
330bb5f97e3SLang Hames     return false;
331bb5f97e3SLang Hames   }
332bb5f97e3SLang Hames }
333bb5f97e3SLang Hames 
MachOPlatform(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,Error & Err)334bb5f97e3SLang Hames MachOPlatform::MachOPlatform(
335bb5f97e3SLang Hames     ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
3362487db1fSLang Hames     JITDylib &PlatformJD,
337bb5f97e3SLang Hames     std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
3382487db1fSLang Hames     : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
339bb5f97e3SLang Hames       MachOHeaderStartSymbol(ES.intern("___dso_handle")) {
340bb5f97e3SLang Hames   ErrorAsOutParameter _(&Err);
341bb5f97e3SLang Hames 
342bb5f97e3SLang Hames   ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));
343bb5f97e3SLang Hames 
344bb5f97e3SLang Hames   PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
345bb5f97e3SLang Hames 
346ff846fcbSLang Hames   // Force linking of eh-frame registration functions.
347ff846fcbSLang Hames   if (auto Err2 = lookupAndRecordAddrs(
348ff846fcbSLang Hames           ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
349ff846fcbSLang Hames           {{ES.intern("___orc_rt_macho_register_ehframe_section"),
350ff846fcbSLang Hames             &orc_rt_macho_register_ehframe_section},
351ff846fcbSLang Hames            {ES.intern("___orc_rt_macho_deregister_ehframe_section"),
352ff846fcbSLang Hames             &orc_rt_macho_deregister_ehframe_section}})) {
353ff846fcbSLang Hames     Err = std::move(Err2);
354ff846fcbSLang Hames     return;
355ff846fcbSLang Hames   }
356ff846fcbSLang Hames 
357ff846fcbSLang Hames   State = BootstrapPhase2;
358ff846fcbSLang Hames 
359bb5f97e3SLang Hames   // Associate wrapper function tags with JIT-side function implementations.
360bb5f97e3SLang Hames   if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
361bb5f97e3SLang Hames     Err = std::move(E2);
362bb5f97e3SLang Hames     return;
363bb5f97e3SLang Hames   }
364bb5f97e3SLang Hames 
365bb5f97e3SLang Hames   // Lookup addresses of runtime functions callable by the platform,
366bb5f97e3SLang Hames   // call the platform bootstrap function to initialize the platform-state
367bb5f97e3SLang Hames   // object in the executor.
368bb5f97e3SLang Hames   if (auto E2 = bootstrapMachORuntime(PlatformJD)) {
369bb5f97e3SLang Hames     Err = std::move(E2);
370bb5f97e3SLang Hames     return;
371bb5f97e3SLang Hames   }
372ff846fcbSLang Hames 
373f9aef477SLang Hames   // PlatformJD hasn't been set up by the platform yet (since we're creating
374f9aef477SLang Hames   // the platform now), so set it up.
375f9aef477SLang Hames   if (auto E2 = setupJITDylib(PlatformJD)) {
376f9aef477SLang Hames     Err = std::move(E2);
377f9aef477SLang Hames     return;
378f9aef477SLang Hames   }
379f9aef477SLang Hames 
380ff846fcbSLang Hames   State = Initialized;
381bb5f97e3SLang Hames }
382bb5f97e3SLang Hames 
associateRuntimeSupportFunctions(JITDylib & PlatformJD)383bb5f97e3SLang Hames Error MachOPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
3842487db1fSLang Hames   ExecutionSession::JITDispatchHandlerAssociationMap WFs;
385bb5f97e3SLang Hames 
386f9aef477SLang Hames   using PushInitializersSPSSig =
387f9aef477SLang Hames       SPSExpected<SPSMachOJITDylibDepInfoMap>(SPSExecutorAddr);
388f9aef477SLang Hames   WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] =
389f9aef477SLang Hames       ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
390f9aef477SLang Hames           this, &MachOPlatform::rt_pushInitializers);
391bb5f97e3SLang Hames 
392bb5f97e3SLang Hames   using LookupSymbolSPSSig =
393ef391df2SLang Hames       SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
394bb5f97e3SLang Hames   WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] =
3952487db1fSLang Hames       ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
396bb5f97e3SLang Hames                                               &MachOPlatform::rt_lookupSymbol);
397bb5f97e3SLang Hames 
3982487db1fSLang Hames   return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
399bb5f97e3SLang Hames }
400bb5f97e3SLang Hames 
pushInitializersLoop(PushInitializersSendResultFn SendResult,JITDylibSP JD)401f9aef477SLang Hames void MachOPlatform::pushInitializersLoop(
402f9aef477SLang Hames     PushInitializersSendResultFn SendResult, JITDylibSP JD) {
40385fb9976SLang Hames   DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
404f9aef477SLang Hames   DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap;
405f9aef477SLang Hames   SmallVector<JITDylib *, 16> Worklist({JD.get()});
406f9aef477SLang Hames 
407eb918d8dSLang Hames   ES.runSessionLocked([&]() {
408f9aef477SLang Hames     while (!Worklist.empty()) {
409f9aef477SLang Hames       // FIXME: Check for defunct dylibs.
410f9aef477SLang Hames 
411f9aef477SLang Hames       auto DepJD = Worklist.back();
412f9aef477SLang Hames       Worklist.pop_back();
413f9aef477SLang Hames 
414f9aef477SLang Hames       // If we've already visited this JITDylib on this iteration then continue.
415f9aef477SLang Hames       if (JDDepMap.count(DepJD))
416f9aef477SLang Hames         continue;
417f9aef477SLang Hames 
418f9aef477SLang Hames       // Add dep info.
419f9aef477SLang Hames       auto &DM = JDDepMap[DepJD];
420f9aef477SLang Hames       DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
421f9aef477SLang Hames         for (auto &KV : O) {
422f9aef477SLang Hames           if (KV.first == DepJD)
423f9aef477SLang Hames             continue;
424f9aef477SLang Hames           DM.push_back(KV.first);
425f9aef477SLang Hames           Worklist.push_back(KV.first);
426f9aef477SLang Hames         }
427f9aef477SLang Hames       });
428f9aef477SLang Hames 
429f9aef477SLang Hames       // Add any registered init symbols.
430f9aef477SLang Hames       auto RISItr = RegisteredInitSymbols.find(DepJD);
43185fb9976SLang Hames       if (RISItr != RegisteredInitSymbols.end()) {
432f9aef477SLang Hames         NewInitSymbols[DepJD] = std::move(RISItr->second);
43385fb9976SLang Hames         RegisteredInitSymbols.erase(RISItr);
43485fb9976SLang Hames       }
43585fb9976SLang Hames     }
436eb918d8dSLang Hames   });
43785fb9976SLang Hames 
438f9aef477SLang Hames   // If there are no further init symbols to look up then send the link order
439f9aef477SLang Hames   // (as a list of header addresses) to the caller.
440bb5f97e3SLang Hames   if (NewInitSymbols.empty()) {
441f9aef477SLang Hames 
442f9aef477SLang Hames     // To make the list intelligible to the runtime we need to convert all
443f9aef477SLang Hames     // JITDylib pointers to their header addresses.
444f9aef477SLang Hames     DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
445f9aef477SLang Hames     HeaderAddrs.reserve(JDDepMap.size());
446f9aef477SLang Hames     {
447f9aef477SLang Hames       std::lock_guard<std::mutex> Lock(PlatformMutex);
448f9aef477SLang Hames       for (auto &KV : JDDepMap) {
449f9aef477SLang Hames         auto I = JITDylibToHeaderAddr.find(KV.first);
450f9aef477SLang Hames         if (I == JITDylibToHeaderAddr.end()) {
451f9aef477SLang Hames           // The header address should have been materialized by the previous
452f9aef477SLang Hames           // round, but we need to handle the pathalogical case where someone
453f9aef477SLang Hames           // removes the symbol on another thread while we're running.
454f9aef477SLang Hames           SendResult(
455f9aef477SLang Hames               make_error<StringError>("JITDylib " + KV.first->getName() +
456f9aef477SLang Hames                                           " has no registered header address",
457f9aef477SLang Hames                                       inconvertibleErrorCode()));
458f9aef477SLang Hames           return;
459f9aef477SLang Hames         }
460f9aef477SLang Hames         HeaderAddrs[KV.first] = I->second;
461f9aef477SLang Hames       }
462f9aef477SLang Hames     }
463f9aef477SLang Hames 
464f9aef477SLang Hames     // Build the dep info map to return.
465f9aef477SLang Hames     MachOJITDylibDepInfoMap DIM;
466f9aef477SLang Hames     DIM.reserve(JDDepMap.size());
467f9aef477SLang Hames     for (auto &KV : JDDepMap) {
468f9aef477SLang Hames       assert(HeaderAddrs.count(KV.first) && "Missing header addr");
469f9aef477SLang Hames       auto H = HeaderAddrs[KV.first];
470f9aef477SLang Hames       MachOJITDylibDepInfo DepInfo;
471f9aef477SLang Hames       for (auto &Dep : KV.second) {
472f9aef477SLang Hames         assert(HeaderAddrs.count(Dep) && "Missing header addr");
473f9aef477SLang Hames         DepInfo.DepHeaders.push_back(HeaderAddrs[Dep]);
474f9aef477SLang Hames       }
475f9aef477SLang Hames       DIM.push_back(std::make_pair(H, std::move(DepInfo)));
476f9aef477SLang Hames     }
477f9aef477SLang Hames     SendResult(DIM);
478c40ce0daSLang Hames     return;
47985fb9976SLang Hames   }
48085fb9976SLang Hames 
481bb5f97e3SLang Hames   // Otherwise issue a lookup and re-run this phase when it completes.
482bb5f97e3SLang Hames   lookupInitSymbolsAsync(
483bb5f97e3SLang Hames       [this, SendResult = std::move(SendResult), &JD](Error Err) mutable {
484bb5f97e3SLang Hames         if (Err)
485bb5f97e3SLang Hames           SendResult(std::move(Err));
486bb5f97e3SLang Hames         else
487f9aef477SLang Hames           pushInitializersLoop(std::move(SendResult), JD);
488bb5f97e3SLang Hames       },
489bb5f97e3SLang Hames       ES, std::move(NewInitSymbols));
490bb5f97e3SLang Hames }
491bb5f97e3SLang Hames 
rt_pushInitializers(PushInitializersSendResultFn SendResult,ExecutorAddr JDHeaderAddr)492f9aef477SLang Hames void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
493f9aef477SLang Hames                                         ExecutorAddr JDHeaderAddr) {
494f9aef477SLang Hames   JITDylibSP JD;
495bb5f97e3SLang Hames   {
496bb5f97e3SLang Hames     std::lock_guard<std::mutex> Lock(PlatformMutex);
497f9aef477SLang Hames     auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
498bb5f97e3SLang Hames     if (I != HeaderAddrToJITDylib.end())
499bb5f97e3SLang Hames       JD = I->second;
500bb5f97e3SLang Hames   }
501bb5f97e3SLang Hames 
502bb5f97e3SLang Hames   LLVM_DEBUG({
503f9aef477SLang Hames     dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
504f9aef477SLang Hames     if (JD)
505f9aef477SLang Hames       dbgs() << "pushing initializers for " << JD->getName() << "\n";
506f9aef477SLang Hames     else
507f9aef477SLang Hames       dbgs() << "No JITDylib for header address.\n";
508bb5f97e3SLang Hames   });
509f9aef477SLang Hames 
510f9aef477SLang Hames   if (!JD) {
511f9aef477SLang Hames     SendResult(
512f9aef477SLang Hames         make_error<StringError>("No JITDylib with header addr " +
513f9aef477SLang Hames                                     formatv("{0:x}", JDHeaderAddr.getValue()),
514bb5f97e3SLang Hames                                 inconvertibleErrorCode()));
515bb5f97e3SLang Hames     return;
516bb5f97e3SLang Hames   }
517bb5f97e3SLang Hames 
518f9aef477SLang Hames   pushInitializersLoop(std::move(SendResult), JD);
519bb5f97e3SLang Hames }
520bb5f97e3SLang Hames 
rt_lookupSymbol(SendSymbolAddressFn SendResult,ExecutorAddr Handle,StringRef SymbolName)521bb5f97e3SLang Hames void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
522ef391df2SLang Hames                                     ExecutorAddr Handle, StringRef SymbolName) {
523bb5f97e3SLang Hames   LLVM_DEBUG({
524bb5f97e3SLang Hames     dbgs() << "MachOPlatform::rt_lookupSymbol(\""
525bb5f97e3SLang Hames            << formatv("{0:x}", Handle.getValue()) << "\")\n";
526bb5f97e3SLang Hames   });
527bb5f97e3SLang Hames 
528bb5f97e3SLang Hames   JITDylib *JD = nullptr;
529bb5f97e3SLang Hames 
530bb5f97e3SLang Hames   {
531bb5f97e3SLang Hames     std::lock_guard<std::mutex> Lock(PlatformMutex);
532118e953bSLang Hames     auto I = HeaderAddrToJITDylib.find(Handle);
533bb5f97e3SLang Hames     if (I != HeaderAddrToJITDylib.end())
534bb5f97e3SLang Hames       JD = I->second;
535bb5f97e3SLang Hames   }
536bb5f97e3SLang Hames 
537bb5f97e3SLang Hames   if (!JD) {
538bb5f97e3SLang Hames     LLVM_DEBUG({
539bb5f97e3SLang Hames       dbgs() << "  No JITDylib for handle "
540bb5f97e3SLang Hames              << formatv("{0:x}", Handle.getValue()) << "\n";
541bb5f97e3SLang Hames     });
542bb5f97e3SLang Hames     SendResult(make_error<StringError>("No JITDylib associated with handle " +
543bb5f97e3SLang Hames                                            formatv("{0:x}", Handle.getValue()),
544bb5f97e3SLang Hames                                        inconvertibleErrorCode()));
545bb5f97e3SLang Hames     return;
546bb5f97e3SLang Hames   }
547bb5f97e3SLang Hames 
548af5602d3SHubert Tong   // Use functor class to work around XL build compiler issue on AIX.
549af5602d3SHubert Tong   class RtLookupNotifyComplete {
550af5602d3SHubert Tong   public:
551af5602d3SHubert Tong     RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
552af5602d3SHubert Tong         : SendResult(std::move(SendResult)) {}
553af5602d3SHubert Tong     void operator()(Expected<SymbolMap> Result) {
554af5602d3SHubert Tong       if (Result) {
555af5602d3SHubert Tong         assert(Result->size() == 1 && "Unexpected result map count");
556ef391df2SLang Hames         SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
557af5602d3SHubert Tong       } else {
558af5602d3SHubert Tong         SendResult(Result.takeError());
559af5602d3SHubert Tong       }
560af5602d3SHubert Tong     }
561af5602d3SHubert Tong 
562af5602d3SHubert Tong   private:
563af5602d3SHubert Tong     SendSymbolAddressFn SendResult;
564af5602d3SHubert Tong   };
565af5602d3SHubert Tong 
566bb5f97e3SLang Hames   // FIXME: Proper mangling.
567bb5f97e3SLang Hames   auto MangledName = ("_" + SymbolName).str();
568bb5f97e3SLang Hames   ES.lookup(
569bb5f97e3SLang Hames       LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
570bb5f97e3SLang Hames       SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready,
571af5602d3SHubert Tong       RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
572bb5f97e3SLang Hames }
573bb5f97e3SLang Hames 
bootstrapMachORuntime(JITDylib & PlatformJD)574bb5f97e3SLang Hames Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) {
57564288571SLang Hames   if (auto Err = lookupAndRecordAddrs(
57664288571SLang Hames           ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
57764288571SLang Hames           {{ES.intern("___orc_rt_macho_platform_bootstrap"),
57864288571SLang Hames             &orc_rt_macho_platform_bootstrap},
57964288571SLang Hames            {ES.intern("___orc_rt_macho_platform_shutdown"),
58064288571SLang Hames             &orc_rt_macho_platform_shutdown},
581f9aef477SLang Hames            {ES.intern("___orc_rt_macho_register_jitdylib"),
582f9aef477SLang Hames             &orc_rt_macho_register_jitdylib},
583f9aef477SLang Hames            {ES.intern("___orc_rt_macho_deregister_jitdylib"),
584f9aef477SLang Hames             &orc_rt_macho_deregister_jitdylib},
585f9aef477SLang Hames            {ES.intern("___orc_rt_macho_register_object_platform_sections"),
586f9aef477SLang Hames             &orc_rt_macho_register_object_platform_sections},
587f9aef477SLang Hames            {ES.intern("___orc_rt_macho_deregister_object_platform_sections"),
588f9aef477SLang Hames             &orc_rt_macho_deregister_object_platform_sections},
58964288571SLang Hames            {ES.intern("___orc_rt_macho_create_pthread_key"),
59064288571SLang Hames             &orc_rt_macho_create_pthread_key}}))
59164288571SLang Hames     return Err;
592bb5f97e3SLang Hames 
593ff846fcbSLang Hames   return ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap);
59485fb9976SLang Hames }
59585fb9976SLang Hames 
createPThreadKey()596eda6afdaSLang Hames Expected<uint64_t> MachOPlatform::createPThreadKey() {
597eda6afdaSLang Hames   if (!orc_rt_macho_create_pthread_key)
598eda6afdaSLang Hames     return make_error<StringError>(
599eda6afdaSLang Hames         "Attempting to create pthread key in target, but runtime support has "
600eda6afdaSLang Hames         "not been loaded yet",
601eda6afdaSLang Hames         inconvertibleErrorCode());
602eda6afdaSLang Hames 
603eda6afdaSLang Hames   Expected<uint64_t> Result(0);
6042487db1fSLang Hames   if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
60521a06254SLang Hames           orc_rt_macho_create_pthread_key, Result))
606eda6afdaSLang Hames     return std::move(Err);
607eda6afdaSLang Hames   return Result;
608eda6afdaSLang Hames }
609eda6afdaSLang Hames 
modifyPassConfig(MaterializationResponsibility & MR,jitlink::LinkGraph & LG,jitlink::PassConfiguration & Config)610bb5f97e3SLang Hames void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
611bb5f97e3SLang Hames     MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
612bb5f97e3SLang Hames     jitlink::PassConfiguration &Config) {
613bb5f97e3SLang Hames 
614ff846fcbSLang Hames   auto PS = MP.State.load();
615ff846fcbSLang Hames 
616afeb1e4aSLang Hames   // --- Handle Initializers ---
617afeb1e4aSLang Hames   if (auto InitSymbol = MR.getInitializerSymbol()) {
618afeb1e4aSLang Hames 
619afeb1e4aSLang Hames     // If the initializer symbol is the MachOHeader start symbol then just
620afeb1e4aSLang Hames     // register it and then bail out -- the header materialization unit
621afeb1e4aSLang Hames     // definitely doesn't need any other passes.
622afeb1e4aSLang Hames     if (InitSymbol == MP.MachOHeaderStartSymbol) {
623afeb1e4aSLang Hames       Config.PostAllocationPasses.push_back([this, &MR](jitlink::LinkGraph &G) {
624afeb1e4aSLang Hames         return associateJITDylibHeaderSymbol(G, MR);
625afeb1e4aSLang Hames       });
626bb5f97e3SLang Hames       return;
627bb5f97e3SLang Hames     }
628bb5f97e3SLang Hames 
629afeb1e4aSLang Hames     // If the object contains an init symbol other than the header start symbol
630afeb1e4aSLang Hames     // then add passes to preserve, process and register the init
631afeb1e4aSLang Hames     // sections/symbols.
632afeb1e4aSLang Hames     Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
633afeb1e4aSLang Hames       if (auto Err = preserveInitSections(G, MR))
634afeb1e4aSLang Hames         return Err;
635afeb1e4aSLang Hames       return processObjCImageInfo(G, MR);
636afeb1e4aSLang Hames     });
637afeb1e4aSLang Hames   }
638afeb1e4aSLang Hames 
639afeb1e4aSLang Hames   // --- Add passes for eh-frame and TLV support ---
640ff846fcbSLang Hames   if (PS == MachOPlatform::BootstrapPhase1) {
641ff846fcbSLang Hames     Config.PostFixupPasses.push_back(
642ff846fcbSLang Hames         [this](jitlink::LinkGraph &G) { return registerEHSectionsPhase1(G); });
643ff846fcbSLang Hames     return;
644ff846fcbSLang Hames   }
645afeb1e4aSLang Hames 
646afeb1e4aSLang Hames   // Insert TLV lowering at the start of the PostPrunePasses, since we want
647afeb1e4aSLang Hames   // it to run before GOT/PLT lowering.
648afeb1e4aSLang Hames   Config.PostPrunePasses.insert(
649afeb1e4aSLang Hames       Config.PostPrunePasses.begin(),
650afeb1e4aSLang Hames       [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
651afeb1e4aSLang Hames         return fixTLVSectionsAndEdges(G, JD);
652afeb1e4aSLang Hames       });
653afeb1e4aSLang Hames 
654f9aef477SLang Hames   // Add a pass to register the final addresses of any special sections in the
655f9aef477SLang Hames   // object with the runtime.
656f9aef477SLang Hames   Config.PostAllocationPasses.push_back(
657f9aef477SLang Hames       [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
658f9aef477SLang Hames         return registerObjectPlatformSections(G, JD);
659f9aef477SLang Hames       });
66085fb9976SLang Hames }
66185fb9976SLang Hames 
662963378bdSLang Hames ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
getSyntheticSymbolDependencies(MaterializationResponsibility & MR)663bb5f97e3SLang Hames MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies(
66485fb9976SLang Hames     MaterializationResponsibility &MR) {
665bb5f97e3SLang Hames   std::lock_guard<std::mutex> Lock(PluginMutex);
66685fb9976SLang Hames   auto I = InitSymbolDeps.find(&MR);
66785fb9976SLang Hames   if (I != InitSymbolDeps.end()) {
668963378bdSLang Hames     SyntheticSymbolDependenciesMap Result;
66985fb9976SLang Hames     Result[MR.getInitializerSymbol()] = std::move(I->second);
67085fb9976SLang Hames     InitSymbolDeps.erase(&MR);
67185fb9976SLang Hames     return Result;
67285fb9976SLang Hames   }
673963378bdSLang Hames   return SyntheticSymbolDependenciesMap();
67485fb9976SLang Hames }
67585fb9976SLang Hames 
associateJITDylibHeaderSymbol(jitlink::LinkGraph & G,MaterializationResponsibility & MR)676afeb1e4aSLang Hames Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
677afeb1e4aSLang Hames     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
678bb5f97e3SLang Hames   auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
679bb5f97e3SLang Hames     return Sym->getName() == *MP.MachOHeaderStartSymbol;
680bb5f97e3SLang Hames   });
681afeb1e4aSLang Hames   assert(I != G.defined_symbols().end() && "Missing MachO header start symbol");
682afeb1e4aSLang Hames 
683afeb1e4aSLang Hames   auto &JD = MR.getTargetJITDylib();
684bb5f97e3SLang Hames   std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
685118e953bSLang Hames   auto HeaderAddr = (*I)->getAddress();
686f9aef477SLang Hames   MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
687bb5f97e3SLang Hames   MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
688f9aef477SLang Hames   G.allocActions().push_back(
689f9aef477SLang Hames       {cantFail(
690f9aef477SLang Hames            WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>(
691f9aef477SLang Hames                MP.orc_rt_macho_register_jitdylib, JD.getName(), HeaderAddr)),
692f9aef477SLang Hames        cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
693f9aef477SLang Hames            MP.orc_rt_macho_deregister_jitdylib, HeaderAddr))});
694bb5f97e3SLang Hames   return Error::success();
695bb5f97e3SLang Hames }
696bb5f97e3SLang Hames 
preserveInitSections(jitlink::LinkGraph & G,MaterializationResponsibility & MR)697bb5f97e3SLang Hames Error MachOPlatform::MachOPlatformPlugin::preserveInitSections(
69885fb9976SLang Hames     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
69985fb9976SLang Hames 
700bb5f97e3SLang Hames   JITLinkSymbolSet InitSectionSymbols;
701bb5f97e3SLang Hames   for (auto &InitSectionName : InitSectionNames) {
702bb5f97e3SLang Hames     // Skip non-init sections.
703bb5f97e3SLang Hames     auto *InitSection = G.findSectionByName(InitSectionName);
704bb5f97e3SLang Hames     if (!InitSection)
705bb5f97e3SLang Hames       continue;
70685fb9976SLang Hames 
707bb5f97e3SLang Hames     // Make a pass over live symbols in the section: those blocks are already
708bb5f97e3SLang Hames     // preserved.
709bb5f97e3SLang Hames     DenseSet<jitlink::Block *> AlreadyLiveBlocks;
710bb5f97e3SLang Hames     for (auto &Sym : InitSection->symbols()) {
711bb5f97e3SLang Hames       auto &B = Sym->getBlock();
712bb5f97e3SLang Hames       if (Sym->isLive() && Sym->getOffset() == 0 &&
713bb5f97e3SLang Hames           Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
714bb5f97e3SLang Hames         InitSectionSymbols.insert(Sym);
715bb5f97e3SLang Hames         AlreadyLiveBlocks.insert(&B);
716bb5f97e3SLang Hames       }
71785fb9976SLang Hames     }
71885fb9976SLang Hames 
719bb5f97e3SLang Hames     // Add anonymous symbols to preserve any not-already-preserved blocks.
720bb5f97e3SLang Hames     for (auto *B : InitSection->blocks())
721bb5f97e3SLang Hames       if (!AlreadyLiveBlocks.count(B))
722bb5f97e3SLang Hames         InitSectionSymbols.insert(
723bb5f97e3SLang Hames             &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
724bb5f97e3SLang Hames   }
72585fb9976SLang Hames 
726bb5f97e3SLang Hames   if (!InitSectionSymbols.empty()) {
727bb5f97e3SLang Hames     std::lock_guard<std::mutex> Lock(PluginMutex);
728bb5f97e3SLang Hames     InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
72985fb9976SLang Hames   }
73085fb9976SLang Hames 
73185fb9976SLang Hames   return Error::success();
73285fb9976SLang Hames }
73385fb9976SLang Hames 
processObjCImageInfo(jitlink::LinkGraph & G,MaterializationResponsibility & MR)734cdcc3547SLang Hames Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
735cdcc3547SLang Hames     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
736cdcc3547SLang Hames 
737cdcc3547SLang Hames   // If there's an ObjC imagine info then either
738cdcc3547SLang Hames   //   (1) It's the first __objc_imageinfo we've seen in this JITDylib. In
739cdcc3547SLang Hames   //       this case we name and record it.
740cdcc3547SLang Hames   // OR
741cdcc3547SLang Hames   //   (2) We already have a recorded __objc_imageinfo for this JITDylib,
742cdcc3547SLang Hames   //       in which case we just verify it.
743cdcc3547SLang Hames   auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName);
744cdcc3547SLang Hames   if (!ObjCImageInfo)
745cdcc3547SLang Hames     return Error::success();
746cdcc3547SLang Hames 
747cdcc3547SLang Hames   auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
748cdcc3547SLang Hames 
749cdcc3547SLang Hames   // Check that the section is not empty if present.
750cdcc3547SLang Hames   if (llvm::empty(ObjCImageInfoBlocks))
751cdcc3547SLang Hames     return make_error<StringError>("Empty " + ObjCImageInfoSectionName +
752cdcc3547SLang Hames                                        " section in " + G.getName(),
753cdcc3547SLang Hames                                    inconvertibleErrorCode());
754cdcc3547SLang Hames 
755cdcc3547SLang Hames   // Check that there's only one block in the section.
756cdcc3547SLang Hames   if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
757cdcc3547SLang Hames     return make_error<StringError>("Multiple blocks in " +
758cdcc3547SLang Hames                                        ObjCImageInfoSectionName +
759cdcc3547SLang Hames                                        " section in " + G.getName(),
760cdcc3547SLang Hames                                    inconvertibleErrorCode());
761cdcc3547SLang Hames 
762cdcc3547SLang Hames   // Check that the __objc_imageinfo section is unreferenced.
763cdcc3547SLang Hames   // FIXME: We could optimize this check if Symbols had a ref-count.
764cdcc3547SLang Hames   for (auto &Sec : G.sections()) {
765cdcc3547SLang Hames     if (&Sec != ObjCImageInfo)
766cdcc3547SLang Hames       for (auto *B : Sec.blocks())
767cdcc3547SLang Hames         for (auto &E : B->edges())
768cdcc3547SLang Hames           if (E.getTarget().isDefined() &&
769cdcc3547SLang Hames               &E.getTarget().getBlock().getSection() == ObjCImageInfo)
770cdcc3547SLang Hames             return make_error<StringError>(ObjCImageInfoSectionName +
771cdcc3547SLang Hames                                                " is referenced within file " +
772cdcc3547SLang Hames                                                G.getName(),
773cdcc3547SLang Hames                                            inconvertibleErrorCode());
774cdcc3547SLang Hames   }
775cdcc3547SLang Hames 
776cdcc3547SLang Hames   auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
777cdcc3547SLang Hames   auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
778cdcc3547SLang Hames   auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());
779cdcc3547SLang Hames   auto Flags =
780cdcc3547SLang Hames       support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());
781cdcc3547SLang Hames 
782cdcc3547SLang Hames   // Lock the mutex while we verify / update the ObjCImageInfos map.
783cdcc3547SLang Hames   std::lock_guard<std::mutex> Lock(PluginMutex);
784cdcc3547SLang Hames 
785cdcc3547SLang Hames   auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());
786cdcc3547SLang Hames   if (ObjCImageInfoItr != ObjCImageInfos.end()) {
787cdcc3547SLang Hames     // We've already registered an __objc_imageinfo section. Verify the
788cdcc3547SLang Hames     // content of this new section matches, then delete it.
789cdcc3547SLang Hames     if (ObjCImageInfoItr->second.first != Version)
790cdcc3547SLang Hames       return make_error<StringError>(
791cdcc3547SLang Hames           "ObjC version in " + G.getName() +
792cdcc3547SLang Hames               " does not match first registered version",
793cdcc3547SLang Hames           inconvertibleErrorCode());
794cdcc3547SLang Hames     if (ObjCImageInfoItr->second.second != Flags)
795cdcc3547SLang Hames       return make_error<StringError>("ObjC flags in " + G.getName() +
796cdcc3547SLang Hames                                          " do not match first registered flags",
797cdcc3547SLang Hames                                      inconvertibleErrorCode());
798cdcc3547SLang Hames 
799cdcc3547SLang Hames     // __objc_imageinfo is valid. Delete the block.
800cdcc3547SLang Hames     for (auto *S : ObjCImageInfo->symbols())
801cdcc3547SLang Hames       G.removeDefinedSymbol(*S);
802cdcc3547SLang Hames     G.removeBlock(ObjCImageInfoBlock);
803cdcc3547SLang Hames   } else {
804cdcc3547SLang Hames     // We haven't registered an __objc_imageinfo section yet. Register and
805cdcc3547SLang Hames     // move on. The section should already be marked no-dead-strip.
806cdcc3547SLang Hames     ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags);
807cdcc3547SLang Hames   }
808cdcc3547SLang Hames 
809cdcc3547SLang Hames   return Error::success();
810cdcc3547SLang Hames }
811cdcc3547SLang Hames 
fixTLVSectionsAndEdges(jitlink::LinkGraph & G,JITDylib & JD)812eda6afdaSLang Hames Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
813eda6afdaSLang Hames     jitlink::LinkGraph &G, JITDylib &JD) {
814eda6afdaSLang Hames 
815eda6afdaSLang Hames   // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr.
816eda6afdaSLang Hames   for (auto *Sym : G.external_symbols())
817eda6afdaSLang Hames     if (Sym->getName() == "__tlv_bootstrap") {
818eda6afdaSLang Hames       Sym->setName("___orc_rt_macho_tlv_get_addr");
819eda6afdaSLang Hames       break;
820eda6afdaSLang Hames     }
821eda6afdaSLang Hames 
822eda6afdaSLang Hames   // Store key in __thread_vars struct fields.
823eda6afdaSLang Hames   if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) {
824eda6afdaSLang Hames     Optional<uint64_t> Key;
825eda6afdaSLang Hames     {
826eda6afdaSLang Hames       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
827eda6afdaSLang Hames       auto I = MP.JITDylibToPThreadKey.find(&JD);
828eda6afdaSLang Hames       if (I != MP.JITDylibToPThreadKey.end())
829eda6afdaSLang Hames         Key = I->second;
830eda6afdaSLang Hames     }
831eda6afdaSLang Hames 
832eda6afdaSLang Hames     if (!Key) {
833eda6afdaSLang Hames       if (auto KeyOrErr = MP.createPThreadKey())
834eda6afdaSLang Hames         Key = *KeyOrErr;
835eda6afdaSLang Hames       else
836eda6afdaSLang Hames         return KeyOrErr.takeError();
837eda6afdaSLang Hames     }
838eda6afdaSLang Hames 
839eda6afdaSLang Hames     uint64_t PlatformKeyBits =
840eda6afdaSLang Hames         support::endian::byte_swap(*Key, G.getEndianness());
841eda6afdaSLang Hames 
842eda6afdaSLang Hames     for (auto *B : ThreadDataSec->blocks()) {
843eda6afdaSLang Hames       if (B->getSize() != 3 * G.getPointerSize())
844eda6afdaSLang Hames         return make_error<StringError>("__thread_vars block at " +
845eda6afdaSLang Hames                                            formatv("{0:x}", B->getAddress()) +
846eda6afdaSLang Hames                                            " has unexpected size",
847eda6afdaSLang Hames                                        inconvertibleErrorCode());
848eda6afdaSLang Hames 
849eda6afdaSLang Hames       auto NewBlockContent = G.allocateBuffer(B->getSize());
850eda6afdaSLang Hames       llvm::copy(B->getContent(), NewBlockContent.data());
851eda6afdaSLang Hames       memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits,
852eda6afdaSLang Hames              G.getPointerSize());
853eda6afdaSLang Hames       B->setContent(NewBlockContent);
854eda6afdaSLang Hames     }
855eda6afdaSLang Hames   }
856eda6afdaSLang Hames 
857eda6afdaSLang Hames   // Transform any TLV edges into GOT edges.
858eda6afdaSLang Hames   for (auto *B : G.blocks())
859eda6afdaSLang Hames     for (auto &E : B->edges())
860eda6afdaSLang Hames       if (E.getKind() ==
86127ea3f16SLang Hames           jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable)
86227ea3f16SLang Hames         E.setKind(jitlink::x86_64::
86327ea3f16SLang Hames                       RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);
864eda6afdaSLang Hames 
865eda6afdaSLang Hames   return Error::success();
866eda6afdaSLang Hames }
867eda6afdaSLang Hames 
registerObjectPlatformSections(jitlink::LinkGraph & G,JITDylib & JD)868f9aef477SLang Hames Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
869f9aef477SLang Hames     jitlink::LinkGraph &G, JITDylib &JD) {
870afeb1e4aSLang Hames 
871f9aef477SLang Hames   // Add an action to register the eh-frame.
872afeb1e4aSLang Hames   if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) {
873afeb1e4aSLang Hames     jitlink::SectionRange R(*EHFrameSection);
874afeb1e4aSLang Hames     if (!R.empty())
875089acf25SLang Hames       G.allocActions().push_back(
876089acf25SLang Hames           {cantFail(
877089acf25SLang Hames                WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
878089acf25SLang Hames                    MP.orc_rt_macho_register_ehframe_section, R.getRange())),
879089acf25SLang Hames            cantFail(
880089acf25SLang Hames                WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
881089acf25SLang Hames                    MP.orc_rt_macho_deregister_ehframe_section, R.getRange()))});
882afeb1e4aSLang Hames   }
883afeb1e4aSLang Hames 
884afeb1e4aSLang Hames   // Get a pointer to the thread data section if there is one. It will be used
885afeb1e4aSLang Hames   // below.
886afeb1e4aSLang Hames   jitlink::Section *ThreadDataSection =
887afeb1e4aSLang Hames       G.findSectionByName(ThreadDataSectionName);
888afeb1e4aSLang Hames 
889afeb1e4aSLang Hames   // Handle thread BSS section if there is one.
890afeb1e4aSLang Hames   if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
891afeb1e4aSLang Hames     // If there's already a thread data section in this graph then merge the
892afeb1e4aSLang Hames     // thread BSS section content into it, otherwise just treat the thread
893afeb1e4aSLang Hames     // BSS section as the thread data section.
894afeb1e4aSLang Hames     if (ThreadDataSection)
895afeb1e4aSLang Hames       G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
896afeb1e4aSLang Hames     else
897afeb1e4aSLang Hames       ThreadDataSection = ThreadBSSSection;
898afeb1e4aSLang Hames   }
899afeb1e4aSLang Hames 
900f9aef477SLang Hames   SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs;
901f9aef477SLang Hames 
902afeb1e4aSLang Hames   // Having merged thread BSS (if present) and thread data (if present),
903afeb1e4aSLang Hames   // record the resulting section range.
904afeb1e4aSLang Hames   if (ThreadDataSection) {
905afeb1e4aSLang Hames     jitlink::SectionRange R(*ThreadDataSection);
906ff846fcbSLang Hames     if (!R.empty()) {
907ff846fcbSLang Hames       if (MP.State != MachOPlatform::Initialized)
908ff846fcbSLang Hames         return make_error<StringError>("__thread_data section encountered, but "
909ff846fcbSLang Hames                                        "MachOPlatform has not finished booting",
910ff846fcbSLang Hames                                        inconvertibleErrorCode());
911ff846fcbSLang Hames 
912f9aef477SLang Hames       MachOPlatformSecs.push_back({ThreadDataSectionName, R.getRange()});
913f9aef477SLang Hames     }
914f9aef477SLang Hames   }
915f9aef477SLang Hames 
916f9aef477SLang Hames   // If any platform sections were found then add an allocation action to call
917f9aef477SLang Hames   // the registration function.
918f9aef477SLang Hames   StringRef PlatformSections[] = {
919f9aef477SLang Hames       ModInitFuncSectionName,   ObjCClassListSectionName,
920f9aef477SLang Hames       ObjCImageInfoSectionName, ObjCSelRefsSectionName,
921f9aef477SLang Hames       Swift5ProtoSectionName,   Swift5ProtosSectionName,
922f9aef477SLang Hames       Swift5TypesSectionName,
923f9aef477SLang Hames   };
924f9aef477SLang Hames 
925f9aef477SLang Hames   for (auto &SecName : PlatformSections) {
926f9aef477SLang Hames     auto *Sec = G.findSectionByName(SecName);
927f9aef477SLang Hames     if (!Sec)
928f9aef477SLang Hames       continue;
929f9aef477SLang Hames     jitlink::SectionRange R(*Sec);
930f9aef477SLang Hames     if (R.empty())
931f9aef477SLang Hames       continue;
932f9aef477SLang Hames 
933f9aef477SLang Hames     MachOPlatformSecs.push_back({SecName, R.getRange()});
934f9aef477SLang Hames   }
935f9aef477SLang Hames 
936f9aef477SLang Hames   if (!MachOPlatformSecs.empty()) {
937f9aef477SLang Hames     Optional<ExecutorAddr> HeaderAddr;
938f9aef477SLang Hames     {
939f9aef477SLang Hames       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
940f9aef477SLang Hames       auto I = MP.JITDylibToHeaderAddr.find(&JD);
941f9aef477SLang Hames       if (I != MP.JITDylibToHeaderAddr.end())
942f9aef477SLang Hames         HeaderAddr = I->second;
943f9aef477SLang Hames     }
944f9aef477SLang Hames 
945f9aef477SLang Hames     if (!HeaderAddr)
946f9aef477SLang Hames       return make_error<StringError>("Missing header for " + JD.getName(),
947f9aef477SLang Hames                                      inconvertibleErrorCode());
948f9aef477SLang Hames 
949f9aef477SLang Hames     // Dump the scraped inits.
950f9aef477SLang Hames     LLVM_DEBUG({
951f9aef477SLang Hames       dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
952f9aef477SLang Hames       for (auto &KV : MachOPlatformSecs)
953f9aef477SLang Hames         dbgs() << "  " << KV.first << ": " << KV.second << "\n";
954f9aef477SLang Hames     });
955f9aef477SLang Hames 
956f9aef477SLang Hames     using SPSRegisterObjectPlatformSectionsArgs =
957f9aef477SLang Hames         SPSArgList<SPSExecutorAddr,
958f9aef477SLang Hames                    SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
959ff846fcbSLang Hames     G.allocActions().push_back(
960089acf25SLang Hames         {cantFail(
961f9aef477SLang Hames              WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
962f9aef477SLang Hames                  MP.orc_rt_macho_register_object_platform_sections, *HeaderAddr,
963f9aef477SLang Hames                  MachOPlatformSecs)),
964089acf25SLang Hames          cantFail(
965f9aef477SLang Hames              WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
966f9aef477SLang Hames                  MP.orc_rt_macho_deregister_object_platform_sections,
967f9aef477SLang Hames                  *HeaderAddr, MachOPlatformSecs))});
968afeb1e4aSLang Hames   }
969f9aef477SLang Hames 
970afeb1e4aSLang Hames   return Error::success();
971afeb1e4aSLang Hames }
972afeb1e4aSLang Hames 
registerEHSectionsPhase1(jitlink::LinkGraph & G)973ff846fcbSLang Hames Error MachOPlatform::MachOPlatformPlugin::registerEHSectionsPhase1(
974ff846fcbSLang Hames     jitlink::LinkGraph &G) {
975ff846fcbSLang Hames 
976ff846fcbSLang Hames   // If there's no eh-frame there's nothing to do.
977ff846fcbSLang Hames   auto *EHFrameSection = G.findSectionByName(EHFrameSectionName);
978ff846fcbSLang Hames   if (!EHFrameSection)
979ff846fcbSLang Hames     return Error::success();
980ff846fcbSLang Hames 
981ff846fcbSLang Hames   // If the eh-frame section is empty there's nothing to do.
982ff846fcbSLang Hames   jitlink::SectionRange R(*EHFrameSection);
983ff846fcbSLang Hames   if (R.empty())
984ff846fcbSLang Hames     return Error::success();
985ff846fcbSLang Hames 
986ff846fcbSLang Hames   // Since we're linking the object containing the registration code now the
987ff846fcbSLang Hames   // addresses won't be ready in the platform. We'll have to find them in this
988ff846fcbSLang Hames   // graph instead.
989ff846fcbSLang Hames   ExecutorAddr orc_rt_macho_register_ehframe_section;
990ff846fcbSLang Hames   ExecutorAddr orc_rt_macho_deregister_ehframe_section;
991ff846fcbSLang Hames   for (auto *Sym : G.defined_symbols()) {
992ff846fcbSLang Hames     if (!Sym->hasName())
993ff846fcbSLang Hames       continue;
994ff846fcbSLang Hames     if (Sym->getName() == "___orc_rt_macho_register_ehframe_section")
995ff846fcbSLang Hames       orc_rt_macho_register_ehframe_section = ExecutorAddr(Sym->getAddress());
996ff846fcbSLang Hames     else if (Sym->getName() == "___orc_rt_macho_deregister_ehframe_section")
997ff846fcbSLang Hames       orc_rt_macho_deregister_ehframe_section = ExecutorAddr(Sym->getAddress());
998ff846fcbSLang Hames 
999ff846fcbSLang Hames     if (orc_rt_macho_register_ehframe_section &&
1000ff846fcbSLang Hames         orc_rt_macho_deregister_ehframe_section)
1001ff846fcbSLang Hames       break;
1002afeb1e4aSLang Hames   }
1003afeb1e4aSLang Hames 
1004ff846fcbSLang Hames   // If we failed to find the required functions then bail out.
1005ff846fcbSLang Hames   if (!orc_rt_macho_register_ehframe_section ||
1006ff846fcbSLang Hames       !orc_rt_macho_deregister_ehframe_section)
1007ff846fcbSLang Hames     return make_error<StringError>("Could not find eh-frame registration "
1008ff846fcbSLang Hames                                    "functions during platform bootstrap",
1009ff846fcbSLang Hames                                    inconvertibleErrorCode());
1010ff846fcbSLang Hames 
1011ff846fcbSLang Hames   // Otherwise, add allocation actions to the graph to register eh-frames for
1012ff846fcbSLang Hames   // this object.
1013ff846fcbSLang Hames   G.allocActions().push_back(
1014089acf25SLang Hames       {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
1015089acf25SLang Hames            orc_rt_macho_register_ehframe_section, R.getRange())),
1016089acf25SLang Hames        cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
1017089acf25SLang Hames            orc_rt_macho_deregister_ehframe_section, R.getRange()))});
1018ff846fcbSLang Hames 
1019afeb1e4aSLang Hames   return Error::success();
1020afeb1e4aSLang Hames }
1021afeb1e4aSLang Hames 
102285fb9976SLang Hames } // End namespace orc.
102385fb9976SLang Hames } // End namespace llvm.
1024