Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
35266 views
//===------ MachOPlatform.cpp - Utilities for executing MachO in Orc ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"910#include "llvm/BinaryFormat/MachO.h"11#include "llvm/ExecutionEngine/JITLink/MachO.h"12#include "llvm/ExecutionEngine/JITLink/aarch64.h"13#include "llvm/ExecutionEngine/JITLink/x86_64.h"14#include "llvm/ExecutionEngine/Orc/DebugUtils.h"15#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"16#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"17#include "llvm/ExecutionEngine/Orc/MachOBuilder.h"18#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"19#include "llvm/Support/BinaryByteStream.h"20#include "llvm/Support/Debug.h"21#include <optional>2223#define DEBUG_TYPE "orc"2425using namespace llvm;26using namespace llvm::orc;27using namespace llvm::orc::shared;2829namespace llvm {30namespace orc {31namespace shared {3233using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>;34using SPSMachOJITDylibDepInfoMap =35SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>;3637class SPSMachOExecutorSymbolFlags;3839template <>40class SPSSerializationTraits<SPSMachOJITDylibDepInfo,41MachOPlatform::MachOJITDylibDepInfo> {42public:43static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) {44return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders);45}4647static bool serialize(SPSOutputBuffer &OB,48const MachOPlatform::MachOJITDylibDepInfo &DDI) {49return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed,50DDI.DepHeaders);51}5253static bool deserialize(SPSInputBuffer &IB,54MachOPlatform::MachOJITDylibDepInfo &DDI) {55return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed,56DDI.DepHeaders);57}58};5960template <>61class SPSSerializationTraits<SPSMachOExecutorSymbolFlags,62MachOPlatform::MachOExecutorSymbolFlags> {63private:64using UT = std::underlying_type_t<MachOPlatform::MachOExecutorSymbolFlags>;6566public:67static size_t size(const MachOPlatform::MachOExecutorSymbolFlags &SF) {68return sizeof(UT);69}7071static bool serialize(SPSOutputBuffer &OB,72const MachOPlatform::MachOExecutorSymbolFlags &SF) {73return SPSArgList<UT>::serialize(OB, static_cast<UT>(SF));74}7576static bool deserialize(SPSInputBuffer &IB,77MachOPlatform::MachOExecutorSymbolFlags &SF) {78UT Tmp;79if (!SPSArgList<UT>::deserialize(IB, Tmp))80return false;81SF = static_cast<MachOPlatform::MachOExecutorSymbolFlags>(Tmp);82return true;83}84};8586} // namespace shared87} // namespace orc88} // namespace llvm8990namespace {9192using SPSRegisterSymbolsArgs =93SPSArgList<SPSExecutorAddr,94SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr,95SPSMachOExecutorSymbolFlags>>>;9697std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP,98std::string Name) {99unsigned PointerSize;100llvm::endianness Endianness;101const auto &TT = MOP.getExecutionSession().getTargetTriple();102103switch (TT.getArch()) {104case Triple::aarch64:105case Triple::x86_64:106PointerSize = 8;107Endianness = llvm::endianness::little;108break;109default:110llvm_unreachable("Unrecognized architecture");111}112113return std::make_unique<jitlink::LinkGraph>(std::move(Name), TT, PointerSize,114Endianness,115jitlink::getGenericEdgeKindName);116}117118// Creates a Bootstrap-Complete LinkGraph to run deferred actions.119class MachOPlatformCompleteBootstrapMaterializationUnit120: public MaterializationUnit {121public:122using SymbolTableVector =123SmallVector<std::tuple<ExecutorAddr, ExecutorAddr,124MachOPlatform::MachOExecutorSymbolFlags>>;125126MachOPlatformCompleteBootstrapMaterializationUnit(127MachOPlatform &MOP, StringRef PlatformJDName,128SymbolStringPtr CompleteBootstrapSymbol, SymbolTableVector SymTab,129shared::AllocActions DeferredAAs, ExecutorAddr MachOHeaderAddr,130ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown,131ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib,132ExecutorAddr RegisterObjectSymbolTable,133ExecutorAddr DeregisterObjectSymbolTable)134: MaterializationUnit(135{{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}),136MOP(MOP), PlatformJDName(PlatformJDName),137CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),138SymTab(std::move(SymTab)), DeferredAAs(std::move(DeferredAAs)),139MachOHeaderAddr(MachOHeaderAddr), PlatformBootstrap(PlatformBootstrap),140PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),141DeregisterJITDylib(DeregisterJITDylib),142RegisterObjectSymbolTable(RegisterObjectSymbolTable),143DeregisterObjectSymbolTable(DeregisterObjectSymbolTable) {}144145StringRef getName() const override {146return "MachOPlatformCompleteBootstrap";147}148149void materialize(std::unique_ptr<MaterializationResponsibility> R) override {150using namespace jitlink;151auto G = createPlatformGraph(MOP, "<OrcRTCompleteBootstrap>");152auto &PlaceholderSection =153G->createSection("__orc_rt_cplt_bs", MemProt::Read);154auto &PlaceholderBlock =155G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0);156G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1,157Linkage::Strong, Scope::Hidden, false, true);158159// Reserve space for the stolen actions, plus two extras.160G->allocActions().reserve(DeferredAAs.size() + 3);161162// 1. Bootstrap the platform support code.163G->allocActions().push_back(164{cantFail(WrapperFunctionCall::Create<SPSArgList<>>(PlatformBootstrap)),165cantFail(166WrapperFunctionCall::Create<SPSArgList<>>(PlatformShutdown))});167168// 2. Register the platform JITDylib.169G->allocActions().push_back(170{cantFail(WrapperFunctionCall::Create<171SPSArgList<SPSString, SPSExecutorAddr>>(172RegisterJITDylib, PlatformJDName, MachOHeaderAddr)),173cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(174DeregisterJITDylib, MachOHeaderAddr))});175176// 3. Register deferred symbols.177G->allocActions().push_back(178{cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>(179RegisterObjectSymbolTable, MachOHeaderAddr, SymTab)),180cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>(181DeregisterObjectSymbolTable, MachOHeaderAddr, SymTab))});182183// 4. Add the deferred actions to the graph.184std::move(DeferredAAs.begin(), DeferredAAs.end(),185std::back_inserter(G->allocActions()));186187MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));188}189190void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}191192private:193MachOPlatform &MOP;194StringRef PlatformJDName;195SymbolStringPtr CompleteBootstrapSymbol;196SymbolTableVector SymTab;197shared::AllocActions DeferredAAs;198ExecutorAddr MachOHeaderAddr;199ExecutorAddr PlatformBootstrap;200ExecutorAddr PlatformShutdown;201ExecutorAddr RegisterJITDylib;202ExecutorAddr DeregisterJITDylib;203ExecutorAddr RegisterObjectSymbolTable;204ExecutorAddr DeregisterObjectSymbolTable;205};206207static StringRef ObjCRuntimeObjectSectionsData[] = {208MachOObjCCatListSectionName, MachOObjCCatList2SectionName,209MachOObjCClassListSectionName, MachOObjCClassRefsSectionName,210MachOObjCConstSectionName, MachOObjCDataSectionName,211MachOObjCProtoListSectionName, MachOObjCProtoRefsSectionName,212MachOObjCNLCatListSectionName, MachOObjCNLClassListSectionName,213MachOObjCSelRefsSectionName};214215static StringRef ObjCRuntimeObjectSectionsText[] = {216MachOObjCClassNameSectionName, MachOObjCMethNameSectionName,217MachOObjCMethTypeSectionName, MachOSwift5TypesSectionName,218MachOSwift5TypeRefSectionName, MachOSwift5FieldMetadataSectionName,219MachOSwift5EntrySectionName, MachOSwift5ProtoSectionName,220MachOSwift5ProtosSectionName};221222static StringRef ObjCRuntimeObjectSectionName =223"__llvm_jitlink_ObjCRuntimeRegistrationObject";224225static StringRef ObjCImageInfoSymbolName =226"__llvm_jitlink_macho_objc_imageinfo";227228struct ObjCImageInfoFlags {229uint16_t SwiftABIVersion;230uint16_t SwiftVersion;231bool HasCategoryClassProperties;232bool HasSignedObjCClassROs;233234static constexpr uint32_t SIGNED_CLASS_RO = (1 << 4);235static constexpr uint32_t HAS_CATEGORY_CLASS_PROPERTIES = (1 << 6);236237explicit ObjCImageInfoFlags(uint32_t RawFlags) {238HasSignedObjCClassROs = RawFlags & SIGNED_CLASS_RO;239HasCategoryClassProperties = RawFlags & HAS_CATEGORY_CLASS_PROPERTIES;240SwiftABIVersion = (RawFlags >> 8) & 0xFF;241SwiftVersion = (RawFlags >> 16) & 0xFFFF;242}243244uint32_t rawFlags() const {245uint32_t Result = 0;246if (HasCategoryClassProperties)247Result |= HAS_CATEGORY_CLASS_PROPERTIES;248if (HasSignedObjCClassROs)249Result |= SIGNED_CLASS_RO;250Result |= (SwiftABIVersion << 8);251Result |= (SwiftVersion << 16);252return Result;253}254};255} // end anonymous namespace256257namespace llvm {258namespace orc {259260std::optional<MachOPlatform::HeaderOptions::BuildVersionOpts>261MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple(const Triple &TT,262uint32_t MinOS,263uint32_t SDK) {264265uint32_t Platform;266switch (TT.getOS()) {267case Triple::IOS:268Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR269: MachO::PLATFORM_IOS;270break;271case Triple::MacOSX:272Platform = MachO::PLATFORM_MACOS;273break;274case Triple::TvOS:275Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR276: MachO::PLATFORM_TVOS;277break;278case Triple::WatchOS:279Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR280: MachO::PLATFORM_WATCHOS;281break;282case Triple::XROS:283Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR284: MachO::PLATFORM_XROS;285break;286default:287return std::nullopt;288}289290return MachOPlatform::HeaderOptions::BuildVersionOpts{Platform, MinOS, SDK};291}292293Expected<std::unique_ptr<MachOPlatform>> MachOPlatform::Create(294ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,295JITDylib &PlatformJD, std::unique_ptr<DefinitionGenerator> OrcRuntime,296HeaderOptions PlatformJDOpts, MachOHeaderMUBuilder BuildMachOHeaderMU,297std::optional<SymbolAliasMap> RuntimeAliases) {298299// If the target is not supported then bail out immediately.300if (!supportedTarget(ES.getTargetTriple()))301return make_error<StringError>("Unsupported MachOPlatform triple: " +302ES.getTargetTriple().str(),303inconvertibleErrorCode());304305auto &EPC = ES.getExecutorProcessControl();306307// Create default aliases if the caller didn't supply any.308if (!RuntimeAliases)309RuntimeAliases = standardPlatformAliases(ES);310311// Define the aliases.312if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))313return std::move(Err);314315// Add JIT-dispatch function support symbols.316if (auto Err = PlatformJD.define(317absoluteSymbols({{ES.intern("___orc_rt_jit_dispatch"),318{EPC.getJITDispatchInfo().JITDispatchFunction,319JITSymbolFlags::Exported}},320{ES.intern("___orc_rt_jit_dispatch_ctx"),321{EPC.getJITDispatchInfo().JITDispatchContext,322JITSymbolFlags::Exported}}})))323return std::move(Err);324325// Create the instance.326Error Err = Error::success();327auto P = std::unique_ptr<MachOPlatform>(new MachOPlatform(328ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime),329std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU), Err));330if (Err)331return std::move(Err);332return std::move(P);333}334335Expected<std::unique_ptr<MachOPlatform>>336MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,337JITDylib &PlatformJD, const char *OrcRuntimePath,338HeaderOptions PlatformJDOpts,339MachOHeaderMUBuilder BuildMachOHeaderMU,340std::optional<SymbolAliasMap> RuntimeAliases) {341342// Create a generator for the ORC runtime archive.343auto OrcRuntimeArchiveGenerator =344StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);345if (!OrcRuntimeArchiveGenerator)346return OrcRuntimeArchiveGenerator.takeError();347348return Create(ES, ObjLinkingLayer, PlatformJD,349std::move(*OrcRuntimeArchiveGenerator),350std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU),351std::move(RuntimeAliases));352}353354Error MachOPlatform::setupJITDylib(JITDylib &JD) {355return setupJITDylib(JD, /*Opts=*/{});356}357358Error MachOPlatform::setupJITDylib(JITDylib &JD, HeaderOptions Opts) {359if (auto Err = JD.define(BuildMachOHeaderMU(*this, std::move(Opts))))360return Err;361362return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();363}364365Error MachOPlatform::teardownJITDylib(JITDylib &JD) {366std::lock_guard<std::mutex> Lock(PlatformMutex);367auto I = JITDylibToHeaderAddr.find(&JD);368if (I != JITDylibToHeaderAddr.end()) {369assert(HeaderAddrToJITDylib.count(I->second) &&370"HeaderAddrToJITDylib missing entry");371HeaderAddrToJITDylib.erase(I->second);372JITDylibToHeaderAddr.erase(I);373}374JITDylibToPThreadKey.erase(&JD);375return Error::success();376}377378Error MachOPlatform::notifyAdding(ResourceTracker &RT,379const MaterializationUnit &MU) {380auto &JD = RT.getJITDylib();381const auto &InitSym = MU.getInitializerSymbol();382if (!InitSym)383return Error::success();384385RegisteredInitSymbols[&JD].add(InitSym,386SymbolLookupFlags::WeaklyReferencedSymbol);387LLVM_DEBUG({388dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "389<< MU.getName() << "\n";390});391return Error::success();392}393394Error MachOPlatform::notifyRemoving(ResourceTracker &RT) {395llvm_unreachable("Not supported yet");396}397398static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,399ArrayRef<std::pair<const char *, const char *>> AL) {400for (auto &KV : AL) {401auto AliasName = ES.intern(KV.first);402assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");403Aliases[std::move(AliasName)] = {ES.intern(KV.second),404JITSymbolFlags::Exported};405}406}407408SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) {409SymbolAliasMap Aliases;410addAliases(ES, Aliases, requiredCXXAliases());411addAliases(ES, Aliases, standardRuntimeUtilityAliases());412return Aliases;413}414415ArrayRef<std::pair<const char *, const char *>>416MachOPlatform::requiredCXXAliases() {417static const std::pair<const char *, const char *> RequiredCXXAliases[] = {418{"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}};419420return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);421}422423ArrayRef<std::pair<const char *, const char *>>424MachOPlatform::standardRuntimeUtilityAliases() {425static const std::pair<const char *, const char *>426StandardRuntimeUtilityAliases[] = {427{"___orc_rt_run_program", "___orc_rt_macho_run_program"},428{"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},429{"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},430{"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},431{"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},432{"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};433434return ArrayRef<std::pair<const char *, const char *>>(435StandardRuntimeUtilityAliases);436}437438bool MachOPlatform::supportedTarget(const Triple &TT) {439switch (TT.getArch()) {440case Triple::aarch64:441case Triple::x86_64:442return true;443default:444return false;445}446}447448jitlink::Edge::Kind MachOPlatform::getPointerEdgeKind(jitlink::LinkGraph &G) {449switch (G.getTargetTriple().getArch()) {450case Triple::aarch64:451return jitlink::aarch64::Pointer64;452case Triple::x86_64:453return jitlink::x86_64::Pointer64;454default:455llvm_unreachable("Unsupported architecture");456}457}458459MachOPlatform::MachOExecutorSymbolFlags460MachOPlatform::flagsForSymbol(jitlink::Symbol &Sym) {461MachOPlatform::MachOExecutorSymbolFlags Flags{};462if (Sym.getLinkage() == jitlink::Linkage::Weak)463Flags |= MachOExecutorSymbolFlags::Weak;464465if (Sym.isCallable())466Flags |= MachOExecutorSymbolFlags::Callable;467468return Flags;469}470471MachOPlatform::MachOPlatform(472ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,473JITDylib &PlatformJD,474std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,475HeaderOptions PlatformJDOpts, MachOHeaderMUBuilder BuildMachOHeaderMU,476Error &Err)477: ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer),478BuildMachOHeaderMU(std::move(BuildMachOHeaderMU)) {479ErrorAsOutParameter _(&Err);480ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));481PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));482483BootstrapInfo BI;484Bootstrap = &BI;485486// Bootstrap process -- here be phase-ordering dragons.487//488// The MachOPlatform class uses allocation actions to register metadata489// sections with the ORC runtime, however the runtime contains metadata490// registration functions that have their own metadata that they need to491// register (e.g. the frame-info registration functions have frame-info).492// We can't use an ordinary lookup to find these registration functions493// because their address is needed during the link of the containing graph494// itself (to build the allocation actions that will call the registration495// functions). Further complicating the situation (a) the graph containing496// the registration functions is allowed to depend on other graphs (e.g. the497// graph containing the ORC runtime RTTI support) so we need to handle an498// unknown set of dependencies during bootstrap, and (b) these graphs may499// be linked concurrently if the user has installed a concurrent dispatcher.500//501// We satisfy these constraints by implementing a bootstrap phase during which502// allocation actions generated by MachOPlatform are appended to a list of503// deferred allocation actions, rather than to the graphs themselves. At the504// end of the bootstrap process the deferred actions are attached to a final505// "complete-bootstrap" graph that causes them to be run.506//507// The bootstrap steps are as follows:508//509// 1. Request the graph containing the mach header. This graph is guaranteed510// not to have any metadata so the fact that the registration functions511// are not available yet is not a problem.512//513// 2. Look up the registration functions and discard the results. This will514// trigger linking of the graph containing these functions, and515// consequently any graphs that it depends on. We do not use the lookup516// result to find the addresses of the functions requested (as described517// above the lookup will return too late for that), instead we capture the518// addresses in a post-allocation pass injected by the platform runtime519// during bootstrap only.520//521// 3. During bootstrap the MachOPlatformPlugin keeps a count of the number of522// graphs being linked (potentially concurrently), and we block until all523// of these graphs have completed linking. This is to avoid a race on the524// deferred-actions vector: the lookup for the runtime registration525// functions may return while some functions (those that are being526// incidentally linked in, but aren't reachable via the runtime functions)527// are still being linked, and we need to capture any allocation actions528// for this incidental code before we proceed.529//530// 4. Once all active links are complete we transfer the deferred actions to531// a newly added CompleteBootstrap graph and then request a symbol from532// the CompleteBootstrap graph to trigger materialization. This will cause533// all deferred actions to be run, and once this lookup returns we can534// proceed.535//536// 5. Finally, we associate runtime support methods in MachOPlatform with537// the corresponding jit-dispatch tag variables in the ORC runtime to make538// the support methods callable. The bootstrap is now complete.539540// Step (1) Add header materialization unit and request.541if ((Err = PlatformJD.define(542this->BuildMachOHeaderMU(*this, std::move(PlatformJDOpts)))))543return;544if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))545return;546547// Step (2) Request runtime registration functions to trigger548// materialization..549if ((Err = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),550SymbolLookupSet(551{PlatformBootstrap.Name, PlatformShutdown.Name,552RegisterJITDylib.Name, DeregisterJITDylib.Name,553RegisterObjectSymbolTable.Name,554DeregisterObjectSymbolTable.Name,555RegisterObjectPlatformSections.Name,556DeregisterObjectPlatformSections.Name,557CreatePThreadKey.Name}))558.takeError()))559return;560561// Step (3) Wait for any incidental linker work to complete.562{563std::unique_lock<std::mutex> Lock(BI.Mutex);564BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; });565Bootstrap = nullptr;566}567568// Step (4) Add complete-bootstrap materialization unit and request.569auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap");570if ((Err = PlatformJD.define(571std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>(572*this, PlatformJD.getName(), BootstrapCompleteSymbol,573std::move(BI.SymTab), std::move(BI.DeferredAAs),574BI.MachOHeaderAddr, PlatformBootstrap.Addr,575PlatformShutdown.Addr, RegisterJITDylib.Addr,576DeregisterJITDylib.Addr, RegisterObjectSymbolTable.Addr,577DeregisterObjectSymbolTable.Addr))))578return;579if ((Err = ES.lookup(makeJITDylibSearchOrder(580&PlatformJD, JITDylibLookupFlags::MatchAllSymbols),581std::move(BootstrapCompleteSymbol))582.takeError()))583return;584585// (5) Associate runtime support functions.586if ((Err = associateRuntimeSupportFunctions()))587return;588}589590Error MachOPlatform::associateRuntimeSupportFunctions() {591ExecutionSession::JITDispatchHandlerAssociationMap WFs;592593using PushInitializersSPSSig =594SPSExpected<SPSMachOJITDylibDepInfoMap>(SPSExecutorAddr);595WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] =596ES.wrapAsyncWithSPS<PushInitializersSPSSig>(597this, &MachOPlatform::rt_pushInitializers);598599using PushSymbolsSPSSig =600SPSError(SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>);601WFs[ES.intern("___orc_rt_macho_push_symbols_tag")] =602ES.wrapAsyncWithSPS<PushSymbolsSPSSig>(this,603&MachOPlatform::rt_pushSymbols);604605return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));606}607608void MachOPlatform::pushInitializersLoop(609PushInitializersSendResultFn SendResult, JITDylibSP JD) {610DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;611DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap;612SmallVector<JITDylib *, 16> Worklist({JD.get()});613614ES.runSessionLocked([&]() {615while (!Worklist.empty()) {616// FIXME: Check for defunct dylibs.617618auto DepJD = Worklist.back();619Worklist.pop_back();620621// If we've already visited this JITDylib on this iteration then continue.622if (JDDepMap.count(DepJD))623continue;624625// Add dep info.626auto &DM = JDDepMap[DepJD];627DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {628for (auto &KV : O) {629if (KV.first == DepJD)630continue;631DM.push_back(KV.first);632Worklist.push_back(KV.first);633}634});635636// Add any registered init symbols.637auto RISItr = RegisteredInitSymbols.find(DepJD);638if (RISItr != RegisteredInitSymbols.end()) {639NewInitSymbols[DepJD] = std::move(RISItr->second);640RegisteredInitSymbols.erase(RISItr);641}642}643});644645// If there are no further init symbols to look up then send the link order646// (as a list of header addresses) to the caller.647if (NewInitSymbols.empty()) {648649// To make the list intelligible to the runtime we need to convert all650// JITDylib pointers to their header addresses. Only include JITDylibs651// that appear in the JITDylibToHeaderAddr map (i.e. those that have been652// through setupJITDylib) -- bare JITDylibs aren't managed by the platform.653DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;654HeaderAddrs.reserve(JDDepMap.size());655{656std::lock_guard<std::mutex> Lock(PlatformMutex);657for (auto &KV : JDDepMap) {658auto I = JITDylibToHeaderAddr.find(KV.first);659if (I != JITDylibToHeaderAddr.end())660HeaderAddrs[KV.first] = I->second;661}662}663664// Build the dep info map to return.665MachOJITDylibDepInfoMap DIM;666DIM.reserve(JDDepMap.size());667for (auto &KV : JDDepMap) {668auto HI = HeaderAddrs.find(KV.first);669// Skip unmanaged JITDylibs.670if (HI == HeaderAddrs.end())671continue;672auto H = HI->second;673MachOJITDylibDepInfo DepInfo;674for (auto &Dep : KV.second) {675auto HJ = HeaderAddrs.find(Dep);676if (HJ != HeaderAddrs.end())677DepInfo.DepHeaders.push_back(HJ->second);678}679DIM.push_back(std::make_pair(H, std::move(DepInfo)));680}681SendResult(DIM);682return;683}684685// Otherwise issue a lookup and re-run this phase when it completes.686lookupInitSymbolsAsync(687[this, SendResult = std::move(SendResult), JD](Error Err) mutable {688if (Err)689SendResult(std::move(Err));690else691pushInitializersLoop(std::move(SendResult), JD);692},693ES, std::move(NewInitSymbols));694}695696void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,697ExecutorAddr JDHeaderAddr) {698JITDylibSP JD;699{700std::lock_guard<std::mutex> Lock(PlatformMutex);701auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);702if (I != HeaderAddrToJITDylib.end())703JD = I->second;704}705706LLVM_DEBUG({707dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";708if (JD)709dbgs() << "pushing initializers for " << JD->getName() << "\n";710else711dbgs() << "No JITDylib for header address.\n";712});713714if (!JD) {715SendResult(make_error<StringError>("No JITDylib with header addr " +716formatv("{0:x}", JDHeaderAddr),717inconvertibleErrorCode()));718return;719}720721pushInitializersLoop(std::move(SendResult), JD);722}723724void MachOPlatform::rt_pushSymbols(725PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle,726const std::vector<std::pair<StringRef, bool>> &SymbolNames) {727728JITDylib *JD = nullptr;729730{731std::lock_guard<std::mutex> Lock(PlatformMutex);732auto I = HeaderAddrToJITDylib.find(Handle);733if (I != HeaderAddrToJITDylib.end())734JD = I->second;735}736LLVM_DEBUG({737dbgs() << "MachOPlatform::rt_pushSymbols(";738if (JD)739dbgs() << "\"" << JD->getName() << "\", [ ";740else741dbgs() << "<invalid handle " << Handle << ">, [ ";742for (auto &Name : SymbolNames)743dbgs() << "\"" << Name.first << "\" ";744dbgs() << "])\n";745});746747if (!JD) {748SendResult(make_error<StringError>("No JITDylib associated with handle " +749formatv("{0:x}", Handle),750inconvertibleErrorCode()));751return;752}753754SymbolLookupSet LS;755for (auto &[Name, Required] : SymbolNames)756LS.add(ES.intern(Name), Required757? SymbolLookupFlags::RequiredSymbol758: SymbolLookupFlags::WeaklyReferencedSymbol);759760ES.lookup(761LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},762std::move(LS), SymbolState::Ready,763[SendResult = std::move(SendResult)](Expected<SymbolMap> Result) mutable {764SendResult(Result.takeError());765},766NoDependenciesToRegister);767}768769Expected<uint64_t> MachOPlatform::createPThreadKey() {770if (!CreatePThreadKey.Addr)771return make_error<StringError>(772"Attempting to create pthread key in target, but runtime support has "773"not been loaded yet",774inconvertibleErrorCode());775776Expected<uint64_t> Result(0);777if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(778CreatePThreadKey.Addr, Result))779return std::move(Err);780return Result;781}782783void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(784MaterializationResponsibility &MR, jitlink::LinkGraph &LG,785jitlink::PassConfiguration &Config) {786787using namespace jitlink;788789bool InBootstrapPhase =790&MR.getTargetJITDylib() == &MP.PlatformJD && MP.Bootstrap;791792// If we're in the bootstrap phase then increment the active graphs.793if (InBootstrapPhase) {794Config.PrePrunePasses.push_back(795[this](LinkGraph &G) { return bootstrapPipelineStart(G); });796Config.PostAllocationPasses.push_back([this](LinkGraph &G) {797return bootstrapPipelineRecordRuntimeFunctions(G);798});799}800801// --- Handle Initializers ---802if (auto InitSymbol = MR.getInitializerSymbol()) {803804// If the initializer symbol is the MachOHeader start symbol then just805// register it and then bail out -- the header materialization unit806// definitely doesn't need any other passes.807if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) {808Config.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) {809return associateJITDylibHeaderSymbol(G, MR);810});811return;812}813814// If the object contains an init symbol other than the header start symbol815// then add passes to preserve, process and register the init816// sections/symbols.817Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) {818if (auto Err = preserveImportantSections(G, MR))819return Err;820return processObjCImageInfo(G, MR);821});822Config.PostPrunePasses.push_back(823[this](LinkGraph &G) { return createObjCRuntimeObject(G); });824Config.PostAllocationPasses.push_back(825[this, &MR](LinkGraph &G) { return populateObjCRuntimeObject(G, MR); });826}827828// Insert TLV lowering at the start of the PostPrunePasses, since we want829// it to run before GOT/PLT lowering.830Config.PostPrunePasses.insert(831Config.PostPrunePasses.begin(),832[this, &JD = MR.getTargetJITDylib()](LinkGraph &G) {833return fixTLVSectionsAndEdges(G, JD);834});835836// Add symbol table prepare and register passes: These will add strings for837// all symbols to the c-strings section, and build a symbol table registration838// call.839auto JITSymTabInfo = std::make_shared<JITSymTabVector>();840Config.PostPrunePasses.push_back([this, JITSymTabInfo](LinkGraph &G) {841return prepareSymbolTableRegistration(G, *JITSymTabInfo);842});843Config.PostFixupPasses.push_back([this, &MR, JITSymTabInfo,844InBootstrapPhase](LinkGraph &G) {845return addSymbolTableRegistration(G, MR, *JITSymTabInfo, InBootstrapPhase);846});847848// Add a pass to register the final addresses of any special sections in the849// object with the runtime.850Config.PostAllocationPasses.push_back(851[this, &JD = MR.getTargetJITDylib(), InBootstrapPhase](LinkGraph &G) {852return registerObjectPlatformSections(G, JD, InBootstrapPhase);853});854855// If we're in the bootstrap phase then steal allocation actions and then856// decrement the active graphs.857if (InBootstrapPhase)858Config.PostFixupPasses.push_back(859[this](LinkGraph &G) { return bootstrapPipelineEnd(G); });860}861862ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap863MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies(864MaterializationResponsibility &MR) {865std::lock_guard<std::mutex> Lock(PluginMutex);866auto I = InitSymbolDeps.find(&MR);867if (I != InitSymbolDeps.end()) {868SyntheticSymbolDependenciesMap Result;869Result[MR.getInitializerSymbol()] = std::move(I->second);870InitSymbolDeps.erase(&MR);871return Result;872}873return SyntheticSymbolDependenciesMap();874}875876Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineStart(877jitlink::LinkGraph &G) {878// Increment the active graphs count in BootstrapInfo.879std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);880++MP.Bootstrap.load()->ActiveGraphs;881return Error::success();882}883884Error MachOPlatform::MachOPlatformPlugin::885bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) {886// Record bootstrap function names.887std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {888{*MP.MachOHeaderStartSymbol, &MP.Bootstrap.load()->MachOHeaderAddr},889{*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},890{*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},891{*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},892{*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},893{*MP.RegisterObjectSymbolTable.Name, &MP.RegisterObjectSymbolTable.Addr},894{*MP.DeregisterObjectSymbolTable.Name,895&MP.DeregisterObjectSymbolTable.Addr},896{*MP.RegisterObjectPlatformSections.Name,897&MP.RegisterObjectPlatformSections.Addr},898{*MP.DeregisterObjectPlatformSections.Name,899&MP.DeregisterObjectPlatformSections.Addr},900{*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr},901{*MP.RegisterObjCRuntimeObject.Name, &MP.RegisterObjCRuntimeObject.Addr},902{*MP.DeregisterObjCRuntimeObject.Name,903&MP.DeregisterObjCRuntimeObject.Addr}};904905bool RegisterMachOHeader = false;906907for (auto *Sym : G.defined_symbols()) {908for (auto &RTSym : RuntimeSymbols) {909if (Sym->hasName() && Sym->getName() == RTSym.first) {910if (*RTSym.second)911return make_error<StringError>(912"Duplicate " + RTSym.first +913" detected during MachOPlatform bootstrap",914inconvertibleErrorCode());915916if (Sym->getName() == *MP.MachOHeaderStartSymbol)917RegisterMachOHeader = true;918919*RTSym.second = Sym->getAddress();920}921}922}923924if (RegisterMachOHeader) {925// If this graph defines the macho header symbol then create the internal926// mapping between it and PlatformJD.927std::lock_guard<std::mutex> Lock(MP.PlatformMutex);928MP.JITDylibToHeaderAddr[&MP.PlatformJD] =929MP.Bootstrap.load()->MachOHeaderAddr;930MP.HeaderAddrToJITDylib[MP.Bootstrap.load()->MachOHeaderAddr] =931&MP.PlatformJD;932}933934return Error::success();935}936937Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd(938jitlink::LinkGraph &G) {939std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);940assert(MP.Bootstrap && "DeferredAAs reset before bootstrap completed");941--MP.Bootstrap.load()->ActiveGraphs;942// Notify Bootstrap->CV while holding the mutex because the mutex is943// also keeping Bootstrap->CV alive.944if (MP.Bootstrap.load()->ActiveGraphs == 0)945MP.Bootstrap.load()->CV.notify_all();946return Error::success();947}948949Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(950jitlink::LinkGraph &G, MaterializationResponsibility &MR) {951auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {952return Sym->getName() == *MP.MachOHeaderStartSymbol;953});954assert(I != G.defined_symbols().end() && "Missing MachO header start symbol");955956auto &JD = MR.getTargetJITDylib();957std::lock_guard<std::mutex> Lock(MP.PlatformMutex);958auto HeaderAddr = (*I)->getAddress();959MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;960MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;961// We can unconditionally add these actions to the Graph because this pass962// isn't used during bootstrap.963G.allocActions().push_back(964{cantFail(965WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>(966MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)),967cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(968MP.DeregisterJITDylib.Addr, HeaderAddr))});969return Error::success();970}971972Error MachOPlatform::MachOPlatformPlugin::preserveImportantSections(973jitlink::LinkGraph &G, MaterializationResponsibility &MR) {974// __objc_imageinfo is "important": we want to preserve it and record its975// address in the first graph that it appears in, then verify and discard it976// in all subsequent graphs. In this pass we preserve unconditionally -- we'll977// manually throw it away in the processObjCImageInfo pass.978if (auto *ObjCImageInfoSec =979G.findSectionByName(MachOObjCImageInfoSectionName)) {980if (ObjCImageInfoSec->blocks_size() != 1)981return make_error<StringError>(982"In " + G.getName() +983"__DATA,__objc_imageinfo contains multiple blocks",984inconvertibleErrorCode());985G.addAnonymousSymbol(**ObjCImageInfoSec->blocks().begin(), 0, 0, false,986true);987988for (auto *B : ObjCImageInfoSec->blocks())989if (!B->edges_empty())990return make_error<StringError>("In " + G.getName() + ", " +991MachOObjCImageInfoSectionName +992" contains references to symbols",993inconvertibleErrorCode());994}995996// Init sections are important: We need to preserve them and so that their997// addresses can be captured and reported to the ORC runtime in998// registerObjectPlatformSections.999JITLinkSymbolSet InitSectionSymbols;1000for (auto &InitSectionName : MachOInitSectionNames) {1001// Skip ObjCImageInfo -- this shouldn't have any dependencies, and we may1002// remove it later.1003if (InitSectionName == MachOObjCImageInfoSectionName)1004continue;10051006// Skip non-init sections.1007auto *InitSection = G.findSectionByName(InitSectionName);1008if (!InitSection)1009continue;10101011// Make a pass over live symbols in the section: those blocks are already1012// preserved.1013DenseSet<jitlink::Block *> AlreadyLiveBlocks;1014for (auto &Sym : InitSection->symbols()) {1015auto &B = Sym->getBlock();1016if (Sym->isLive() && Sym->getOffset() == 0 &&1017Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {1018InitSectionSymbols.insert(Sym);1019AlreadyLiveBlocks.insert(&B);1020}1021}10221023// Add anonymous symbols to preserve any not-already-preserved blocks.1024for (auto *B : InitSection->blocks())1025if (!AlreadyLiveBlocks.count(B))1026InitSectionSymbols.insert(1027&G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));1028}10291030if (!InitSectionSymbols.empty()) {1031std::lock_guard<std::mutex> Lock(PluginMutex);1032InitSymbolDeps[&MR] = std::move(InitSectionSymbols);1033}10341035return Error::success();1036}10371038Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(1039jitlink::LinkGraph &G, MaterializationResponsibility &MR) {10401041// If there's an ObjC imagine info then either1042// (1) It's the first __objc_imageinfo we've seen in this JITDylib. In1043// this case we name and record it.1044// OR1045// (2) We already have a recorded __objc_imageinfo for this JITDylib,1046// in which case we just verify it.1047auto *ObjCImageInfo = G.findSectionByName(MachOObjCImageInfoSectionName);1048if (!ObjCImageInfo)1049return Error::success();10501051auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();10521053// Check that the section is not empty if present.1054if (ObjCImageInfoBlocks.empty())1055return make_error<StringError>("Empty " + MachOObjCImageInfoSectionName +1056" section in " + G.getName(),1057inconvertibleErrorCode());10581059// Check that there's only one block in the section.1060if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())1061return make_error<StringError>("Multiple blocks in " +1062MachOObjCImageInfoSectionName +1063" section in " + G.getName(),1064inconvertibleErrorCode());10651066// Check that the __objc_imageinfo section is unreferenced.1067// FIXME: We could optimize this check if Symbols had a ref-count.1068for (auto &Sec : G.sections()) {1069if (&Sec != ObjCImageInfo)1070for (auto *B : Sec.blocks())1071for (auto &E : B->edges())1072if (E.getTarget().isDefined() &&1073&E.getTarget().getBlock().getSection() == ObjCImageInfo)1074return make_error<StringError>(MachOObjCImageInfoSectionName +1075" is referenced within file " +1076G.getName(),1077inconvertibleErrorCode());1078}10791080auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();1081auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();1082auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());1083auto Flags =1084support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());10851086// Lock the mutex while we verify / update the ObjCImageInfos map.1087std::lock_guard<std::mutex> Lock(PluginMutex);10881089auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());1090if (ObjCImageInfoItr != ObjCImageInfos.end()) {1091// We've already registered an __objc_imageinfo section. Verify the1092// content of this new section matches, then delete it.1093if (ObjCImageInfoItr->second.Version != Version)1094return make_error<StringError>(1095"ObjC version in " + G.getName() +1096" does not match first registered version",1097inconvertibleErrorCode());1098if (ObjCImageInfoItr->second.Flags != Flags)1099if (Error E = mergeImageInfoFlags(G, MR, ObjCImageInfoItr->second, Flags))1100return E;11011102// __objc_imageinfo is valid. Delete the block.1103for (auto *S : ObjCImageInfo->symbols())1104G.removeDefinedSymbol(*S);1105G.removeBlock(ObjCImageInfoBlock);1106} else {1107LLVM_DEBUG({1108dbgs() << "MachOPlatform: Registered __objc_imageinfo for "1109<< MR.getTargetJITDylib().getName() << " in " << G.getName()1110<< "; flags = " << formatv("{0:x4}", Flags) << "\n";1111});1112// We haven't registered an __objc_imageinfo section yet. Register and1113// move on. The section should already be marked no-dead-strip.1114G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName,1115ObjCImageInfoBlock.getSize(), jitlink::Linkage::Strong,1116jitlink::Scope::Hidden, false, true);1117if (auto Err = MR.defineMaterializing(1118{{MR.getExecutionSession().intern(ObjCImageInfoSymbolName),1119JITSymbolFlags()}}))1120return Err;1121ObjCImageInfos[&MR.getTargetJITDylib()] = {Version, Flags, false};1122}11231124return Error::success();1125}11261127Error MachOPlatform::MachOPlatformPlugin::mergeImageInfoFlags(1128jitlink::LinkGraph &G, MaterializationResponsibility &MR,1129ObjCImageInfo &Info, uint32_t NewFlags) {1130if (Info.Flags == NewFlags)1131return Error::success();11321133ObjCImageInfoFlags Old(Info.Flags);1134ObjCImageInfoFlags New(NewFlags);11351136// Check for incompatible flags.1137if (Old.SwiftABIVersion && New.SwiftABIVersion &&1138Old.SwiftABIVersion != New.SwiftABIVersion)1139return make_error<StringError>("Swift ABI version in " + G.getName() +1140" does not match first registered flags",1141inconvertibleErrorCode());11421143// HasCategoryClassProperties and HasSignedObjCClassROs can be disabled before1144// they are registered, if necessary, but once they are in use must be1145// supported by subsequent objects.1146if (Info.Finalized && Old.HasCategoryClassProperties &&1147!New.HasCategoryClassProperties)1148return make_error<StringError>("ObjC category class property support in " +1149G.getName() +1150" does not match first registered flags",1151inconvertibleErrorCode());1152if (Info.Finalized && Old.HasSignedObjCClassROs && !New.HasSignedObjCClassROs)1153return make_error<StringError>("ObjC class_ro_t pointer signing in " +1154G.getName() +1155" does not match first registered flags",1156inconvertibleErrorCode());11571158// If we cannot change the flags, ignore any remaining differences. Adding1159// Swift or changing its version are unlikely to cause problems in practice.1160if (Info.Finalized)1161return Error::success();11621163// Use the minimum Swift version.1164if (Old.SwiftVersion && New.SwiftVersion)1165New.SwiftVersion = std::min(Old.SwiftVersion, New.SwiftVersion);1166else if (Old.SwiftVersion)1167New.SwiftVersion = Old.SwiftVersion;1168// Add a Swift ABI version if it was pure objc before.1169if (!New.SwiftABIVersion)1170New.SwiftABIVersion = Old.SwiftABIVersion;1171// Disable class properties if any object does not support it.1172if (Old.HasCategoryClassProperties != New.HasCategoryClassProperties)1173New.HasCategoryClassProperties = false;1174// Disable signed class ro data if any object does not support it.1175if (Old.HasSignedObjCClassROs != New.HasSignedObjCClassROs)1176New.HasSignedObjCClassROs = false;11771178LLVM_DEBUG({1179dbgs() << "MachOPlatform: Merging __objc_imageinfo flags for "1180<< MR.getTargetJITDylib().getName() << " (was "1181<< formatv("{0:x4}", Old.rawFlags()) << ")"1182<< " with " << G.getName() << " (" << formatv("{0:x4}", NewFlags)1183<< ")"1184<< " -> " << formatv("{0:x4}", New.rawFlags()) << "\n";1185});11861187Info.Flags = New.rawFlags();1188return Error::success();1189}11901191Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(1192jitlink::LinkGraph &G, JITDylib &JD) {11931194// Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr.1195for (auto *Sym : G.external_symbols())1196if (Sym->getName() == "__tlv_bootstrap") {1197Sym->setName("___orc_rt_macho_tlv_get_addr");1198break;1199}12001201// Store key in __thread_vars struct fields.1202if (auto *ThreadDataSec = G.findSectionByName(MachOThreadVarsSectionName)) {1203std::optional<uint64_t> Key;1204{1205std::lock_guard<std::mutex> Lock(MP.PlatformMutex);1206auto I = MP.JITDylibToPThreadKey.find(&JD);1207if (I != MP.JITDylibToPThreadKey.end())1208Key = I->second;1209}12101211if (!Key) {1212if (auto KeyOrErr = MP.createPThreadKey())1213Key = *KeyOrErr;1214else1215return KeyOrErr.takeError();1216}12171218uint64_t PlatformKeyBits =1219support::endian::byte_swap(*Key, G.getEndianness());12201221for (auto *B : ThreadDataSec->blocks()) {1222if (B->getSize() != 3 * G.getPointerSize())1223return make_error<StringError>("__thread_vars block at " +1224formatv("{0:x}", B->getAddress()) +1225" has unexpected size",1226inconvertibleErrorCode());12271228auto NewBlockContent = G.allocateBuffer(B->getSize());1229llvm::copy(B->getContent(), NewBlockContent.data());1230memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits,1231G.getPointerSize());1232B->setContent(NewBlockContent);1233}1234}12351236// Transform any TLV edges into GOT edges.1237for (auto *B : G.blocks())1238for (auto &E : B->edges())1239if (E.getKind() ==1240jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable)1241E.setKind(jitlink::x86_64::1242RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);12431244return Error::success();1245}12461247std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections>1248MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(1249jitlink::LinkGraph &G) {1250using namespace jitlink;12511252UnwindSections US;12531254// ScanSection records a section range and adds any executable blocks that1255// that section points to to the CodeBlocks vector.1256SmallVector<Block *> CodeBlocks;1257auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) {1258if (Sec.blocks().empty())1259return;1260SecRange = (*Sec.blocks().begin())->getRange();1261for (auto *B : Sec.blocks()) {1262auto R = B->getRange();1263SecRange.Start = std::min(SecRange.Start, R.Start);1264SecRange.End = std::max(SecRange.End, R.End);1265for (auto &E : B->edges()) {1266if (!E.getTarget().isDefined())1267continue;1268auto &TargetBlock = E.getTarget().getBlock();1269auto &TargetSection = TargetBlock.getSection();1270if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)1271CodeBlocks.push_back(&TargetBlock);1272}1273}1274};12751276if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName))1277ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);12781279if (Section *CUInfoSec =1280G.findSectionByName(MachOCompactUnwindInfoSectionName))1281ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);12821283// If we didn't find any pointed-to code-blocks then there's no need to1284// register any info.1285if (CodeBlocks.empty())1286return std::nullopt;12871288// We have info to register. Sort the code blocks into address order and1289// build a list of contiguous address ranges covering them all.1290llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) {1291return LHS->getAddress() < RHS->getAddress();1292});1293for (auto *B : CodeBlocks) {1294if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress())1295US.CodeRanges.push_back(B->getRange());1296else1297US.CodeRanges.back().End = B->getRange().End;1298}12991300LLVM_DEBUG({1301dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n"1302<< " DWARF: ";1303if (US.DwarfSection.Start)1304dbgs() << US.DwarfSection << "\n";1305else1306dbgs() << "none\n";1307dbgs() << " Compact-unwind: ";1308if (US.CompactUnwindSection.Start)1309dbgs() << US.CompactUnwindSection << "\n";1310else1311dbgs() << "none\n"1312<< "for code ranges:\n";1313for (auto &CR : US.CodeRanges)1314dbgs() << " " << CR << "\n";1315if (US.CodeRanges.size() >= G.sections_size())1316dbgs() << "WARNING: High number of discontiguous code ranges! "1317"Padding may be interfering with coalescing.\n";1318});13191320return US;1321}13221323Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(1324jitlink::LinkGraph &G, JITDylib &JD, bool InBootstrapPhase) {13251326// Get a pointer to the thread data section if there is one. It will be used1327// below.1328jitlink::Section *ThreadDataSection =1329G.findSectionByName(MachOThreadDataSectionName);13301331// Handle thread BSS section if there is one.1332if (auto *ThreadBSSSection = G.findSectionByName(MachOThreadBSSSectionName)) {1333// If there's already a thread data section in this graph then merge the1334// thread BSS section content into it, otherwise just treat the thread1335// BSS section as the thread data section.1336if (ThreadDataSection)1337G.mergeSections(*ThreadDataSection, *ThreadBSSSection);1338else1339ThreadDataSection = ThreadBSSSection;1340}13411342SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs;13431344// Collect data sections to register.1345StringRef DataSections[] = {MachODataDataSectionName,1346MachODataCommonSectionName,1347MachOEHFrameSectionName};1348for (auto &SecName : DataSections) {1349if (auto *Sec = G.findSectionByName(SecName)) {1350jitlink::SectionRange R(*Sec);1351if (!R.empty())1352MachOPlatformSecs.push_back({SecName, R.getRange()});1353}1354}13551356// Having merged thread BSS (if present) and thread data (if present),1357// record the resulting section range.1358if (ThreadDataSection) {1359jitlink::SectionRange R(*ThreadDataSection);1360if (!R.empty())1361MachOPlatformSecs.push_back({MachOThreadDataSectionName, R.getRange()});1362}13631364// If any platform sections were found then add an allocation action to call1365// the registration function.1366StringRef PlatformSections[] = {MachOModInitFuncSectionName,1367ObjCRuntimeObjectSectionName};13681369for (auto &SecName : PlatformSections) {1370auto *Sec = G.findSectionByName(SecName);1371if (!Sec)1372continue;1373jitlink::SectionRange R(*Sec);1374if (R.empty())1375continue;13761377MachOPlatformSecs.push_back({SecName, R.getRange()});1378}13791380std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange,1381ExecutorAddrRange>>1382UnwindInfo;1383if (auto UI = findUnwindSectionInfo(G))1384UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection,1385UI->CompactUnwindSection);13861387if (!MachOPlatformSecs.empty() || UnwindInfo) {1388// Dump the scraped inits.1389LLVM_DEBUG({1390dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";1391for (auto &KV : MachOPlatformSecs)1392dbgs() << " " << KV.first << ": " << KV.second << "\n";1393});13941395using SPSRegisterObjectPlatformSectionsArgs = SPSArgList<1396SPSExecutorAddr,1397SPSOptional<SPSTuple<SPSSequence<SPSExecutorAddrRange>,1398SPSExecutorAddrRange, SPSExecutorAddrRange>>,1399SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;14001401shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase)1402? G.allocActions()1403: MP.Bootstrap.load()->DeferredAAs;14041405ExecutorAddr HeaderAddr;1406{1407std::lock_guard<std::mutex> Lock(MP.PlatformMutex);1408auto I = MP.JITDylibToHeaderAddr.find(&JD);1409assert(I != MP.JITDylibToHeaderAddr.end() &&1410"No header registered for JD");1411assert(I->second && "Null header registered for JD");1412HeaderAddr = I->second;1413}1414allocActions.push_back(1415{cantFail(1416WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(1417MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,1418MachOPlatformSecs)),1419cantFail(1420WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(1421MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,1422UnwindInfo, MachOPlatformSecs))});1423}14241425return Error::success();1426}14271428Error MachOPlatform::MachOPlatformPlugin::createObjCRuntimeObject(1429jitlink::LinkGraph &G) {14301431bool NeedTextSegment = false;1432size_t NumRuntimeSections = 0;14331434for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData)1435if (G.findSectionByName(ObjCRuntimeSectionName))1436++NumRuntimeSections;14371438for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {1439if (G.findSectionByName(ObjCRuntimeSectionName)) {1440++NumRuntimeSections;1441NeedTextSegment = true;1442}1443}14441445// Early out for no runtime sections.1446if (NumRuntimeSections == 0)1447return Error::success();14481449// If there were any runtime sections then we need to add an __objc_imageinfo1450// section.1451++NumRuntimeSections;14521453size_t MachOSize = sizeof(MachO::mach_header_64) +1454(NeedTextSegment + 1) * sizeof(MachO::segment_command_64) +1455NumRuntimeSections * sizeof(MachO::section_64);14561457auto &Sec = G.createSection(ObjCRuntimeObjectSectionName,1458MemProt::Read | MemProt::Write);1459G.createMutableContentBlock(Sec, MachOSize, ExecutorAddr(), 16, 0, true);14601461return Error::success();1462}14631464Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(1465jitlink::LinkGraph &G, MaterializationResponsibility &MR) {14661467auto *ObjCRuntimeObjectSec =1468G.findSectionByName(ObjCRuntimeObjectSectionName);14691470if (!ObjCRuntimeObjectSec)1471return Error::success();14721473switch (G.getTargetTriple().getArch()) {1474case Triple::aarch64:1475case Triple::x86_64:1476// Supported.1477break;1478default:1479return make_error<StringError>("Unrecognized MachO arch in triple " +1480G.getTargetTriple().str(),1481inconvertibleErrorCode());1482}14831484auto &SecBlock = **ObjCRuntimeObjectSec->blocks().begin();14851486struct SecDesc {1487MachO::section_64 Sec;1488unique_function<void(size_t RecordOffset)> AddFixups;1489};14901491std::vector<SecDesc> TextSections, DataSections;1492auto AddSection = [&](SecDesc &SD, jitlink::Section &GraphSec) {1493jitlink::SectionRange SR(GraphSec);1494StringRef FQName = GraphSec.getName();1495memset(&SD.Sec, 0, sizeof(MachO::section_64));1496memcpy(SD.Sec.sectname, FQName.drop_front(7).data(), FQName.size() - 7);1497memcpy(SD.Sec.segname, FQName.data(), 6);1498SD.Sec.addr = SR.getStart() - SecBlock.getAddress();1499SD.Sec.size = SR.getSize();1500SD.Sec.flags = MachO::S_REGULAR;1501};15021503// Add the __objc_imageinfo section.1504{1505DataSections.push_back({});1506auto &SD = DataSections.back();1507memset(&SD.Sec, 0, sizeof(SD.Sec));1508memcpy(SD.Sec.sectname, "__objc_imageinfo", 16);1509strcpy(SD.Sec.segname, "__DATA");1510SD.Sec.size = 8;1511SD.AddFixups = [&](size_t RecordOffset) {1512auto PointerEdge = getPointerEdgeKind(G);15131514// Look for an existing __objc_imageinfo symbol.1515jitlink::Symbol *ObjCImageInfoSym = nullptr;1516for (auto *Sym : G.external_symbols())1517if (Sym->getName() == ObjCImageInfoSymbolName) {1518ObjCImageInfoSym = Sym;1519break;1520}1521if (!ObjCImageInfoSym)1522for (auto *Sym : G.absolute_symbols())1523if (Sym->getName() == ObjCImageInfoSymbolName) {1524ObjCImageInfoSym = Sym;1525break;1526}1527if (!ObjCImageInfoSym)1528for (auto *Sym : G.defined_symbols())1529if (Sym->hasName() && Sym->getName() == ObjCImageInfoSymbolName) {1530ObjCImageInfoSym = Sym;1531std::optional<uint32_t> Flags;1532{1533std::lock_guard<std::mutex> Lock(PluginMutex);1534auto It = ObjCImageInfos.find(&MR.getTargetJITDylib());1535if (It != ObjCImageInfos.end()) {1536It->second.Finalized = true;1537Flags = It->second.Flags;1538}1539}15401541if (Flags) {1542// We own the definition of __objc_image_info; write the final1543// merged flags value.1544auto Content = Sym->getBlock().getMutableContent(G);1545assert(Content.size() == 8 &&1546"__objc_image_info size should have been verified already");1547support::endian::write32(&Content[4], *Flags, G.getEndianness());1548}1549break;1550}1551if (!ObjCImageInfoSym)1552ObjCImageInfoSym =1553&G.addExternalSymbol(ObjCImageInfoSymbolName, 8, false);15541555SecBlock.addEdge(PointerEdge,1556RecordOffset + ((char *)&SD.Sec.addr - (char *)&SD.Sec),1557*ObjCImageInfoSym, -SecBlock.getAddress().getValue());1558};1559}15601561for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) {1562if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) {1563DataSections.push_back({});1564AddSection(DataSections.back(), *GraphSec);1565}1566}15671568for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {1569if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) {1570TextSections.push_back({});1571AddSection(TextSections.back(), *GraphSec);1572}1573}15741575assert(ObjCRuntimeObjectSec->blocks_size() == 1 &&1576"Unexpected number of blocks in runtime sections object");15771578// Build the header struct up-front. This also gives us a chance to check1579// that the triple is supported, which we'll assume below.1580MachO::mach_header_64 Hdr;1581Hdr.magic = MachO::MH_MAGIC_64;1582switch (G.getTargetTriple().getArch()) {1583case Triple::aarch64:1584Hdr.cputype = MachO::CPU_TYPE_ARM64;1585Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;1586break;1587case Triple::x86_64:1588Hdr.cputype = MachO::CPU_TYPE_X86_64;1589Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;1590break;1591default:1592llvm_unreachable("Unsupported architecture");1593}15941595Hdr.filetype = MachO::MH_DYLIB;1596Hdr.ncmds = 1 + !TextSections.empty();1597Hdr.sizeofcmds =1598Hdr.ncmds * sizeof(MachO::segment_command_64) +1599(TextSections.size() + DataSections.size()) * sizeof(MachO::section_64);1600Hdr.flags = 0;1601Hdr.reserved = 0;16021603auto SecContent = SecBlock.getAlreadyMutableContent();1604char *P = SecContent.data();1605auto WriteMachOStruct = [&](auto S) {1606if (G.getEndianness() != llvm::endianness::native)1607MachO::swapStruct(S);1608memcpy(P, &S, sizeof(S));1609P += sizeof(S);1610};16111612auto WriteSegment = [&](StringRef Name, std::vector<SecDesc> &Secs) {1613MachO::segment_command_64 SegLC;1614memset(&SegLC, 0, sizeof(SegLC));1615memcpy(SegLC.segname, Name.data(), Name.size());1616SegLC.cmd = MachO::LC_SEGMENT_64;1617SegLC.cmdsize = sizeof(MachO::segment_command_64) +1618Secs.size() * sizeof(MachO::section_64);1619SegLC.nsects = Secs.size();1620WriteMachOStruct(SegLC);1621for (auto &SD : Secs) {1622if (SD.AddFixups)1623SD.AddFixups(P - SecContent.data());1624WriteMachOStruct(SD.Sec);1625}1626};16271628WriteMachOStruct(Hdr);1629if (!TextSections.empty())1630WriteSegment("__TEXT", TextSections);1631if (!DataSections.empty())1632WriteSegment("__DATA", DataSections);16331634assert(P == SecContent.end() && "Underflow writing ObjC runtime object");1635return Error::success();1636}16371638Error MachOPlatform::MachOPlatformPlugin::prepareSymbolTableRegistration(1639jitlink::LinkGraph &G, JITSymTabVector &JITSymTabInfo) {16401641auto *CStringSec = G.findSectionByName(MachOCStringSectionName);1642if (!CStringSec)1643CStringSec = &G.createSection(MachOCStringSectionName,1644MemProt::Read | MemProt::Exec);16451646// Make a map of existing strings so that we can re-use them:1647DenseMap<StringRef, jitlink::Symbol *> ExistingStrings;1648for (auto *Sym : CStringSec->symbols()) {16491650// The LinkGraph builder should have created single strings blocks, and all1651// plugins should have maintained this invariant.1652auto Content = Sym->getBlock().getContent();1653ExistingStrings.insert(1654std::make_pair(StringRef(Content.data(), Content.size()), Sym));1655}16561657// Add all symbol names to the string section, and record the symbols for1658// those names.1659{1660SmallVector<jitlink::Symbol *> SymsToProcess;1661for (auto *Sym : G.defined_symbols())1662SymsToProcess.push_back(Sym);1663for (auto *Sym : G.absolute_symbols())1664SymsToProcess.push_back(Sym);16651666for (auto *Sym : SymsToProcess) {1667if (!Sym->hasName())1668continue;16691670auto I = ExistingStrings.find(Sym->getName());1671if (I == ExistingStrings.end()) {1672auto &NameBlock = G.createMutableContentBlock(1673*CStringSec, G.allocateCString(Sym->getName()), orc::ExecutorAddr(),16741, 0);1675auto &SymbolNameSym = G.addAnonymousSymbol(1676NameBlock, 0, NameBlock.getSize(), false, true);1677JITSymTabInfo.push_back({Sym, &SymbolNameSym});1678} else1679JITSymTabInfo.push_back({Sym, I->second});1680}1681}16821683return Error::success();1684}16851686Error MachOPlatform::MachOPlatformPlugin::addSymbolTableRegistration(1687jitlink::LinkGraph &G, MaterializationResponsibility &MR,1688JITSymTabVector &JITSymTabInfo, bool InBootstrapPhase) {16891690ExecutorAddr HeaderAddr;1691{1692std::lock_guard<std::mutex> Lock(MP.PlatformMutex);1693auto I = MP.JITDylibToHeaderAddr.find(&MR.getTargetJITDylib());1694assert(I != MP.JITDylibToHeaderAddr.end() && "No header registered for JD");1695assert(I->second && "Null header registered for JD");1696HeaderAddr = I->second;1697}16981699SymbolTableVector LocalSymTab;1700auto &SymTab = LLVM_LIKELY(!InBootstrapPhase) ? LocalSymTab1701: MP.Bootstrap.load()->SymTab;1702for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo)1703SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(),1704flagsForSymbol(*OriginalSymbol)});17051706// Bail out if we're in the bootstrap phase -- registration of thees symbols1707// will be attached to the bootstrap graph.1708if (LLVM_UNLIKELY(InBootstrapPhase))1709return Error::success();17101711shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase)1712? G.allocActions()1713: MP.Bootstrap.load()->DeferredAAs;1714allocActions.push_back(1715{cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>(1716MP.RegisterObjectSymbolTable.Addr, HeaderAddr, SymTab)),1717cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>(1718MP.DeregisterObjectSymbolTable.Addr, HeaderAddr, SymTab))});17191720return Error::success();1721}17221723template <typename MachOTraits>1724jitlink::Block &createHeaderBlock(MachOPlatform &MOP,1725const MachOPlatform::HeaderOptions &Opts,1726JITDylib &JD, jitlink::LinkGraph &G,1727jitlink::Section &HeaderSection) {1728auto HdrInfo =1729getMachOHeaderInfoFromTriple(MOP.getExecutionSession().getTargetTriple());1730MachOBuilder<MachOTraits> B(HdrInfo.PageSize);17311732B.Header.filetype = MachO::MH_DYLIB;1733B.Header.cputype = HdrInfo.CPUType;1734B.Header.cpusubtype = HdrInfo.CPUSubType;17351736if (Opts.IDDylib)1737B.template addLoadCommand<MachO::LC_ID_DYLIB>(1738Opts.IDDylib->Name, Opts.IDDylib->Timestamp,1739Opts.IDDylib->CurrentVersion, Opts.IDDylib->CompatibilityVersion);1740else1741B.template addLoadCommand<MachO::LC_ID_DYLIB>(JD.getName(), 0, 0, 0);17421743for (auto &BV : Opts.BuildVersions)1744B.template addLoadCommand<MachO::LC_BUILD_VERSION>(1745BV.Platform, BV.MinOS, BV.SDK, static_cast<uint32_t>(0));1746for (auto &D : Opts.LoadDylibs)1747B.template addLoadCommand<MachO::LC_LOAD_DYLIB>(1748D.Name, D.Timestamp, D.CurrentVersion, D.CompatibilityVersion);1749for (auto &P : Opts.RPaths)1750B.template addLoadCommand<MachO::LC_RPATH>(P);17511752auto HeaderContent = G.allocateBuffer(B.layout());1753B.write(HeaderContent);17541755return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,17560);1757}17581759SimpleMachOHeaderMU::SimpleMachOHeaderMU(MachOPlatform &MOP,1760SymbolStringPtr HeaderStartSymbol,1761MachOPlatform::HeaderOptions Opts)1762: MaterializationUnit(1763createHeaderInterface(MOP, std::move(HeaderStartSymbol))),1764MOP(MOP), Opts(std::move(Opts)) {}17651766void SimpleMachOHeaderMU::materialize(1767std::unique_ptr<MaterializationResponsibility> R) {1768auto G = createPlatformGraph(MOP, "<MachOHeaderMU>");1769addMachOHeader(R->getTargetJITDylib(), *G, R->getInitializerSymbol());1770MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));1771}17721773void SimpleMachOHeaderMU::discard(const JITDylib &JD,1774const SymbolStringPtr &Sym) {}17751776void SimpleMachOHeaderMU::addMachOHeader(1777JITDylib &JD, jitlink::LinkGraph &G,1778const SymbolStringPtr &InitializerSymbol) {1779auto &HeaderSection = G.createSection("__header", MemProt::Read);1780auto &HeaderBlock = createHeaderBlock(JD, G, HeaderSection);17811782// Init symbol is header-start symbol.1783G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol, HeaderBlock.getSize(),1784jitlink::Linkage::Strong, jitlink::Scope::Default, false,1785true);1786for (auto &HS : AdditionalHeaderSymbols)1787G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(),1788jitlink::Linkage::Strong, jitlink::Scope::Default, false,1789true);1790}17911792jitlink::Block &1793SimpleMachOHeaderMU::createHeaderBlock(JITDylib &JD, jitlink::LinkGraph &G,1794jitlink::Section &HeaderSection) {1795switch (MOP.getExecutionSession().getTargetTriple().getArch()) {1796case Triple::aarch64:1797case Triple::x86_64:1798return ::createHeaderBlock<MachO64LE>(MOP, Opts, JD, G, HeaderSection);1799default:1800llvm_unreachable("Unsupported architecture");1801}1802}18031804MaterializationUnit::Interface SimpleMachOHeaderMU::createHeaderInterface(1805MachOPlatform &MOP, const SymbolStringPtr &HeaderStartSymbol) {1806SymbolFlagsMap HeaderSymbolFlags;18071808HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;1809for (auto &HS : AdditionalHeaderSymbols)1810HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =1811JITSymbolFlags::Exported;18121813return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),1814HeaderStartSymbol);1815}18161817MachOHeaderInfo getMachOHeaderInfoFromTriple(const Triple &TT) {1818switch (TT.getArch()) {1819case Triple::aarch64:1820return {/* PageSize = */ 16 * 1024,1821/* CPUType = */ MachO::CPU_TYPE_ARM64,1822/* CPUSubType = */ MachO::CPU_SUBTYPE_ARM64_ALL};1823case Triple::x86_64:1824return {/* PageSize = */ 4 * 1024,1825/* CPUType = */ MachO::CPU_TYPE_X86_64,1826/* CPUSubType = */ MachO::CPU_SUBTYPE_X86_64_ALL};1827default:1828llvm_unreachable("Unrecognized architecture");1829}1830}18311832} // End namespace orc.1833} // End namespace llvm.183418351836