23#define DEBUG_TYPE "orc"
47 return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.
Sealed,
53 return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.
Sealed,
64std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(
MachOPlatform &MOP,
70 switch (
TT.getArch()) {
80 return std::make_unique<jitlink::LinkGraph>(std::move(
Name), TT, PointerSize,
95 void materialize(std::unique_ptr<MaterializationResponsibility> R)
override {
96 auto G = createPlatformGraph(MOP,
"<MachOHeaderMU>");
97 addMachOHeader(*
G, MOP,
R->getInitializerSymbol());
105 auto &HeaderSection =
G.createSection(
"__header", MemProt::Read);
106 auto &HeaderBlock = createHeaderBlock(
G, HeaderSection);
109 G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol,
110 HeaderBlock.getSize(), jitlink::Linkage::Strong,
111 jitlink::Scope::Default,
false,
true);
112 for (
auto &HS : AdditionalHeaderSymbols)
113 G.addDefinedSymbol(HeaderBlock,
HS.Offset,
HS.Name, HeaderBlock.getSize(),
114 jitlink::Linkage::Strong, jitlink::Scope::Default,
119 struct HeaderSymbol {
124 static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
125 {
"___mh_executable_header", 0}};
131 switch (
G.getTargetTriple().getArch()) {
152 auto HeaderContent =
G.allocateContent(
153 ArrayRef<char>(
reinterpret_cast<const char *
>(&Hdr),
sizeof(Hdr)));
155 return G.createContentBlock(HeaderSection, HeaderContent,
ExecutorAddr(), 8,
165 for (
auto &HS : AdditionalHeaderSymbols)
176constexpr MachOHeaderMaterializationUnit::HeaderSymbol
177 MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[];
180class MachOPlatformCompleteBootstrapMaterializationUnit
183 MachOPlatformCompleteBootstrapMaterializationUnit(
191 MOP(MOP), PlatformJDName(PlatformJDName),
192 CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),
193 DeferredAAs(std::move(DeferredAAs)),
194 PlatformBootstrap(PlatformBootstrap),
195 PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),
196 DeregisterJITDylib(DeregisterJITDylib),
197 MachOHeaderAddr(MachOHeaderAddr) {}
200 return "MachOPlatformCompleteBootstrap";
203 void materialize(std::unique_ptr<MaterializationResponsibility> R)
override {
204 using namespace jitlink;
205 auto G = createPlatformGraph(MOP,
"<OrcRTCompleteBootstrap>");
206 auto &PlaceholderSection =
207 G->createSection(
"__orc_rt_cplt_bs", MemProt::Read);
208 auto &PlaceholderBlock =
209 G->createZeroFillBlock(PlaceholderSection, 1,
ExecutorAddr(), 1, 0);
210 G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1,
211 Linkage::Strong, Scope::Hidden,
false,
true);
214 G->allocActions().reserve(DeferredAAs.size() + 2);
217 G->allocActions().push_back(
223 G->allocActions().push_back(
226 RegisterJITDylib, PlatformJDName, MachOHeaderAddr)),
228 DeregisterJITDylib, MachOHeaderAddr))});
231 std::move(DeferredAAs.begin(), DeferredAAs.end(),
232 std::back_inserter(
G->allocActions()));
251static StringRef ObjCRuntimeObjectSectionsData[] = {
256static StringRef ObjCRuntimeObjectSectionsText[] = {
263static StringRef ObjCRuntimeObjectSectionName =
264 "__llvm_jitlink_ObjCRuntimeRegistrationObject";
266static StringRef ObjCImageInfoSymbolName =
267 "__llvm_jitlink_macho_objc_imageinfo";
277 std::unique_ptr<DefinitionGenerator> OrcRuntime,
278 std::optional<SymbolAliasMap> RuntimeAliases) {
282 return make_error<StringError>(
"Unsupported MachOPlatform triple: " +
294 return std::move(Err);
297 if (
auto Err = PlatformJD.
define(
299 {EPC.getJITDispatchInfo().JITDispatchFunction,
301 {ES.
intern(
"___orc_rt_jit_dispatch_ctx"),
302 {EPC.getJITDispatchInfo().JITDispatchContext,
304 return std::move(Err);
309 ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), Err));
311 return std::move(Err);
317 JITDylib &PlatformJD,
const char *OrcRuntimePath,
318 std::optional<SymbolAliasMap> RuntimeAliases) {
321 auto OrcRuntimeArchiveGenerator =
323 if (!OrcRuntimeArchiveGenerator)
324 return OrcRuntimeArchiveGenerator.takeError();
326 return Create(ES, ObjLinkingLayer, PlatformJD,
327 std::move(*OrcRuntimeArchiveGenerator),
328 std::move(RuntimeAliases));
332 if (
auto Err = JD.
define(std::make_unique<MachOHeaderMaterializationUnit>(
333 *
this, MachOHeaderStartSymbol)))
336 return ES.
lookup({&JD}, MachOHeaderStartSymbol).takeError();
340 std::lock_guard<std::mutex> Lock(PlatformMutex);
341 auto I = JITDylibToHeaderAddr.find(&JD);
342 if (
I != JITDylibToHeaderAddr.end()) {
343 assert(HeaderAddrToJITDylib.count(
I->second) &&
344 "HeaderAddrToJITDylib missing entry");
345 HeaderAddrToJITDylib.erase(
I->second);
346 JITDylibToHeaderAddr.erase(
I);
348 JITDylibToPThreadKey.erase(&JD);
359 RegisteredInitSymbols[&JD].add(InitSym,
362 dbgs() <<
"MachOPlatform: Registered init symbol " << *InitSym <<
" for MU "
373 ArrayRef<std::pair<const char *, const char *>> AL) {
374 for (
auto &KV : AL) {
375 auto AliasName = ES.
intern(KV.first);
376 assert(!Aliases.
count(AliasName) &&
"Duplicate symbol name in alias map");
377 Aliases[std::move(AliasName)] = {ES.
intern(KV.second),
391 static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
392 {
"___cxa_atexit",
"___orc_rt_macho_cxa_atexit"}};
399 static const std::pair<const char *, const char *>
400 StandardRuntimeUtilityAliases[] = {
401 {
"___orc_rt_run_program",
"___orc_rt_macho_run_program"},
402 {
"___orc_rt_jit_dlerror",
"___orc_rt_macho_jit_dlerror"},
403 {
"___orc_rt_jit_dlopen",
"___orc_rt_macho_jit_dlopen"},
404 {
"___orc_rt_jit_dlclose",
"___orc_rt_macho_jit_dlclose"},
405 {
"___orc_rt_jit_dlsym",
"___orc_rt_macho_jit_dlsym"},
406 {
"___orc_rt_log_error",
"___orc_rt_log_error_to_stderr"}};
409 StandardRuntimeUtilityAliases);
412bool MachOPlatform::supportedTarget(
const Triple &TT) {
413 switch (TT.getArch()) {
422MachOPlatform::MachOPlatform(
425 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
Error &Err)
426 : ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer) {
428 ObjLinkingLayer.
addPlugin(std::make_unique<MachOPlatformPlugin>(*
this));
429 PlatformJD.
addGenerator(std::move(OrcRuntimeGenerator));
489 if ((Err = PlatformJD.
define(std::make_unique<MachOHeaderMaterializationUnit>(
490 *
this, MachOHeaderStartSymbol))))
492 if ((Err = ES.
lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))
499 {PlatformBootstrap.Name, PlatformShutdown.Name,
500 RegisterJITDylib.Name, DeregisterJITDylib.Name,
501 RegisterObjectPlatformSections.Name,
502 DeregisterObjectPlatformSections.Name,
503 CreatePThreadKey.Name}))
509 std::unique_lock<std::mutex> Lock(BI.Mutex);
510 BI.CV.wait(Lock, [&]() {
return BI.ActiveGraphs == 0; });
515 auto BootstrapCompleteSymbol = ES.
intern(
"__orc_rt_macho_complete_bootstrap");
516 if ((Err = PlatformJD.
define(
517 std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>(
518 *
this, PlatformJD.
getName(), BootstrapCompleteSymbol,
519 std::move(BI.DeferredAAs), PlatformBootstrap.Addr,
520 PlatformShutdown.Addr, RegisterJITDylib.Addr,
521 DeregisterJITDylib.Addr, BI.MachOHeaderAddr))))
525 std::move(BootstrapCompleteSymbol))
530 if ((Err = associateRuntimeSupportFunctions()))
534Error MachOPlatform::associateRuntimeSupportFunctions() {
537 using PushInitializersSPSSig =
539 WFs[ES.
intern(
"___orc_rt_macho_push_initializers_tag")] =
541 this, &MachOPlatform::rt_pushInitializers);
543 using LookupSymbolSPSSig =
545 WFs[ES.
intern(
"___orc_rt_macho_symbol_lookup_tag")] =
547 &MachOPlatform::rt_lookupSymbol);
552void MachOPlatform::pushInitializersLoop(
553 PushInitializersSendResultFn SendResult,
JITDylibSP JD) {
559 while (!Worklist.empty()) {
562 auto DepJD = Worklist.back();
566 if (JDDepMap.count(DepJD))
570 auto &DM = JDDepMap[DepJD];
571 DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
573 if (KV.first == DepJD)
575 DM.push_back(KV.first);
576 Worklist.push_back(KV.first);
581 auto RISItr = RegisteredInitSymbols.find(DepJD);
582 if (RISItr != RegisteredInitSymbols.end()) {
583 NewInitSymbols[DepJD] = std::move(RISItr->second);
584 RegisteredInitSymbols.erase(RISItr);
591 if (NewInitSymbols.
empty()) {
600 std::lock_guard<std::mutex> Lock(PlatformMutex);
601 for (
auto &KV : JDDepMap) {
602 auto I = JITDylibToHeaderAddr.find(KV.first);
603 if (
I != JITDylibToHeaderAddr.end())
604 HeaderAddrs[KV.first] =
I->second;
609 MachOJITDylibDepInfoMap DIM;
610 DIM.reserve(JDDepMap.size());
611 for (
auto &KV : JDDepMap) {
612 auto HI = HeaderAddrs.
find(KV.first);
614 if (HI == HeaderAddrs.
end())
617 MachOJITDylibDepInfo DepInfo;
618 for (
auto &Dep : KV.second) {
619 auto HJ = HeaderAddrs.
find(Dep);
620 if (HJ != HeaderAddrs.
end())
621 DepInfo.DepHeaders.push_back(HJ->second);
623 DIM.push_back(std::make_pair(
H, std::move(DepInfo)));
630 lookupInitSymbolsAsync(
631 [
this, SendResult = std::move(SendResult), JD](
Error Err)
mutable {
633 SendResult(std::move(Err));
635 pushInitializersLoop(std::move(SendResult), JD);
637 ES, std::move(NewInitSymbols));
640void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
644 std::lock_guard<std::mutex> Lock(PlatformMutex);
645 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
646 if (
I != HeaderAddrToJITDylib.end())
651 dbgs() <<
"MachOPlatform::rt_pushInitializers(" << JDHeaderAddr <<
") ";
653 dbgs() <<
"pushing initializers for " << JD->getName() <<
"\n";
655 dbgs() <<
"No JITDylib for header address.\n";
659 SendResult(make_error<StringError>(
"No JITDylib with header addr " +
660 formatv(
"{0:x}", JDHeaderAddr),
665 pushInitializersLoop(std::move(SendResult), JD);
668void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
671 dbgs() <<
"MachOPlatform::rt_lookupSymbol(\"" << Handle <<
"\")\n";
677 std::lock_guard<std::mutex> Lock(PlatformMutex);
678 auto I = HeaderAddrToJITDylib.find(Handle);
679 if (
I != HeaderAddrToJITDylib.end())
684 LLVM_DEBUG(
dbgs() <<
" No JITDylib for handle " << Handle <<
"\n");
685 SendResult(make_error<StringError>(
"No JITDylib associated with handle " +
692 class RtLookupNotifyComplete {
694 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
695 : SendResult(
std::
move(SendResult)) {}
698 assert(
Result->size() == 1 &&
"Unexpected result map count");
699 SendResult(
Result->begin()->second.getAddress());
701 SendResult(
Result.takeError());
706 SendSymbolAddressFn SendResult;
712 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
718 if (!CreatePThreadKey.Addr)
719 return make_error<StringError>(
720 "Attempting to create pthread key in target, but runtime support has "
721 "not been loaded yet",
726 CreatePThreadKey.Addr,
Result))
727 return std::move(Err);
731void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
735 using namespace jitlink;
737 bool InBootstrapPhase =
741 if (InBootstrapPhase) {
742 Config.PrePrunePasses.push_back(
743 [
this](LinkGraph &
G) {
return bootstrapPipelineStart(
G); });
744 Config.PostAllocationPasses.push_back([
this](LinkGraph &
G) {
745 return bootstrapPipelineRecordRuntimeFunctions(
G);
755 if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) {
756 Config.PostAllocationPasses.push_back([
this, &MR](LinkGraph &
G) {
757 return associateJITDylibHeaderSymbol(
G, MR);
765 Config.PrePrunePasses.push_back([
this, &MR](LinkGraph &
G) {
766 if (
auto Err = preserveImportantSections(
G, MR))
768 return processObjCImageInfo(
G, MR);
770 Config.PostPrunePasses.push_back(
771 [
this](LinkGraph &
G) {
return createObjCRuntimeObject(
G); });
772 Config.PostAllocationPasses.push_back(
773 [
this, &MR](LinkGraph &
G) {
return populateObjCRuntimeObject(
G, MR); });
778 Config.PostPrunePasses.insert(
779 Config.PostPrunePasses.begin(),
781 return fixTLVSectionsAndEdges(
G, JD);
786 Config.PostAllocationPasses.push_back(
788 return registerObjectPlatformSections(
G, JD, InBootstrapPhase);
793 if (InBootstrapPhase)
794 Config.PostFixupPasses.push_back(
795 [
this](LinkGraph &
G) {
return bootstrapPipelineEnd(
G); });
799MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies(
801 std::lock_guard<std::mutex> Lock(PluginMutex);
802 auto I = InitSymbolDeps.find(&MR);
803 if (
I != InitSymbolDeps.end()) {
804 SyntheticSymbolDependenciesMap
Result;
806 InitSymbolDeps.erase(&MR);
809 return SyntheticSymbolDependenciesMap();
812Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineStart(
815 std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
816 ++MP.Bootstrap.load()->ActiveGraphs;
820Error MachOPlatform::MachOPlatformPlugin::
823 std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {
824 {*MP.MachOHeaderStartSymbol, &MP.Bootstrap.load()->MachOHeaderAddr},
825 {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},
826 {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},
827 {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},
828 {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},
829 {*MP.RegisterObjectPlatformSections.Name,
830 &MP.RegisterObjectPlatformSections.Addr},
831 {*MP.DeregisterObjectPlatformSections.Name,
832 &MP.DeregisterObjectPlatformSections.Addr},
833 {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr},
834 {*MP.RegisterObjCRuntimeObject.Name, &MP.RegisterObjCRuntimeObject.Addr},
835 {*MP.DeregisterObjCRuntimeObject.Name,
836 &MP.DeregisterObjCRuntimeObject.Addr}};
838 bool RegisterMachOHeader =
false;
840 for (
auto *
Sym :
G.defined_symbols()) {
841 for (
auto &RTSym : RuntimeSymbols) {
842 if (
Sym->hasName() &&
Sym->getName() == RTSym.first) {
844 return make_error<StringError>(
845 "Duplicate " + RTSym.first +
846 " detected during MachOPlatform bootstrap",
849 if (
Sym->getName() == *MP.MachOHeaderStartSymbol)
850 RegisterMachOHeader =
true;
852 *RTSym.second =
Sym->getAddress();
857 if (RegisterMachOHeader) {
860 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
861 MP.JITDylibToHeaderAddr[&MP.PlatformJD] =
862 MP.Bootstrap.load()->MachOHeaderAddr;
863 MP.HeaderAddrToJITDylib[MP.Bootstrap.load()->MachOHeaderAddr] =
870Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd(
872 std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
873 assert(MP.Bootstrap &&
"DeferredAAs reset before bootstrap completed");
874 --MP.Bootstrap.load()->ActiveGraphs;
877 if (MP.Bootstrap.load()->ActiveGraphs == 0)
878 MP.Bootstrap.load()->CV.notify_all();
882Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
885 return Sym->getName() == *MP.MachOHeaderStartSymbol;
887 assert(
I !=
G.defined_symbols().end() &&
"Missing MachO header start symbol");
890 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
891 auto HeaderAddr = (*I)->getAddress();
892 MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
893 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
896 G.allocActions().push_back(
899 MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)),
901 MP.DeregisterJITDylib.Addr, HeaderAddr))});
905Error MachOPlatform::MachOPlatformPlugin::preserveImportantSections(
911 if (
auto *ObjCImageInfoSec =
913 if (ObjCImageInfoSec->blocks_size() != 1)
914 return make_error<StringError>(
915 "In " +
G.getName() +
916 "__DATA,__objc_imageinfo contains multiple blocks",
918 G.addAnonymousSymbol(**ObjCImageInfoSec->blocks().begin(), 0, 0,
false,
921 for (
auto *
B : ObjCImageInfoSec->blocks())
922 if (!
B->edges_empty())
923 return make_error<StringError>(
"In " +
G.getName() +
", " +
925 " contains references to symbols",
932 JITLinkSymbolSet InitSectionSymbols;
940 auto *InitSection =
G.findSectionByName(InitSectionName);
947 for (
auto &
Sym : InitSection->symbols()) {
948 auto &
B =
Sym->getBlock();
949 if (
Sym->isLive() &&
Sym->getOffset() == 0 &&
950 Sym->getSize() ==
B.getSize() && !AlreadyLiveBlocks.
count(&
B)) {
951 InitSectionSymbols.insert(
Sym);
957 for (
auto *
B : InitSection->blocks())
958 if (!AlreadyLiveBlocks.
count(
B))
959 InitSectionSymbols.insert(
960 &
G.addAnonymousSymbol(*
B, 0,
B->getSize(),
false,
true));
963 if (!InitSectionSymbols.empty()) {
964 std::lock_guard<std::mutex> Lock(PluginMutex);
965 InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
971Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
984 auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
987 if (ObjCImageInfoBlocks.empty())
989 " section in " +
G.getName(),
993 if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
994 return make_error<StringError>(
"Multiple blocks in " +
996 " section in " +
G.getName(),
1001 for (
auto &Sec :
G.sections()) {
1002 if (&Sec != ObjCImageInfo)
1003 for (
auto *
B : Sec.blocks())
1004 for (
auto &
E :
B->edges())
1005 if (
E.getTarget().isDefined() &&
1006 &
E.getTarget().getBlock().getSection() == ObjCImageInfo)
1008 " is referenced within file " +
1013 auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
1014 auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
1020 std::lock_guard<std::mutex> Lock(PluginMutex);
1023 if (ObjCImageInfoItr != ObjCImageInfos.end()) {
1026 if (ObjCImageInfoItr->second.Version != Version)
1027 return make_error<StringError>(
1028 "ObjC version in " +
G.getName() +
1029 " does not match first registered version",
1031 if (ObjCImageInfoItr->second.Flags != Flags)
1032 return make_error<StringError>(
"ObjC flags in " +
G.getName() +
1033 " do not match first registered flags",
1037 for (
auto *S : ObjCImageInfo->symbols())
1038 G.removeDefinedSymbol(*S);
1039 G.removeBlock(ObjCImageInfoBlock);
1043 G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName,
1047 {{MR.getExecutionSession().intern(ObjCImageInfoSymbolName),
1048 JITSymbolFlags()}}))
1056Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
1060 for (
auto *
Sym :
G.external_symbols())
1061 if (
Sym->getName() ==
"__tlv_bootstrap") {
1062 Sym->setName(
"___orc_rt_macho_tlv_get_addr");
1068 std::optional<uint64_t>
Key;
1070 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
1071 auto I = MP.JITDylibToPThreadKey.find(&JD);
1072 if (
I != MP.JITDylibToPThreadKey.end())
1077 if (
auto KeyOrErr = MP.createPThreadKey())
1080 return KeyOrErr.takeError();
1086 for (
auto *
B : ThreadDataSec->blocks()) {
1087 if (
B->getSize() != 3 *
G.getPointerSize())
1088 return make_error<StringError>(
"__thread_vars block at " +
1089 formatv(
"{0:x}",
B->getAddress()) +
1090 " has unexpected size",
1093 auto NewBlockContent =
G.allocateBuffer(
B->getSize());
1094 llvm::copy(
B->getContent(), NewBlockContent.data());
1095 memcpy(NewBlockContent.data() +
G.getPointerSize(), &PlatformKeyBits,
1096 G.getPointerSize());
1097 B->setContent(NewBlockContent);
1102 for (
auto *
B :
G.blocks())
1103 for (
auto &
E :
B->edges())
1106 E.setKind(jitlink::x86_64::
1107 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);
1112std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections>
1113MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
1115 using namespace jitlink;
1123 if (Sec.blocks().empty())
1125 SecRange = (*Sec.blocks().begin())->getRange();
1126 for (
auto *
B : Sec.blocks()) {
1127 auto R =
B->getRange();
1128 SecRange.Start = std::min(SecRange.Start,
R.Start);
1129 SecRange.End = std::max(SecRange.End,
R.End);
1130 for (
auto &
E :
B->edges()) {
1131 if (!
E.getTarget().isDefined())
1133 auto &TargetBlock =
E.getTarget().getBlock();
1134 auto &TargetSection = TargetBlock.getSection();
1135 if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)
1142 ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
1144 if (Section *CUInfoSec =
1146 ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
1150 if (CodeBlocks.
empty())
1151 return std::nullopt;
1156 return LHS->getAddress() <
RHS->getAddress();
1158 for (
auto *
B : CodeBlocks) {
1159 if (US.CodeRanges.empty() || US.CodeRanges.back().End !=
B->getAddress())
1160 US.CodeRanges.push_back(
B->getRange());
1162 US.CodeRanges.back().End =
B->getRange().End;
1166 dbgs() <<
"MachOPlatform identified unwind info in " <<
G.getName() <<
":\n"
1168 if (US.DwarfSection.Start)
1169 dbgs() << US.DwarfSection <<
"\n";
1172 dbgs() <<
" Compact-unwind: ";
1173 if (US.CompactUnwindSection.Start)
1174 dbgs() << US.CompactUnwindSection <<
"\n";
1177 <<
"for code ranges:\n";
1178 for (
auto &CR : US.CodeRanges)
1179 dbgs() <<
" " << CR <<
"\n";
1180 if (US.CodeRanges.size() >=
G.sections_size())
1181 dbgs() <<
"WARNING: High number of discontiguous code ranges! "
1182 "Padding may be interfering with coalescing.\n";
1188Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
1201 if (ThreadDataSection)
1202 G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
1204 ThreadDataSection = ThreadBSSSection;
1213 for (
auto &SecName : DataSections) {
1214 if (
auto *Sec =
G.findSectionByName(SecName)) {
1217 MachOPlatformSecs.
push_back({SecName,
R.getRange()});
1223 if (ThreadDataSection) {
1232 ObjCRuntimeObjectSectionName};
1234 for (
auto &SecName : PlatformSections) {
1235 auto *Sec =
G.findSectionByName(SecName);
1242 MachOPlatformSecs.
push_back({SecName,
R.getRange()});
1248 if (
auto UI = findUnwindSectionInfo(
G))
1249 UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection,
1250 UI->CompactUnwindSection);
1252 if (!MachOPlatformSecs.
empty() || UnwindInfo) {
1255 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
1256 auto I = MP.JITDylibToHeaderAddr.find(&JD);
1257 assert(
I != MP.JITDylibToHeaderAddr.end() &&
1258 "Missing header for JITDylib");
1259 HeaderAddr =
I->second;
1264 dbgs() <<
"MachOPlatform: Scraped " <<
G.getName() <<
" init sections:\n";
1265 for (
auto &KV : MachOPlatformSecs)
1266 dbgs() <<
" " << KV.first <<
": " << KV.second <<
"\n";
1269 using SPSRegisterObjectPlatformSectionsArgs =
SPSArgList<
1277 : MP.Bootstrap.load()->DeferredAAs;
1279 allocActions.push_back(
1281 WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
1282 MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
1283 MachOPlatformSecs)),
1285 WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
1286 MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
1287 UnwindInfo, MachOPlatformSecs))});
1293Error MachOPlatform::MachOPlatformPlugin::createObjCRuntimeObject(
1296 bool NeedTextSegment =
false;
1297 size_t NumRuntimeSections = 0;
1299 for (
auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData)
1300 if (
G.findSectionByName(ObjCRuntimeSectionName))
1301 ++NumRuntimeSections;
1303 for (
auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {
1304 if (
G.findSectionByName(ObjCRuntimeSectionName)) {
1305 ++NumRuntimeSections;
1306 NeedTextSegment =
true;
1311 if (NumRuntimeSections == 0)
1316 ++NumRuntimeSections;
1322 auto &Sec =
G.createSection(ObjCRuntimeObjectSectionName,
1323 MemProt::Read | MemProt::Write);
1324 G.createMutableContentBlock(Sec, MachOSize,
ExecutorAddr(), 16, 0,
true);
1329Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(
1332 auto *ObjCRuntimeObjectSec =
1333 G.findSectionByName(ObjCRuntimeObjectSectionName);
1335 if (!ObjCRuntimeObjectSec)
1338 switch (
G.getTargetTriple().getArch()) {
1344 return make_error<StringError>(
"Unrecognized MachO arch in triple " +
1345 G.getTargetTriple().str(),
1349 auto &SecBlock = **ObjCRuntimeObjectSec->blocks().begin();
1356 std::vector<SecDesc> TextSections, DataSections;
1362 memcpy(SD.Sec.segname, FQName.
data(), 6);
1363 SD.Sec.addr = SR.getStart() - SecBlock.getAddress();
1364 SD.Sec.size = SR.getSize();
1370 DataSections.push_back({});
1371 auto &SD = DataSections.back();
1372 memset(&SD.Sec, 0,
sizeof(SD.Sec));
1373 memcpy(SD.Sec.sectname,
"__objc_imageinfo", 16);
1374 strcpy(SD.Sec.segname,
"__DATA");
1376 SD.AddFixups = [&](
size_t RecordOffset) {
1378 switch (
G.getTargetTriple().getArch()) {
1391 for (
auto *
Sym :
G.external_symbols())
1392 if (
Sym->getName() == ObjCImageInfoSymbolName) {
1393 ObjCImageInfoSym =
Sym;
1396 if (!ObjCImageInfoSym)
1397 for (
auto *
Sym :
G.absolute_symbols())
1398 if (
Sym->getName() == ObjCImageInfoSymbolName) {
1399 ObjCImageInfoSym =
Sym;
1402 if (!ObjCImageInfoSym)
1403 for (
auto *
Sym :
G.defined_symbols())
1404 if (
Sym->hasName() &&
Sym->getName() == ObjCImageInfoSymbolName) {
1405 ObjCImageInfoSym =
Sym;
1408 if (!ObjCImageInfoSym)
1410 &
G.addExternalSymbol(ObjCImageInfoSymbolName, 8,
false);
1412 SecBlock.addEdge(PointerEdge,
1413 RecordOffset + ((
char *)&SD.Sec.addr - (
char *)&SD.Sec),
1414 *ObjCImageInfoSym, -SecBlock.getAddress().getValue());
1418 for (
auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) {
1419 if (
auto *GraphSec =
G.findSectionByName(ObjCRuntimeSectionName)) {
1420 DataSections.push_back({});
1421 AddSection(DataSections.back(), *GraphSec);
1425 for (
auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {
1426 if (
auto *GraphSec =
G.findSectionByName(ObjCRuntimeSectionName)) {
1427 TextSections.push_back({});
1428 AddSection(TextSections.back(), *GraphSec);
1432 assert(ObjCRuntimeObjectSec->blocks_size() == 1 &&
1433 "Unexpected number of blocks in runtime sections object");
1439 switch (
G.getTargetTriple().getArch()) {
1453 Hdr.
ncmds = 1 + !TextSections.empty();
1460 auto SecContent = SecBlock.getAlreadyMutableContent();
1461 char *
P = SecContent.data();
1462 auto WriteMachOStruct = [&](
auto S) {
1465 memcpy(
P, &S,
sizeof(S));
1469 auto WriteSegment = [&](
StringRef Name, std::vector<SecDesc> &Secs) {
1471 memset(&SegLC, 0,
sizeof(SegLC));
1473 SegLC.
cmd = MachO::LC_SEGMENT_64;
1476 SegLC.
nsects = Secs.size();
1477 WriteMachOStruct(SegLC);
1478 for (
auto &SD : Secs) {
1480 SD.AddFixups(
P - SecContent.data());
1481 WriteMachOStruct(SD.Sec);
1485 WriteMachOStruct(Hdr);
1486 if (!TextSections.empty())
1487 WriteSegment(
"__TEXT", TextSections);
1488 if (!DataSections.empty())
1489 WriteSegment(
"__DATA", DataSections);
1491 assert(
P == SecContent.end() &&
"Underflow writing ObjC runtime object");
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_LIKELY(EXPR)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Implements a dense probed hash-table based set.
Helper for Errors used as out-parameters.
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.
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Triple - Helper class for working with autoconf configuration names.
const std::string & str() const
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An Addressable with content and edges.
const std::string & getName() const
Get the name for this JITLinkDylib.
Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...
Represents an object file section.
An ExecutionSession represents a running JIT program.
ExecutorProcessControl & getExecutorProcessControl()
Get the ExecutorProcessControl object associated with this ExecutionSession.
const Triple & getTargetTriple() const
Return the triple for the executor.
Error callSPSWrapper(ExecutorAddr WrapperFnAddr, WrapperCallArgTs &&...WrapperCallArgs)
Run a wrapper function using SPS to serialize the arguments and deserialize the results.
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H)
Wrap a handler that takes concrete argument types (and a sender for a concrete return type) to produc...
void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, SymbolLookupSet Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies)
Search the given JITDylibs for the given symbols.
Error registerJITDispatchHandlers(JITDylib &JD, JITDispatchHandlerAssociationMap WFs)
For each tag symbol name, associate the corresponding AsyncHandlerWrapperFunction with the address of...
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
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.
GeneratorT & addGenerator(std::unique_ptr< GeneratorT > DefGenerator)
Adds a definition generator to this JITDylib and returns a referenece to it.
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,...
virtual StringRef getName() const =0
Return the name of this materialization unit.
virtual void materialize(std::unique_ptr< MaterializationResponsibility > R)=0
Implementations of this method should materialize all symbols in the materialzation unit,...
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization symbol for this MaterializationUnit (if any).
An ObjectLayer implementation built on JITLink.
ObjectLinkingLayer & addPlugin(std::unique_ptr< Plugin > P)
Add a pass-config modifier.
void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< MemoryBuffer > O) override
Emit an object file.
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, GetObjectFileInterface GetObjFileInterface=GetObjectFileInterface())
Try to create a StaticLibraryDefinitionGenerator from the given path.
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Pointer to a pooled string representing a symbol name.
A utility class for serializing to a blob from a variadic list.
SPS tag type for expecteds, which are either a T or a string representing an error.
SPS tag type for optionals.
Output char buffer with overflow check.
SPS tag type for sequences.
static bool serialize(SPSOutputBuffer &OB, const MachOPlatform::MachOJITDylibDepInfo &DDI)
static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI)
static bool deserialize(SPSInputBuffer &IB, MachOPlatform::MachOJITDylibDepInfo &DDI)
Specialize to describe how to serialize/deserialize to/from the given concrete type.
static Expected< WrapperFunctionCall > Create(ExecutorAddr FnAddr, const ArgTs &...Args)
Create a WrapperFunctionCall using the given SPS serializer to serialize the arguments.
unique_function is a type-erasing functor similar to std::function.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
@ S_REGULAR
S_REGULAR - Regular section.
void swapStruct(fat_header &mh)
constexpr uint64_t PointerSize
aarch64 pointer size.
@ 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.
const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
constexpr support::endianness Endianness
The endianness of all multi-byte encoded values in MessagePack.
SPSTuple< SPSExecutorAddr, SPSExecutorAddr > SPSExecutorAddrRange
std::vector< AllocActionCallPair > AllocActions
A vector of allocation actions to be run for this allocation.
StringRef MachOSwift5EntrySectionName
StringRef MachOThreadBSSSectionName
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...
StringRef MachOCompactUnwindInfoSectionName
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.
StringRef MachOSwift5ProtosSectionName
StringRef MachOEHFrameSectionName
StringRef MachOModInitFuncSectionName
StringRef MachOInitSectionNames[19]
StringRef MachOObjCConstSectionName
StringRef MachODataDataSectionName
StringRef MachOSwift5ProtoSectionName
static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, ArrayRef< std::pair< const char *, const char * > > AL)
StringRef MachOObjCCatListSectionName
StringRef MachOObjCClassRefsSectionName
StringRef MachOObjCDataSectionName
StringRef MachOObjCClassNameSectionName
StringRef MachOObjCMethNameSectionName
StringRef MachOObjCClassListSectionName
StringRef MachOObjCSelRefsSectionName
StringRef MachOSwift5FieldMetadataSectionName
StringRef MachOObjCMethTypeSectionName
StringRef MachOSwift5TypesSectionName
StringRef MachOObjCImageInfoSectionName
RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
StringRef MachOThreadDataSectionName
StringRef MachODataCommonSectionName
StringRef MachOSwift5TypeRefSectionName
value_type byte_swap(value_type value, endianness endian)
uint32_t read32(const void *P, endianness E)
constexpr endianness system_endianness()
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
Represents an address range in the exceutor process.