LLVM: lib/ExecutionEngine/Orc/MachOPlatform.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
10
20#include
21
22#define DEBUG_TYPE "orc"
23
24using namespace llvm;
27
28namespace llvm {
29namespace orc {
31
35
36class SPSMachOExecutorSymbolFlags;
37
38template <>
41public:
43 return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders);
44 }
45
48 return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed,
50 }
51
54 return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed,
56 }
57};
58
59template <>
62private:
63 using UT = std::underlying_type_tMachOPlatform::MachOExecutorSymbolFlags;
64
65public:
67 return sizeof(UT);
68 }
69
74
77 UT Tmp;
79 return false;
81 return true;
82 }
83};
84
85}
86}
87}
88
89namespace {
90
91using SPSRegisterSymbolsArgs =
94 SPSMachOExecutorSymbolFlags>>>;
95
96std::unique_ptrjitlink::LinkGraph createPlatformGraph(MachOPlatform &MOP,
97 std::string Name) {
99 return std::make_uniquejitlink::LinkGraph(
100 std::move(Name), ES.getSymbolStringPool(), ES.getTargetTriple(),
102}
103
104
105class MachOPlatformCompleteBootstrapMaterializationUnit
107public:
108 using SymbolTableVector =
109 SmallVector<std::tuple<ExecutorAddr, ExecutorAddr,
111
112 MachOPlatformCompleteBootstrapMaterializationUnit(
113 MachOPlatform &MOP, StringRef PlatformJDName,
114 SymbolStringPtr CompleteBootstrapSymbol, SymbolTableVector SymTab,
116 ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown,
117 ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib,
118 ExecutorAddr RegisterObjectSymbolTable,
119 ExecutorAddr DeregisterObjectSymbolTable)
120 : MaterializationUnit(
122 MOP(MOP), PlatformJDName(PlatformJDName),
123 CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),
124 SymTab(std::move(SymTab)), DeferredAAs(std::move(DeferredAAs)),
125 MachOHeaderAddr(MachOHeaderAddr), PlatformBootstrap(PlatformBootstrap),
126 PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),
127 DeregisterJITDylib(DeregisterJITDylib),
128 RegisterObjectSymbolTable(RegisterObjectSymbolTable),
129 DeregisterObjectSymbolTable(DeregisterObjectSymbolTable) {}
130
131 StringRef getName() const override {
132 return "MachOPlatformCompleteBootstrap";
133 }
134
135 void materialize(std::unique_ptr R) override {
136 using namespace jitlink;
137 auto G = createPlatformGraph(MOP, "");
138 auto &PlaceholderSection =
139 G->createSection("__orc_rt_cplt_bs", MemProt::Read);
140 auto &PlaceholderBlock =
141 G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0);
142 G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1,
143 Linkage::Strong, Scope::Hidden, false, true);
144
145
146 G->allocActions().reserve(DeferredAAs.size() + 3);
147
148
149 G->allocActions().push_back(
153
154
155 G->allocActions().push_back(
157 SPSArgList<SPSString, SPSExecutorAddr>>(
158 RegisterJITDylib, PlatformJDName, MachOHeaderAddr)),
160 DeregisterJITDylib, MachOHeaderAddr))});
161
162
163 G->allocActions().push_back(
165 RegisterObjectSymbolTable, MachOHeaderAddr, SymTab)),
167 DeregisterObjectSymbolTable, MachOHeaderAddr, SymTab))});
168
169
170 std::move(DeferredAAs.begin(), DeferredAAs.end(),
171 std::back_inserter(G->allocActions()));
172
173 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
174 }
175
176 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
177
178private:
179 MachOPlatform &MOP;
180 StringRef PlatformJDName;
181 SymbolStringPtr CompleteBootstrapSymbol;
182 SymbolTableVector SymTab;
184 ExecutorAddr MachOHeaderAddr;
185 ExecutorAddr PlatformBootstrap;
186 ExecutorAddr PlatformShutdown;
187 ExecutorAddr RegisterJITDylib;
188 ExecutorAddr DeregisterJITDylib;
189 ExecutorAddr RegisterObjectSymbolTable;
190 ExecutorAddr DeregisterObjectSymbolTable;
191};
192
193static StringRef ObjCRuntimeObjectSectionsData[] = {
200
201static StringRef ObjCRuntimeObjectSectionsText[] = {
207
208static StringRef ObjCRuntimeObjectSectionName =
209 "__llvm_jitlink_ObjCRuntimeRegistrationObject";
210
211static StringRef ObjCImageInfoSymbolName =
212 "__llvm_jitlink_macho_objc_imageinfo";
213
214struct ObjCImageInfoFlags {
215 uint16_t SwiftABIVersion;
216 uint16_t SwiftVersion;
217 bool HasCategoryClassProperties;
218 bool HasSignedObjCClassROs;
219
220 static constexpr uint32_t SIGNED_CLASS_RO = (1 << 4);
221 static constexpr uint32_t HAS_CATEGORY_CLASS_PROPERTIES = (1 << 6);
222
223 explicit ObjCImageInfoFlags(uint32_t RawFlags) {
224 HasSignedObjCClassROs = RawFlags & SIGNED_CLASS_RO;
225 HasCategoryClassProperties = RawFlags & HAS_CATEGORY_CLASS_PROPERTIES;
226 SwiftABIVersion = (RawFlags >> 8) & 0xFF;
227 SwiftVersion = (RawFlags >> 16) & 0xFFFF;
228 }
229
230 uint32_t rawFlags() const {
232 if (HasCategoryClassProperties)
233 Result |= HAS_CATEGORY_CLASS_PROPERTIES;
234 if (HasSignedObjCClassROs)
235 Result |= SIGNED_CLASS_RO;
236 Result |= (SwiftABIVersion << 8);
237 Result |= (SwiftVersion << 16);
239 }
240};
241}
242
243namespace llvm {
244namespace orc {
245
246std::optionalMachOPlatform::HeaderOptions::BuildVersionOpts
250
252 switch (TT.getOS()) {
254 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR
255 : MachO::PLATFORM_IOS;
256 break;
258 Platform = MachO::PLATFORM_MACOS;
259 break;
261 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR
262 : MachO::PLATFORM_TVOS;
263 break;
265 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR
266 : MachO::PLATFORM_WATCHOS;
267 break;
269 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR
270 : MachO::PLATFORM_XROS;
271 break;
272 default:
273 return std::nullopt;
274 }
275
277}
278
281 std::unique_ptr OrcRuntime,
284 std::optional RuntimeAliases) {
285
286 auto &ES = ObjLinkingLayer.getExecutionSession();
287
288
289 if (!supportedTarget(ES.getTargetTriple()))
291 ES.getTargetTriple().str(),
293
294 auto &EPC = ES.getExecutorProcessControl();
295
296
297 if (!RuntimeAliases)
299
300
301 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
302 return std::move(Err);
303
304
305 if (auto Err = PlatformJD.define(
307 {EPC.getJITDispatchInfo().JITDispatchFunction,
309 {ES.intern("___orc_rt_jit_dispatch_ctx"),
310 {EPC.getJITDispatchInfo().JITDispatchContext,
312 return std::move(Err);
313
314
316 auto P = std::unique_ptr(new MachOPlatform(
317 ObjLinkingLayer, PlatformJD, std::move(OrcRuntime),
318 std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU), Err));
319 if (Err)
320 return std::move(Err);
321 return std::move(P);
322}
323
326 const char *OrcRuntimePath, HeaderOptions PlatformJDOpts,
328 std::optional RuntimeAliases) {
329
330
331 auto OrcRuntimeArchiveGenerator =
333 if (!OrcRuntimeArchiveGenerator)
334 return OrcRuntimeArchiveGenerator.takeError();
335
336 return Create(ObjLinkingLayer, PlatformJD,
337 std::move(*OrcRuntimeArchiveGenerator),
338 std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU),
339 std::move(RuntimeAliases));
340}
341
345
347 if (auto Err = JD.define(BuildMachOHeaderMU(*this, std::move(Opts))))
348 return Err;
349
350 return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();
351}
352
354 std::lock_guardstd::mutex Lock(PlatformMutex);
355 auto I = JITDylibToHeaderAddr.find(&JD);
356 if (I != JITDylibToHeaderAddr.end()) {
357 assert(HeaderAddrToJITDylib.count(I->second) &&
358 "HeaderAddrToJITDylib missing entry");
359 HeaderAddrToJITDylib.erase(I->second);
360 JITDylibToHeaderAddr.erase(I);
361 }
362 JITDylibToPThreadKey.erase(&JD);
364}
365
370 if (!InitSym)
372
373 RegisteredInitSymbols[&JD].add(InitSym,
376 dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
378 });
380}
381
385
387 ArrayRef<std::pair<const char *, const char *>> AL) {
388 for (auto &KV : AL) {
389 auto AliasName = ES.intern(KV.first);
390 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
391 Aliases[std::move(AliasName)] = {ES.intern(KV.second),
393 }
394}
395
403
406 static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
407 {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}};
408
410}
411
414 static const std::pair<const char *, const char *>
415 StandardRuntimeUtilityAliases[] = {
416 {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
417 {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
418 {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
419 {"___orc_rt_jit_dlupdate", "___orc_rt_macho_jit_dlupdate"},
420 {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
421 {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
422 {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
423
425 StandardRuntimeUtilityAliases);
426}
427
430 static const std::pair<const char *, const char *>
431 StandardLazyCompilationAliases[] = {
432 {"__orc_rt_reenter", "__orc_rt_sysv_reenter"},
433 {"__orc_rt_resolve_tag", "___orc_rt_resolve_tag"}};
434
436 StandardLazyCompilationAliases);
437}
438
439bool MachOPlatform::supportedTarget(const Triple &TT) {
440 switch (TT.getArch()) {
443 return true;
444 default:
445 return false;
446 }
447}
448
449jitlink::Edge::Kind MachOPlatform::getPointerEdgeKind(jitlink::LinkGraph &G) {
450 switch (G.getTargetTriple().getArch()) {
455 default:
457 }
458}
459
461MachOPlatform::flagsForSymbol(jitlink::Symbol &Sym) {
465
468
470}
471
472MachOPlatform::MachOPlatform(
473 ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
474 std::unique_ptr OrcRuntimeGenerator,
478 ObjLinkingLayer(ObjLinkingLayer),
479 BuildMachOHeaderMU(std::move(BuildMachOHeaderMU)) {
480 ErrorAsOutParameter _(Err);
481 ObjLinkingLayer.addPlugin(std::make_unique(*this));
482 PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
483
484 {
485
486 std::optional ForceEHFrames;
487 if ((Err = ES.getBootstrapMapValue<bool, bool>("darwin-use-ehframes-only",
488 ForceEHFrames)))
489 return;
490 this->ForceEHFrames = ForceEHFrames.value_or(false);
491 }
492
493 BootstrapInfo BI;
494 Bootstrap = &BI;
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551 if ((Err = PlatformJD.define(
552 this->BuildMachOHeaderMU(*this, std::move(PlatformJDOpts)))))
553 return;
554 if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))
555 return;
556
557
558
560 SymbolLookupSet(
561 {PlatformBootstrap.Name, PlatformShutdown.Name,
562 RegisterJITDylib.Name, DeregisterJITDylib.Name,
563 RegisterObjectSymbolTable.Name,
564 DeregisterObjectSymbolTable.Name,
565 RegisterObjectPlatformSections.Name,
566 DeregisterObjectPlatformSections.Name,
567 CreatePThreadKey.Name}))
568 .takeError()))
569 return;
570
571
572 {
573 std::unique_lockstd::mutex Lock(PlatformMutex);
574 BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; });
575 Bootstrap = nullptr;
576 }
577
578
579 auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap");
580 if ((Err = PlatformJD.define(
581 std::make_unique(
582 *this, PlatformJD.getName(), BootstrapCompleteSymbol,
583 std::move(BI.SymTab), std::move(BI.DeferredAAs),
584 BI.MachOHeaderAddr, PlatformBootstrap.Addr,
585 PlatformShutdown.Addr, RegisterJITDylib.Addr,
586 DeregisterJITDylib.Addr, RegisterObjectSymbolTable.Addr,
587 DeregisterObjectSymbolTable.Addr))))
588 return;
591 std::move(BootstrapCompleteSymbol))
592 .takeError()))
593 return;
594
595
596
597
598
599
600
601
602 if ((Err = associateRuntimeSupportFunctions()))
603 return;
604}
605
606Error MachOPlatform::associateRuntimeSupportFunctions() {
608
609 using PushInitializersSPSSig =
610 SPSExpected(SPSExecutorAddr);
611 WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] =
612 ES.wrapAsyncWithSPS(
613 this, &MachOPlatform::rt_pushInitializers);
614
615 using PushSymbolsSPSSig =
616 SPSError(SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>);
617 WFs[ES.intern("___orc_rt_macho_push_symbols_tag")] =
618 ES.wrapAsyncWithSPS(this,
619 &MachOPlatform::rt_pushSymbols);
620
621 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
622}
623
624void MachOPlatform::pushInitializersLoop(
625 PushInitializersSendResultFn SendResult, JITDylibSP JD) {
626 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
627 DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap;
629
630 ES.runSessionLocked([&]() {
631 while (!Worklist.empty()) {
632
633
634 auto DepJD = Worklist.back();
635 Worklist.pop_back();
636
637
639 if (!Inserted)
640 continue;
641
642
643 auto &DM = It->second;
645 for (auto &KV : O) {
646 if (KV.first == DepJD)
647 continue;
648 DM.push_back(KV.first);
649 Worklist.push_back(KV.first);
650 }
651 });
652
653
654 auto RISItr = RegisteredInitSymbols.find(DepJD);
655 if (RISItr != RegisteredInitSymbols.end()) {
656 NewInitSymbols[DepJD] = std::move(RISItr->second);
657 RegisteredInitSymbols.erase(RISItr);
658 }
659 }
660 });
661
662
663
664 if (NewInitSymbols.empty()) {
665
666
667
668
669
670 DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
672 {
673 std::lock_guardstd::mutex Lock(PlatformMutex);
674 for (auto &KV : JDDepMap) {
675 auto I = JITDylibToHeaderAddr.find(KV.first);
676 if (I != JITDylibToHeaderAddr.end())
677 HeaderAddrs[KV.first] = I->second;
678 }
679 }
680
681
683 DIM.reserve(JDDepMap.size());
684 for (auto &KV : JDDepMap) {
685 auto HI = HeaderAddrs.find(KV.first);
686
687 if (HI == HeaderAddrs.end())
688 continue;
691 for (auto &Dep : KV.second) {
692 auto HJ = HeaderAddrs.find(Dep);
693 if (HJ != HeaderAddrs.end())
694 DepInfo.DepHeaders.push_back(HJ->second);
695 }
696 DIM.push_back(std::make_pair(H, std::move(DepInfo)));
697 }
698 SendResult(DIM);
699 return;
700 }
701
702
704 [this, SendResult = std::move(SendResult), JD](Error Err) mutable {
705 if (Err)
706 SendResult(std::move(Err));
707 else
708 pushInitializersLoop(std::move(SendResult), JD);
709 },
710 ES, std::move(NewInitSymbols));
711}
712
713void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
716 {
717 std::lock_guardstd::mutex Lock(PlatformMutex);
718 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
719 if (I != HeaderAddrToJITDylib.end())
720 JD = I->second;
721 }
722
724 dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
725 if (JD)
726 dbgs() << "pushing initializers for " << JD->getName() << "\n";
727 else
728 dbgs() << "No JITDylib for header address.\n";
729 });
730
731 if (!JD) {
733 formatv("{0:x}", JDHeaderAddr),
735 return;
736 }
737
738 pushInitializersLoop(std::move(SendResult), JD);
739}
740
741void MachOPlatform::rt_pushSymbols(
742 PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle,
743 const std::vector<std::pair<StringRef, bool>> &SymbolNames) {
744
745 JITDylib *JD = nullptr;
746
747 {
748 std::lock_guardstd::mutex Lock(PlatformMutex);
749 auto I = HeaderAddrToJITDylib.find(Handle);
750 if (I != HeaderAddrToJITDylib.end())
751 JD = I->second;
752 }
754 dbgs() << "MachOPlatform::rt_pushSymbols(";
755 if (JD)
756 dbgs() << "\"" << JD->getName() << "\", [ ";
757 else
758 dbgs() << "<invalid handle " << Handle << ">, [ ";
759 for (auto &Name : SymbolNames)
760 dbgs() << "\"" << Name.first << "\" ";
761 dbgs() << "])\n";
762 });
763
764 if (!JD) {
766 formatv("{0:x}", Handle),
768 return;
769 }
770
771 SymbolLookupSet LS;
772 for (auto &[Name, Required] : SymbolNames)
776
777 ES.lookup(
780 [SendResult = std::move(SendResult)](Expected Result) mutable {
781 SendResult(Result.takeError());
782 },
784}
785
786Expected<uint64_t> MachOPlatform::createPThreadKey() {
787 if (!CreatePThreadKey.Addr)
789 "Attempting to create pthread key in target, but runtime support has "
790 "not been loaded yet",
792
793 Expected<uint64_t> Result(0);
794 if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
795 CreatePThreadKey.Addr, Result))
796 return std::move(Err);
798}
799
800void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
802 jitlink::PassConfiguration &Config) {
803
804 using namespace jitlink;
805
806 bool InBootstrapPhase = false;
807
808 ExecutorAddr HeaderAddr;
809 {
810 std::lock_guardstd::mutex Lock(MP.PlatformMutex);
812 if (MP.Bootstrap) {
813 InBootstrapPhase = true;
814 ++MP.Bootstrap->ActiveGraphs;
815 }
816 }
817
818
820 if (I != MP.JITDylibToHeaderAddr.end())
821 HeaderAddr = I->second;
822 }
823
824
825
826 if (MP.ForceEHFrames)
829
830
831
832
833 if (HeaderAddr)
834 LG.addAbsoluteSymbol("__jitlink$libunwind_dso_base", HeaderAddr, 0,
835 Linkage::Strong, Scope::Local, true);
836
837
840 return bootstrapPipelineRecordRuntimeFunctions(G);
841 });
842
843
845
846
847
848
849 if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) {
851 return associateJITDylibHeaderSymbol(G, MR);
852 });
853 return;
854 }
855
856
857
858
859 Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) {
860 if (auto Err = preserveImportantSections(G, MR))
861 return Err;
862 return processObjCImageInfo(G, MR);
863 });
865 [this](LinkGraph &G) { return createObjCRuntimeObject(G); });
867 [this, &MR](LinkGraph &G) { return populateObjCRuntimeObject(G, MR); });
868 }
869
870
871
875 return fixTLVSectionsAndEdges(G, JD);
876 });
877
878
879
880
881 auto JITSymTabInfo = std::make_shared();
882 Config.PostPrunePasses.push_back([this, JITSymTabInfo](LinkGraph &G) {
883 return prepareSymbolTableRegistration(G, *JITSymTabInfo);
884 });
885 Config.PostFixupPasses.push_back([this, &MR, JITSymTabInfo,
886 InBootstrapPhase](LinkGraph &G) {
887 return addSymbolTableRegistration(G, MR, *JITSymTabInfo, InBootstrapPhase);
888 });
889
890
891
893 HeaderAddr,
894 InBootstrapPhase](LinkGraph &G) {
895 return registerObjectPlatformSections(G, JD, HeaderAddr, InBootstrapPhase);
896 });
897
898
899
900 if (InBootstrapPhase)
902 [this](LinkGraph &G) { return bootstrapPipelineEnd(G); });
903}
904
905Error MachOPlatform::MachOPlatformPlugin::
906 bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) {
907
908 std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {
909 {*MP.MachOHeaderStartSymbol, &MP.Bootstrap->MachOHeaderAddr},
910 {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},
911 {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},
912 {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},
913 {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},
914 {*MP.RegisterObjectSymbolTable.Name, &MP.RegisterObjectSymbolTable.Addr},
915 {*MP.DeregisterObjectSymbolTable.Name,
916 &MP.DeregisterObjectSymbolTable.Addr},
917 {*MP.RegisterObjectPlatformSections.Name,
918 &MP.RegisterObjectPlatformSections.Addr},
919 {*MP.DeregisterObjectPlatformSections.Name,
920 &MP.DeregisterObjectPlatformSections.Addr},
921 {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr},
922 {*MP.RegisterObjCRuntimeObject.Name, &MP.RegisterObjCRuntimeObject.Addr},
923 {*MP.DeregisterObjCRuntimeObject.Name,
924 &MP.DeregisterObjCRuntimeObject.Addr}};
925
926 bool RegisterMachOHeader = false;
927
928 for (auto *Sym : G.defined_symbols()) {
929 for (auto &RTSym : RuntimeSymbols) {
930 if (Sym->hasName() && *Sym->getName() == RTSym.first) {
931 if (*RTSym.second)
933 "Duplicate " + RTSym.first +
934 " detected during MachOPlatform bootstrap",
936
937 if (Sym->getName() == MP.MachOHeaderStartSymbol)
938 RegisterMachOHeader = true;
939
941 }
942 }
943 }
944
945 if (RegisterMachOHeader) {
946
947
948 std::lock_guardstd::mutex Lock(MP.PlatformMutex);
949 MP.JITDylibToHeaderAddr[&MP.PlatformJD] = MP.Bootstrap->MachOHeaderAddr;
950 MP.HeaderAddrToJITDylib[MP.Bootstrap->MachOHeaderAddr] = &MP.PlatformJD;
951 }
952
954}
955
956Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd(
957 jitlink::LinkGraph &G) {
958 std::lock_guardstd::mutex Lock(MP.PlatformMutex);
959
960 --MP.Bootstrap->ActiveGraphs;
961
962
963 if (MP.Bootstrap->ActiveGraphs == 0)
964 MP.Bootstrap->CV.notify_all();
966}
967
968Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
969 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
970 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
971 return Sym->getName() == MP.MachOHeaderStartSymbol;
972 });
973 assert(I != G.defined_symbols().end() && "Missing MachO header start symbol");
974
976 std::lock_guardstd::mutex Lock(MP.PlatformMutex);
977 auto HeaderAddr = (*I)->getAddress();
978 MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
979 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
980
981
982 G.allocActions().push_back(
985 MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)),
987 MP.DeregisterJITDylib.Addr, HeaderAddr))});
989}
990
991Error MachOPlatform::MachOPlatformPlugin::preserveImportantSections(
992 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
993
994
995
996
997 if (auto *ObjCImageInfoSec =
999 if (ObjCImageInfoSec->blocks_size() != 1)
1001 "In " + G.getName() +
1002 "__DATA,__objc_imageinfo contains multiple blocks",
1004 G.addAnonymousSymbol(**ObjCImageInfoSec->blocks().begin(), 0, 0, false,
1005 true);
1006
1007 for (auto *B : ObjCImageInfoSec->blocks())
1008 if (->edges_empty())
1011 " contains references to symbols",
1013 }
1014
1015
1016
1017
1019
1020 jitlink::Symbol *InitSym = nullptr;
1022
1023
1025 continue;
1026
1027
1028 auto *InitSection = G.findSectionByName(InitSectionName);
1029 if (!InitSection || InitSection->empty())
1030 continue;
1031
1032
1033
1034 if (!InitSym) {
1035 auto &B = **InitSection->blocks().begin();
1036 InitSym = &G.addDefinedSymbol(
1039 }
1040
1041
1042 for (auto *B : InitSection->blocks()) {
1044 continue;
1045
1046 auto &S = G.addAnonymousSymbol(*B, 0, B->getSize(), false, true);
1047 InitSym->getBlock().addEdge(jitlink::Edge::KeepAlive, 0, S, 0);
1048 }
1049 }
1050 }
1051
1053}
1054
1055Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
1056 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
1057
1058
1059
1060
1061
1062
1063
1065 if (!ObjCImageInfo)
1067
1068 auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
1069
1070
1071 if (ObjCImageInfoBlocks.empty())
1073 " section in " + G.getName(),
1075
1076
1077 if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
1080 " section in " + G.getName(),
1082
1083
1084
1085 for (auto &Sec : G.sections()) {
1086 if (&Sec != ObjCImageInfo)
1087 for (auto *B : Sec.blocks())
1088 for (auto &E : B->edges())
1089 if (E.getTarget().isDefined() &&
1090 &E.getTarget().getSection() == ObjCImageInfo)
1092 " is referenced within file " +
1093 G.getName(),
1095 }
1096
1097 auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
1098 auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
1102
1103
1104 std::lock_guardstd::mutex Lock(PluginMutex);
1105
1106 auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());
1107 if (ObjCImageInfoItr != ObjCImageInfos.end()) {
1108
1109
1110 if (ObjCImageInfoItr->second.Version != Version)
1112 "ObjC version in " + G.getName() +
1113 " does not match first registered version",
1115 if (ObjCImageInfoItr->second.Flags != Flags)
1116 if (Error E = mergeImageInfoFlags(G, MR, ObjCImageInfoItr->second, Flags))
1117 return E;
1118
1119
1120 for (auto *S : ObjCImageInfo->symbols())
1121 G.removeDefinedSymbol(*S);
1122 G.removeBlock(ObjCImageInfoBlock);
1123 } else {
1125 dbgs() << "MachOPlatform: Registered __objc_imageinfo for "
1127 << "; flags = " << formatv("{0:x4}", Flags) << "\n";
1128 });
1129
1130
1131 G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName,
1135 {{MR.getExecutionSession().intern(ObjCImageInfoSymbolName),
1136 JITSymbolFlags()}}))
1137 return Err;
1139 }
1140
1142}
1143
1144Error MachOPlatform::MachOPlatformPlugin::mergeImageInfoFlags(
1146 ObjCImageInfo &Info, uint32_t NewFlags) {
1147 if (Info.Flags == NewFlags)
1149
1150 ObjCImageInfoFlags Old(Info.Flags);
1151 ObjCImageInfoFlags New(NewFlags);
1152
1153
1154 if (Old.SwiftABIVersion && New.SwiftABIVersion &&
1155 Old.SwiftABIVersion != New.SwiftABIVersion)
1157 " does not match first registered flags",
1159
1160
1161
1162
1163 if (Info.Finalized && Old.HasCategoryClassProperties &&
1164 .HasCategoryClassProperties)
1166 G.getName() +
1167 " does not match first registered flags",
1169 if (Info.Finalized && Old.HasSignedObjCClassROs && .HasSignedObjCClassROs)
1171 G.getName() +
1172 " does not match first registered flags",
1174
1175
1176
1177 if (Info.Finalized)
1179
1180
1181 if (Old.SwiftVersion && New.SwiftVersion)
1182 New.SwiftVersion = std::min(Old.SwiftVersion, New.SwiftVersion);
1183 else if (Old.SwiftVersion)
1184 New.SwiftVersion = Old.SwiftVersion;
1185
1186 if (.SwiftABIVersion)
1187 New.SwiftABIVersion = Old.SwiftABIVersion;
1188
1189 if (Old.HasCategoryClassProperties != New.HasCategoryClassProperties)
1190 New.HasCategoryClassProperties = false;
1191
1192 if (Old.HasSignedObjCClassROs != New.HasSignedObjCClassROs)
1193 New.HasSignedObjCClassROs = false;
1194
1196 dbgs() << "MachOPlatform: Merging __objc_imageinfo flags for "
1198 << formatv("{0:x4}", Old.rawFlags()) << ")"
1199 << " with " << G.getName() << " (" << formatv("{0:x4}", NewFlags)
1200 << ")"
1201 << " -> " << formatv("{0:x4}", New.rawFlags()) << "\n";
1202 });
1203
1204 Info.Flags = New.rawFlags();
1206}
1207
1208Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
1209 jitlink::LinkGraph &G, JITDylib &JD) {
1210 auto TLVBootStrapSymbolName = G.intern("__tlv_bootstrap");
1211
1212 for (auto *Sym : G.external_symbols())
1213 if (Sym->getName() == TLVBootStrapSymbolName) {
1214 auto TLSGetADDR =
1215 MP.getExecutionSession().intern("___orc_rt_macho_tlv_get_addr");
1216 Sym->setName(std::move(TLSGetADDR));
1217 break;
1218 }
1219
1220
1222 std::optional<uint64_t> Key;
1223 {
1224 std::lock_guardstd::mutex Lock(MP.PlatformMutex);
1225 auto I = MP.JITDylibToPThreadKey.find(&JD);
1226 if (I != MP.JITDylibToPThreadKey.end())
1228 }
1229
1230 if () {
1231 if (auto KeyOrErr = MP.createPThreadKey())
1232 Key = *KeyOrErr;
1233 else
1234 return KeyOrErr.takeError();
1235 }
1236
1237 uint64_t PlatformKeyBits =
1239
1240 for (auto *B : ThreadDataSec->blocks()) {
1241 if (B->getSize() != 3 * G.getPointerSize())
1243 formatv("{0:x}", B->getAddress()) +
1244 " has unexpected size",
1246
1247 auto NewBlockContent = G.allocateBuffer(B->getSize());
1248 llvm::copy(B->getContent(), NewBlockContent.data());
1249 memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits,
1250 G.getPointerSize());
1251 B->setContent(NewBlockContent);
1252 }
1253 }
1254
1255
1256 for (auto *B : G.blocks())
1257 for (auto &E : B->edges())
1258 if (E.getKind() ==
1260 E.setKind(jitlink::x86_64::
1261 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);
1262
1264}
1265
1266std::optionalMachOPlatform::MachOPlatformPlugin::UnwindSections
1267MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
1268 jitlink::LinkGraph &G) {
1269 using namespace jitlink;
1270
1271 UnwindSections US;
1272
1273
1274
1276 auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange,
1277 auto AddCodeBlocks) {
1278 if (Sec.blocks().empty())
1279 return;
1280 SecRange = (*Sec.blocks().begin())->getRange();
1281 for (auto *B : Sec.blocks()) {
1283 SecRange.Start = std::min(SecRange.Start, R.Start);
1284 SecRange.End = std::max(SecRange.End, R.End);
1285 AddCodeBlocks(*B);
1286 }
1287 };
1288
1290 ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection, [&](Block &B) {
1291 if (auto *Fn = jitlink::EHFrameCFIBlockInspector::FromEdgeScan(B)
1292 .getPCBeginEdge())
1293 if (Fn->getTarget().isDefined())
1294 CodeBlocks.push_back(&Fn->getTarget().getBlock());
1295 });
1296 }
1297
1299 ScanUnwindInfoSection(
1300 *CUInfoSec, US.CompactUnwindSection, [&](Block &B) {
1301 for (auto &E : B.edges()) {
1302 assert(E.getTarget().isDefined() &&
1303 "unwind-info record edge has external target");
1304 assert(E.getKind() == Edge::KeepAlive &&
1305 "unwind-info record has unexpected edge kind");
1306 CodeBlocks.push_back(&E.getTarget().getBlock());
1307 }
1308 });
1309 }
1310
1311
1312
1313 if (CodeBlocks.empty())
1314 return std::nullopt;
1315
1316
1317
1319 return LHS->getAddress() < RHS->getAddress();
1320 });
1321 for (auto *B : CodeBlocks) {
1322 if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress())
1323 US.CodeRanges.push_back(B->getRange());
1324 else
1325 US.CodeRanges.back().End = B->getRange().End;
1326 }
1327
1329 dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n"
1330 << " DWARF: ";
1331 if (US.DwarfSection.Start)
1332 dbgs() << US.DwarfSection << "\n";
1333 else
1334 dbgs() << "none\n";
1335 dbgs() << " Compact-unwind: ";
1336 if (US.CompactUnwindSection.Start)
1337 dbgs() << US.CompactUnwindSection << "\n";
1338 else
1339 dbgs() << "none\n"
1340 << "for code ranges:\n";
1341 for (auto &CR : US.CodeRanges)
1342 dbgs() << " " << CR << "\n";
1343 if (US.CodeRanges.size() >= G.sections_size())
1344 dbgs() << "WARNING: High number of discontiguous code ranges! "
1345 "Padding may be interfering with coalescing.\n";
1346 });
1347
1348 return US;
1349}
1350
1351Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
1353 bool InBootstrapPhase) {
1354
1355
1356
1357 jitlink::Section *ThreadDataSection =
1359
1360
1362
1363
1364
1365 if (ThreadDataSection)
1366 G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
1367 else
1368 ThreadDataSection = ThreadBSSSection;
1369 }
1370
1372
1373
1377 for (auto &SecName : DataSections) {
1378 if (auto *Sec = G.findSectionByName(SecName)) {
1379 jitlink::SectionRange R(*Sec);
1380 if (.empty())
1381 MachOPlatformSecs.push_back({SecName, R.getRange()});
1382 }
1383 }
1384
1385
1386
1387 if (ThreadDataSection) {
1388 jitlink::SectionRange R(*ThreadDataSection);
1389 if (.empty())
1391 }
1392
1393
1394
1396 ObjCRuntimeObjectSectionName};
1397
1398 for (auto &SecName : PlatformSections) {
1399 auto *Sec = G.findSectionByName(SecName);
1400 if (!Sec)
1401 continue;
1402 jitlink::SectionRange R(*Sec);
1403 if (R.empty())
1404 continue;
1405
1406 MachOPlatformSecs.push_back({SecName, R.getRange()});
1407 }
1408
1409 std::optional<std::tuple<SmallVector, ExecutorAddrRange,
1410 ExecutorAddrRange>>
1411 UnwindInfo;
1412 if (auto UI = findUnwindSectionInfo(G))
1413 UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection,
1414 UI->CompactUnwindSection);
1415
1416 if (!MachOPlatformSecs.empty() || UnwindInfo) {
1417
1419 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
1420 for (auto &KV : MachOPlatformSecs)
1421 dbgs() << " " << KV.first << ": " << KV.second << "\n";
1422 });
1423
1424 assert(HeaderAddr && "Null header registered for JD");
1425 using SPSRegisterObjectPlatformSectionsArgs = SPSArgList<
1426 SPSExecutorAddr,
1427 SPSOptional<SPSTuple<SPSSequence,
1429 SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
1430
1434 MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
1435 MachOPlatformSecs)),
1438 MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
1439 UnwindInfo, MachOPlatformSecs))};
1440
1442 G.allocActions().push_back(std::move(AllocActions));
1443 else {
1444 std::lock_guardstd::mutex Lock(MP.PlatformMutex);
1445 MP.Bootstrap->DeferredAAs.push_back(std::move(AllocActions));
1446 }
1447 }
1448
1450}
1451
1452Error MachOPlatform::MachOPlatformPlugin::createObjCRuntimeObject(
1453 jitlink::LinkGraph &G) {
1454
1455 bool NeedTextSegment = false;
1456 size_t NumRuntimeSections = 0;
1457
1458 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData)
1459 if (G.findSectionByName(ObjCRuntimeSectionName))
1460 ++NumRuntimeSections;
1461
1462 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {
1463 if (G.findSectionByName(ObjCRuntimeSectionName)) {
1464 ++NumRuntimeSections;
1465 NeedTextSegment = true;
1466 }
1467 }
1468
1469
1470 if (NumRuntimeSections == 0)
1472
1473
1474
1475 ++NumRuntimeSections;
1476
1477 size_t MachOSize = sizeof(MachO::mach_header_64) +
1478 (NeedTextSegment + 1) * sizeof(MachO::segment_command_64) +
1479 NumRuntimeSections * sizeof(MachO::section_64);
1480
1481 auto &Sec = G.createSection(ObjCRuntimeObjectSectionName,
1483 G.createMutableContentBlock(Sec, MachOSize, ExecutorAddr(), 16, 0, true);
1484
1486}
1487
1488Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(
1489 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
1490
1491 auto *ObjCRuntimeObjectSec =
1492 G.findSectionByName(ObjCRuntimeObjectSectionName);
1493
1494 if (!ObjCRuntimeObjectSec)
1496
1497 switch (G.getTargetTriple().getArch()) {
1500
1501 break;
1502 default:
1504 G.getTargetTriple().str(),
1506 }
1507
1508 auto &SecBlock = **ObjCRuntimeObjectSec->blocks().begin();
1509
1510 struct SecDesc {
1511 MachO::section_64 Sec;
1512 unique_function<void(size_t RecordOffset)> AddFixups;
1513 };
1514
1515 std::vector TextSections, DataSections;
1516 auto AddSection = [&](SecDesc &SD, jitlink::Section &GraphSec) {
1517 jitlink::SectionRange SR(GraphSec);
1518 StringRef FQName = GraphSec.getName();
1519 memset(&SD.Sec, 0, sizeof(MachO::section_64));
1520 memcpy(SD.Sec.sectname, FQName.drop_front(7).data(), FQName.size() - 7);
1521 memcpy(SD.Sec.segname, FQName.data(), 6);
1522 SD.Sec.addr = SR.getStart() - SecBlock.getAddress();
1523 SD.Sec.size = SR.getSize();
1525 };
1526
1527
1528 {
1529 DataSections.push_back({});
1530 auto &SD = DataSections.back();
1531 memset(&SD.Sec, 0, sizeof(SD.Sec));
1532 memcpy(SD.Sec.sectname, "__objc_imageinfo", 16);
1533 strcpy(SD.Sec.segname, "__DATA");
1534 SD.Sec.size = 8;
1535 jitlink::Symbol *ObjCImageInfoSym = nullptr;
1536 SD.AddFixups = [&, ObjCImageInfoSym](size_t RecordOffset) mutable {
1537 auto PointerEdge = getPointerEdgeKind(G);
1538
1539
1540 if (!ObjCImageInfoSym) {
1541 auto Name = G.intern(ObjCImageInfoSymbolName);
1542 ObjCImageInfoSym = G.findExternalSymbolByName(Name);
1543 if (!ObjCImageInfoSym)
1544 ObjCImageInfoSym = G.findAbsoluteSymbolByName(Name);
1545 if (!ObjCImageInfoSym) {
1546 ObjCImageInfoSym = G.findDefinedSymbolByName(Name);
1547 if (ObjCImageInfoSym) {
1548 std::optional<uint32_t> Flags;
1549 {
1550 std::lock_guardstd::mutex Lock(PluginMutex);
1552 if (It != ObjCImageInfos.end()) {
1553 It->second.Finalized = true;
1554 Flags = It->second.Flags;
1555 }
1556 }
1557
1558 if (Flags) {
1559
1560
1563 Content.size() == 8 &&
1564 "__objc_image_info size should have been verified already");
1566 }
1567 }
1568 }
1569 if (!ObjCImageInfoSym)
1570 ObjCImageInfoSym = &G.addExternalSymbol(std::move(Name), 8, false);
1571 }
1572
1573 SecBlock.addEdge(PointerEdge,
1574 RecordOffset + ((char *)&SD.Sec.addr - (char *)&SD.Sec),
1575 *ObjCImageInfoSym, -SecBlock.getAddress().getValue());
1576 };
1577 }
1578
1579 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) {
1580 if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) {
1581 DataSections.push_back({});
1582 AddSection(DataSections.back(), *GraphSec);
1583 }
1584 }
1585
1586 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {
1587 if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) {
1588 TextSections.push_back({});
1589 AddSection(TextSections.back(), *GraphSec);
1590 }
1591 }
1592
1593 assert(ObjCRuntimeObjectSec->blocks_size() == 1 &&
1594 "Unexpected number of blocks in runtime sections object");
1595
1596
1597
1598 MachO::mach_header_64 Hdr;
1600 switch (G.getTargetTriple().getArch()) {
1604 break;
1608 break;
1609 default:
1611 }
1612
1614 Hdr.ncmds = 1 + !TextSections.empty();
1616 Hdr.ncmds * sizeof(MachO::segment_command_64) +
1617 (TextSections.size() + DataSections.size()) * sizeof(MachO::section_64);
1620
1621 auto SecContent = SecBlock.getAlreadyMutableContent();
1622 char *P = SecContent.data();
1623 auto WriteMachOStruct = [&](auto S) {
1626 memcpy(P, &S, sizeof(S));
1627 P += sizeof(S);
1628 };
1629
1630 auto WriteSegment = [&](StringRef Name, std::vector &Secs) {
1631 MachO::segment_command_64 SegLC;
1632 memset(&SegLC, 0, sizeof(SegLC));
1634 SegLC.cmd = MachO::LC_SEGMENT_64;
1635 SegLC.cmdsize = sizeof(MachO::segment_command_64) +
1636 Secs.size() * sizeof(MachO::section_64);
1637 SegLC.nsects = Secs.size();
1638 WriteMachOStruct(SegLC);
1639 for (auto &SD : Secs) {
1640 if (SD.AddFixups)
1641 SD.AddFixups(P - SecContent.data());
1642 WriteMachOStruct(SD.Sec);
1643 }
1644 };
1645
1646 WriteMachOStruct(Hdr);
1647 if (!TextSections.empty())
1648 WriteSegment("__TEXT", TextSections);
1649 if (!DataSections.empty())
1650 WriteSegment("__DATA", DataSections);
1651
1652 assert(P == SecContent.end() && "Underflow writing ObjC runtime object");
1654}
1655
1656Error MachOPlatform::MachOPlatformPlugin::prepareSymbolTableRegistration(
1657 jitlink::LinkGraph &G, JITSymTabVector &JITSymTabInfo) {
1658
1660 if (!CStringSec)
1663
1664
1665 DenseMap<StringRef, jitlink::Symbol *> ExistingStrings;
1666 for (auto *Sym : CStringSec->symbols()) {
1667
1668
1669
1671 ExistingStrings.insert(
1672 std::make_pair(StringRef(Content.data(), Content.size()), Sym));
1673 }
1674
1675
1676
1677 {
1681
1682 for (auto *Sym : SymsToProcess) {
1684 continue;
1685
1686 auto I = ExistingStrings.find(*Sym->getName());
1687 if (I == ExistingStrings.end()) {
1688 auto &NameBlock = G.createMutableContentBlock(
1689 *CStringSec, G.allocateCString(*Sym->getName()),
1690 orc::ExecutorAddr(), 1, 0);
1691 auto &SymbolNameSym = G.addAnonymousSymbol(
1692 NameBlock, 0, NameBlock.getSize(), false, true);
1693 JITSymTabInfo.push_back({Sym, &SymbolNameSym});
1694 } else
1695 JITSymTabInfo.push_back({Sym, I->second});
1696 }
1697 }
1698
1700}
1701
1702Error MachOPlatform::MachOPlatformPlugin::addSymbolTableRegistration(
1703 jitlink::LinkGraph &G, MaterializationResponsibility &MR,
1704 JITSymTabVector &JITSymTabInfo, bool InBootstrapPhase) {
1705
1706 ExecutorAddr HeaderAddr;
1707 {
1708 std::lock_guardstd::mutex Lock(MP.PlatformMutex);
1710 assert(I != MP.JITDylibToHeaderAddr.end() && "No header registered for JD");
1711 assert(I->second && "Null header registered for JD");
1712 HeaderAddr = I->second;
1713 }
1714
1716
1717
1718
1719 std::lock_guardstd::mutex Lock(MP.PlatformMutex);
1720 auto &SymTab = MP.Bootstrap->SymTab;
1721 for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo)
1722 SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(),
1723 flagsForSymbol(*OriginalSymbol)});
1725 }
1726
1727 SymbolTableVector SymTab;
1728 for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo)
1729 SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(),
1730 flagsForSymbol(*OriginalSymbol)});
1731
1732 G.allocActions().push_back(
1734 MP.RegisterObjectSymbolTable.Addr, HeaderAddr, SymTab)),
1736 MP.DeregisterObjectSymbolTable.Addr, HeaderAddr, SymTab))});
1737
1739}
1740
1741template
1746 auto HdrInfo =
1749
1751 B.Header.cputype = HdrInfo.CPUType;
1752 B.Header.cpusubtype = HdrInfo.CPUSubType;
1753
1755 B.template addLoadCommandMachO::LC\_ID\_DYLIB(
1757 Opts.IDDylib->CurrentVersion, Opts.IDDylib->CompatibilityVersion);
1758 else
1759 B.template addLoadCommandMachO::LC\_ID\_DYLIB(JD.getName(), 0, 0, 0);
1760
1762 B.template addLoadCommandMachO::LC\_BUILD\_VERSION(
1763 BV.Platform, BV.MinOS, BV.SDK, static_cast<uint32_t>(0));
1764
1767 switch (LD.K) {
1768 case LoadKind::Default:
1769 B.template addLoadCommandMachO::LC\_LOAD\_DYLIB(
1770 LD.D.Name, LD.D.Timestamp, LD.D.CurrentVersion,
1771 LD.D.CompatibilityVersion);
1772 break;
1773 case LoadKind::Weak:
1774 B.template addLoadCommandMachO::LC\_LOAD\_WEAK\_DYLIB(
1775 LD.D.Name, LD.D.Timestamp, LD.D.CurrentVersion,
1776 LD.D.CompatibilityVersion);
1777 break;
1778 }
1779 }
1780 for (auto &P : Opts.RPaths)
1781 B.template addLoadCommandMachO::LC\_RPATH(P);
1782
1783 auto HeaderContent = G.allocateBuffer(B.layout());
1784 B.write(HeaderContent);
1785
1786 return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
1787 0);
1788}
1789
1794 createHeaderInterface(MOP, std::move(HeaderStartSymbol))),
1796
1798 std::unique_ptr R) {
1799 auto G = createPlatformGraph(MOP, "");
1800 addMachOHeader(R->getTargetJITDylib(), *G, R->getInitializerSymbol());
1801 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
1802}
1803
1806
1807void SimpleMachOHeaderMU::addMachOHeader(
1810 auto &HeaderSection = G.createSection("__header", MemProt::Read);
1812
1813
1814 G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol, HeaderBlock.getSize(),
1816 true);
1817 for (auto &HS : AdditionalHeaderSymbols)
1818 G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(),
1820 true);
1821}
1822
1826 switch (MOP.getExecutionSession().getTargetTriple().getArch()) {
1829 return ::createHeaderBlock(MOP, Opts, JD, G, HeaderSection);
1830 default:
1832 }
1833}
1834
1838
1840 for (auto &HS : AdditionalHeaderSymbols)
1843
1845 HeaderStartSymbol);
1846}
1847
1849 switch (TT.getArch()) {
1851 return { 16 * 1024,
1855 return { 4 * 1024,
1858 default:
1860 }
1861}
1862
1863}
1864}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
static StringRef getName(Value *V)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Manages the enabling and disabling of subtarget specific features.
Triple - Helper class for working with autoconf configuration names.
An Addressable with content and edges.
ArrayRef< char > getContent() const
Get the content for this block. Block must not be a zero-fill block.
void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)
Add an edge to this block.
MutableArrayRef< char > getMutableContent(LinkGraph &G)
Get mutable content for this block.
const std::string & getName() const
Get the name for this JITLinkDylib.
void removeSection(Section &Sec)
Remove a section.
Section * findSectionByName(StringRef Name)
Returns the section with the given name if it exists, otherwise returns null.
Symbol & addAbsoluteSymbol(orc::SymbolStringPtr Name, orc::ExecutorAddr Address, orc::ExecutorAddrDiff Size, Linkage L, Scope S, bool IsLive)
Add an absolute symbol.
Represents an object file section.
bool isCallable() const
Returns true is this symbol is callable.
void setName(const orc::SymbolStringPtr Name)
Rename this symbol.
const orc::SymbolStringPtr & getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
Linkage getLinkage() const
Get the linkage for this Symbol.
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
Block & getBlock()
Return the Block for this Symbol (Symbol must be defined).
bool hasName() const
Returns true if this symbol has a name.
An ExecutionSession represents a running JIT program.
const Triple & getTargetTriple() const
Return the triple for the executor.
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
DenseMap< SymbolStringPtr, JITDispatchHandlerFunction > JITDispatchHandlerAssociationMap
A map associating tag names with asynchronous wrapper function implementations in the JIT.
Represents an address in the executor process.
Represents a JIT'd dynamic library.
Error define(std::unique_ptr< MaterializationUnitType > &&MU, ResourceTrackerSP RT=nullptr)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Mediates between MachO initialization and ExecutionSession state.
Error teardownJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is removed to allow the Plat...
Definition MachOPlatform.cpp:353
static ArrayRef< std::pair< const char *, const char * > > standardLazyCompilationAliases()
Returns a list of aliases required to enable lazy compilation via the ORC runtime.
Definition MachOPlatform.cpp:429
Error setupJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is created (unless it is cre...
Definition MachOPlatform.cpp:342
static ArrayRef< std::pair< const char *, const char * > > standardRuntimeUtilityAliases()
Returns the array of standard runtime utility aliases for MachO.
Definition MachOPlatform.cpp:413
std::vector< std::pair< ExecutorAddr, MachOJITDylibDepInfo > > MachOJITDylibDepInfoMap
unique_function< std::unique_ptr< MaterializationUnit >(MachOPlatform &MOP, HeaderOptions Opts)> MachOHeaderMUBuilder
Used by setupJITDylib to create MachO header MaterializationUnits for JITDylibs.
Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) override
This method will be called under the ExecutionSession lock each time a MaterializationUnit is added t...
Definition MachOPlatform.cpp:366
static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES)
Returns an AliasMap containing the default aliases for the MachOPlatform.
Definition MachOPlatform.cpp:396
ExecutionSession & getExecutionSession() const
Error notifyRemoving(ResourceTracker &RT) override
This method will be called under the ExecutionSession lock when a ResourceTracker is removed.
Definition MachOPlatform.cpp:382
static Expected< std::unique_ptr< MachOPlatform > > Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, std::unique_ptr< DefinitionGenerator > OrcRuntime, HeaderOptions PlatformJDOpts={}, MachOHeaderMUBuilder BuildMachOHeaderMU=buildSimpleMachOHeaderMU, std::optional< SymbolAliasMap > RuntimeAliases=std::nullopt)
Try to create a MachOPlatform instance, adding the ORC runtime to the given JITDylib.
Definition MachOPlatform.cpp:280
static ArrayRef< std::pair< const char *, const char * > > requiredCXXAliases()
Returns the array of required CXX aliases.
Definition MachOPlatform.cpp:405
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Error defineMaterializing(SymbolFlagsMap SymbolFlags)
Attempt to claim responsibility for new definitions.
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization pseudo-symbol, if any.
JITDylib & getTargetJITDylib() const
Returns the target JITDylib that these symbols are being materialized into.
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
MaterializationUnit(Interface I)
virtual StringRef getName() const =0
Return the name of this materialization unit.
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization symbol for this MaterializationUnit (if any).
An ObjectLayer implementation built on JITLink.
static void lookupInitSymbolsAsync(unique_function< void(Error)> OnComplete, ExecutionSession &ES, const DenseMap< JITDylib *, SymbolLookupSet > &InitSyms)
Performs an async lookup for the given symbols in each of the given JITDylibs, calling the given hand...
API to remove / transfer ownership of JIT resources.
JITDylib & getJITDylib() const
Return the JITDylib targeted by this tracker.
static Expected< std::unique_ptr< StaticLibraryDefinitionGenerator > > Load(ObjectLayer &L, const char *FileName, VisitMembersFunction VisitMembers=VisitMembersFunction(), GetObjectFileInterface GetObjFileInterface=GetObjectFileInterface())
Try to create a StaticLibraryDefinitionGenerator from the given path.
Pointer to a pooled string representing a symbol name.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ S_REGULAR
S_REGULAR - Regular section.
void swapStruct(fat_header &mh)
@ Pointer64
A plain 64-bit pointer value relocation.
@ RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable
A TLVP entry getter/constructor, transformed to Delta32ToTLVPLoadREXRelaxable.
@ Pointer64
A plain 64-bit pointer value relocation.
LLVM_ABI const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
LLVM_ABI StringRef MachOSwift5EntrySectionName
LLVM_ABI StringRef MachOThreadBSSSectionName
LLVM_ABI StringRef MachOThreadVarsSectionName
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
IntrusiveRefCntPtr< JITDylib > JITDylibSP
std::unique_ptr< ReExportsMaterializationUnit > symbolAliases(SymbolAliasMap Aliases)
Create a ReExportsMaterializationUnit with the given aliases.
std::unique_ptr< AbsoluteSymbolsMaterializationUnit > absoluteSymbols(SymbolMap Symbols)
Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
LLVM_ABI StringRef MachOObjCProtoListSectionName
LLVM_ABI StringRef MachOSwift5ProtosSectionName
LLVM_ABI StringRef MachOEHFrameSectionName
LLVM_ABI StringRef MachOModInitFuncSectionName
LLVM_ABI StringRef MachOObjCConstSectionName
LLVM_ABI StringRef MachODataDataSectionName
LLVM_ABI StringRef MachOCompactUnwindSectionName
LLVM_ABI StringRef MachOSwift5ProtoSectionName
@ MatchExportedSymbolsOnly
static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, ArrayRef< std::pair< const char *, const char * > > AL)
LLVM_ABI StringRef MachOObjCCatListSectionName
LLVM_ABI StringRef MachOObjCClassRefsSectionName
LLVM_ABI StringRef MachOObjCDataSectionName
LLVM_ABI StringRef MachOObjCClassNameSectionName
LLVM_ABI StringRef MachOObjCMethNameSectionName
LLVM_ABI StringRef MachOInitSectionNames[22]
LLVM_ABI StringRef MachOObjCClassListSectionName
LLVM_ABI StringRef MachOObjCSelRefsSectionName
LLVM_ABI StringRef MachOSwift5FieldMetadataSectionName
LLVM_ABI StringRef MachOCStringSectionName
LLVM_ABI StringRef MachOObjCMethTypeSectionName
LLVM_ABI StringRef MachOSwift5TypesSectionName
LLVM_ABI StringRef MachOObjCNLCatListSectionName
jitlink::Block & createHeaderBlock(MachOPlatform &MOP, const MachOPlatform::HeaderOptions &Opts, JITDylib &JD, jitlink::LinkGraph &G, jitlink::Section &HeaderSection)
Definition MachOPlatform.cpp:1742
LLVM_ABI StringRef MachOObjCNLClassListSectionName
LLVM_ABI StringRef MachOObjCImageInfoSectionName
LLVM_ABI MachOHeaderInfo getMachOHeaderInfoFromTriple(const Triple &TT)
Definition MachOPlatform.cpp:1848
LLVM_ABI RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
LLVM_ABI StringRef MachOThreadDataSectionName
LLVM_ABI StringRef MachOUnwindInfoSectionName
LLVM_ABI StringRef MachODataCommonSectionName
LLVM_ABI StringRef MachOObjCProtoRefsSectionName
@ Ready
Emitted to memory, but waiting on transitive dependencies.
DenseMap< SymbolStringPtr, SymbolAliasMapEntry > SymbolAliasMap
A map of Symbols to (Symbol, Flags) pairs.
LLVM_ABI StringRef MachOSwift5TypeRefSectionName
LLVM_ABI StringRef MachOObjCCatList2SectionName
DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap
A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
LLVM_ABI iterator begin() const
value_type byte_swap(value_type value, endianness endian)
uint32_t read32(const void *P, endianness E)
void write32(void *P, uint32_t V, endianness E)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
OutputIt copy(R &&Range, OutputIt Out)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
LinkGraphPassList PostAllocationPasses
Post-allocation passes.
LinkGraphPassList PostFixupPasses
Post-fixup passes.
LinkGraphPassList PostPrunePasses
Post-prune passes.
LinkGraphPassList PrePrunePasses
Pre-prune passes.
std::vector< ExecutorAddr > DepHeaders