aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp615
1 files changed, 440 insertions, 175 deletions
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index a3a766d602c1..9057300bf043 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -15,6 +15,7 @@
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/ExecutionEngine/Orc/MachOBuilder.h"
#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Debug.h"
@@ -34,6 +35,8 @@ using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>;
using SPSMachOJITDylibDepInfoMap =
SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>;
+class SPSMachOExecutorSymbolFlags;
+
template <>
class SPSSerializationTraits<SPSMachOJITDylibDepInfo,
MachOPlatform::MachOJITDylibDepInfo> {
@@ -55,23 +58,54 @@ public:
}
};
+template <>
+class SPSSerializationTraits<SPSMachOExecutorSymbolFlags,
+ MachOPlatform::MachOExecutorSymbolFlags> {
+private:
+ using UT = std::underlying_type_t<MachOPlatform::MachOExecutorSymbolFlags>;
+
+public:
+ static size_t size(const MachOPlatform::MachOExecutorSymbolFlags &SF) {
+ return sizeof(UT);
+ }
+
+ static bool serialize(SPSOutputBuffer &OB,
+ const MachOPlatform::MachOExecutorSymbolFlags &SF) {
+ return SPSArgList<UT>::serialize(OB, static_cast<UT>(SF));
+ }
+
+ static bool deserialize(SPSInputBuffer &IB,
+ MachOPlatform::MachOExecutorSymbolFlags &SF) {
+ UT Tmp;
+ if (!SPSArgList<UT>::deserialize(IB, Tmp))
+ return false;
+ SF = static_cast<MachOPlatform::MachOExecutorSymbolFlags>(Tmp);
+ return true;
+ }
+};
+
} // namespace shared
} // namespace orc
} // namespace llvm
namespace {
+using SPSRegisterSymbolsArgs =
+ SPSArgList<SPSExecutorAddr,
+ SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr,
+ SPSMachOExecutorSymbolFlags>>>;
+
std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP,
std::string Name) {
unsigned PointerSize;
- support::endianness Endianness;
+ llvm::endianness Endianness;
const auto &TT = MOP.getExecutionSession().getTargetTriple();
switch (TT.getArch()) {
case Triple::aarch64:
case Triple::x86_64:
PointerSize = 8;
- Endianness = support::endianness::little;
+ Endianness = llvm::endianness::little;
break;
default:
llvm_unreachable("Unrecognized architecture");
@@ -82,119 +116,32 @@ std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP,
jitlink::getGenericEdgeKindName);
}
-// Generates a MachO header.
-class MachOHeaderMaterializationUnit : public MaterializationUnit {
-public:
- MachOHeaderMaterializationUnit(MachOPlatform &MOP,
- const SymbolStringPtr &HeaderStartSymbol)
- : MaterializationUnit(createHeaderInterface(MOP, HeaderStartSymbol)),
- MOP(MOP) {}
-
- StringRef getName() const override { return "MachOHeaderMU"; }
-
- void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
- auto G = createPlatformGraph(MOP, "<MachOHeaderMU>");
- addMachOHeader(*G, MOP, R->getInitializerSymbol());
- MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
- }
-
- void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
-
- static void addMachOHeader(jitlink::LinkGraph &G, MachOPlatform &MOP,
- const SymbolStringPtr &InitializerSymbol) {
- auto &HeaderSection = G.createSection("__header", MemProt::Read);
- auto &HeaderBlock = createHeaderBlock(G, HeaderSection);
-
- // Init symbol is header-start symbol.
- G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol,
- HeaderBlock.getSize(), jitlink::Linkage::Strong,
- jitlink::Scope::Default, false, true);
- for (auto &HS : AdditionalHeaderSymbols)
- G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(),
- jitlink::Linkage::Strong, jitlink::Scope::Default,
- false, true);
- }
-
-private:
- struct HeaderSymbol {
- const char *Name;
- uint64_t Offset;
- };
-
- static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
- {"___mh_executable_header", 0}};
-
- static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
- jitlink::Section &HeaderSection) {
- MachO::mach_header_64 Hdr;
- Hdr.magic = MachO::MH_MAGIC_64;
- switch (G.getTargetTriple().getArch()) {
- case Triple::aarch64:
- Hdr.cputype = MachO::CPU_TYPE_ARM64;
- Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
- break;
- case Triple::x86_64:
- Hdr.cputype = MachO::CPU_TYPE_X86_64;
- Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
- break;
- default:
- llvm_unreachable("Unrecognized architecture");
- }
- Hdr.filetype = MachO::MH_DYLIB; // Custom file type?
- Hdr.ncmds = 0;
- Hdr.sizeofcmds = 0;
- Hdr.flags = 0;
- Hdr.reserved = 0;
-
- if (G.getEndianness() != support::endian::system_endianness())
- MachO::swapStruct(Hdr);
-
- auto HeaderContent = G.allocateContent(
- ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
-
- return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
- 0);
- }
-
- static MaterializationUnit::Interface
- createHeaderInterface(MachOPlatform &MOP,
- const SymbolStringPtr &HeaderStartSymbol) {
- SymbolFlagsMap HeaderSymbolFlags;
-
- HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
- for (auto &HS : AdditionalHeaderSymbols)
- HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =
- JITSymbolFlags::Exported;
-
- return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
- HeaderStartSymbol);
- }
-
- MachOPlatform &MOP;
-};
-
-constexpr MachOHeaderMaterializationUnit::HeaderSymbol
- MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[];
-
// Creates a Bootstrap-Complete LinkGraph to run deferred actions.
class MachOPlatformCompleteBootstrapMaterializationUnit
: public MaterializationUnit {
public:
+ using SymbolTableVector =
+ SmallVector<std::tuple<ExecutorAddr, ExecutorAddr,
+ MachOPlatform::MachOExecutorSymbolFlags>>;
+
MachOPlatformCompleteBootstrapMaterializationUnit(
MachOPlatform &MOP, StringRef PlatformJDName,
- SymbolStringPtr CompleteBootstrapSymbol, shared::AllocActions DeferredAAs,
+ SymbolStringPtr CompleteBootstrapSymbol, SymbolTableVector SymTab,
+ shared::AllocActions DeferredAAs, ExecutorAddr MachOHeaderAddr,
ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown,
ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib,
- ExecutorAddr MachOHeaderAddr)
+ ExecutorAddr RegisterObjectSymbolTable,
+ ExecutorAddr DeregisterObjectSymbolTable)
: MaterializationUnit(
{{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}),
MOP(MOP), PlatformJDName(PlatformJDName),
CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),
- DeferredAAs(std::move(DeferredAAs)),
- PlatformBootstrap(PlatformBootstrap),
+ SymTab(std::move(SymTab)), DeferredAAs(std::move(DeferredAAs)),
+ MachOHeaderAddr(MachOHeaderAddr), PlatformBootstrap(PlatformBootstrap),
PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),
DeregisterJITDylib(DeregisterJITDylib),
- MachOHeaderAddr(MachOHeaderAddr) {}
+ RegisterObjectSymbolTable(RegisterObjectSymbolTable),
+ DeregisterObjectSymbolTable(DeregisterObjectSymbolTable) {}
StringRef getName() const override {
return "MachOPlatformCompleteBootstrap";
@@ -211,7 +158,7 @@ public:
Linkage::Strong, Scope::Hidden, false, true);
// Reserve space for the stolen actions, plus two extras.
- G->allocActions().reserve(DeferredAAs.size() + 2);
+ G->allocActions().reserve(DeferredAAs.size() + 3);
// 1. Bootstrap the platform support code.
G->allocActions().push_back(
@@ -227,7 +174,14 @@ public:
cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
DeregisterJITDylib, MachOHeaderAddr))});
- // 3. Add the deferred actions to the graph.
+ // 3. Register deferred symbols.
+ G->allocActions().push_back(
+ {cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>(
+ RegisterObjectSymbolTable, MachOHeaderAddr, SymTab)),
+ cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>(
+ DeregisterObjectSymbolTable, MachOHeaderAddr, SymTab))});
+
+ // 4. Add the deferred actions to the graph.
std::move(DeferredAAs.begin(), DeferredAAs.end(),
std::back_inserter(G->allocActions()));
@@ -240,12 +194,15 @@ private:
MachOPlatform &MOP;
StringRef PlatformJDName;
SymbolStringPtr CompleteBootstrapSymbol;
+ SymbolTableVector SymTab;
shared::AllocActions DeferredAAs;
+ ExecutorAddr MachOHeaderAddr;
ExecutorAddr PlatformBootstrap;
ExecutorAddr PlatformShutdown;
ExecutorAddr RegisterJITDylib;
ExecutorAddr DeregisterJITDylib;
- ExecutorAddr MachOHeaderAddr;
+ ExecutorAddr RegisterObjectSymbolTable;
+ ExecutorAddr DeregisterObjectSymbolTable;
};
static StringRef ObjCRuntimeObjectSectionsData[] = {
@@ -266,6 +223,33 @@ static StringRef ObjCRuntimeObjectSectionName =
static StringRef ObjCImageInfoSymbolName =
"__llvm_jitlink_macho_objc_imageinfo";
+struct ObjCImageInfoFlags {
+ uint16_t SwiftABIVersion;
+ uint16_t SwiftVersion;
+ bool HasCategoryClassProperties;
+ bool HasSignedObjCClassROs;
+
+ static constexpr uint32_t SIGNED_CLASS_RO = (1 << 4);
+ static constexpr uint32_t HAS_CATEGORY_CLASS_PROPERTIES = (1 << 6);
+
+ explicit ObjCImageInfoFlags(uint32_t RawFlags) {
+ HasSignedObjCClassROs = RawFlags & SIGNED_CLASS_RO;
+ HasCategoryClassProperties = RawFlags & HAS_CATEGORY_CLASS_PROPERTIES;
+ SwiftABIVersion = (RawFlags >> 8) & 0xFF;
+ SwiftVersion = (RawFlags >> 16) & 0xFFFF;
+ }
+
+ uint32_t rawFlags() const {
+ uint32_t Result = 0;
+ if (HasCategoryClassProperties)
+ Result |= HAS_CATEGORY_CLASS_PROPERTIES;
+ if (HasSignedObjCClassROs)
+ Result |= SIGNED_CLASS_RO;
+ Result |= (SwiftABIVersion << 8);
+ Result |= (SwiftVersion << 16);
+ return Result;
+ }
+};
} // end anonymous namespace
namespace llvm {
@@ -275,6 +259,7 @@ Expected<std::unique_ptr<MachOPlatform>>
MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
JITDylib &PlatformJD,
std::unique_ptr<DefinitionGenerator> OrcRuntime,
+ MachOHeaderMUBuilder BuildMachOHeaderMU,
std::optional<SymbolAliasMap> RuntimeAliases) {
// If the target is not supported then bail out immediately.
@@ -305,8 +290,9 @@ MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
// Create the instance.
Error Err = Error::success();
- auto P = std::unique_ptr<MachOPlatform>(new MachOPlatform(
- ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), Err));
+ auto P = std::unique_ptr<MachOPlatform>(
+ new MachOPlatform(ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime),
+ std::move(BuildMachOHeaderMU), Err));
if (Err)
return std::move(Err);
return std::move(P);
@@ -315,6 +301,7 @@ MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
Expected<std::unique_ptr<MachOPlatform>>
MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
JITDylib &PlatformJD, const char *OrcRuntimePath,
+ MachOHeaderMUBuilder BuildMachOHeaderMU,
std::optional<SymbolAliasMap> RuntimeAliases) {
// Create a generator for the ORC runtime archive.
@@ -325,12 +312,11 @@ MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
return Create(ES, ObjLinkingLayer, PlatformJD,
std::move(*OrcRuntimeArchiveGenerator),
- std::move(RuntimeAliases));
+ std::move(BuildMachOHeaderMU), std::move(RuntimeAliases));
}
Error MachOPlatform::setupJITDylib(JITDylib &JD) {
- if (auto Err = JD.define(std::make_unique<MachOHeaderMaterializationUnit>(
- *this, MachOHeaderStartSymbol)))
+ if (auto Err = JD.define(BuildMachOHeaderMU(*this)))
return Err;
return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();
@@ -419,11 +405,36 @@ bool MachOPlatform::supportedTarget(const Triple &TT) {
}
}
+jitlink::Edge::Kind MachOPlatform::getPointerEdgeKind(jitlink::LinkGraph &G) {
+ switch (G.getTargetTriple().getArch()) {
+ case Triple::aarch64:
+ return jitlink::aarch64::Pointer64;
+ case Triple::x86_64:
+ return jitlink::x86_64::Pointer64;
+ default:
+ llvm_unreachable("Unsupported architecture");
+ }
+}
+
+MachOPlatform::MachOExecutorSymbolFlags
+MachOPlatform::flagsForSymbol(jitlink::Symbol &Sym) {
+ MachOPlatform::MachOExecutorSymbolFlags Flags{};
+ if (Sym.getLinkage() == jitlink::Linkage::Weak)
+ Flags |= MachOExecutorSymbolFlags::Weak;
+
+ if (Sym.isCallable())
+ Flags |= MachOExecutorSymbolFlags::Callable;
+
+ return Flags;
+}
+
MachOPlatform::MachOPlatform(
ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
JITDylib &PlatformJD,
- std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
- : ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer) {
+ std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
+ MachOHeaderMUBuilder BuildMachOHeaderMU, Error &Err)
+ : ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer),
+ BuildMachOHeaderMU(std::move(BuildMachOHeaderMU)) {
ErrorAsOutParameter _(&Err);
ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));
PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
@@ -442,11 +453,11 @@ MachOPlatform::MachOPlatform(
// itself (to build the allocation actions that will call the registration
// functions). Further complicating the situation (a) the graph containing
// the registration functions is allowed to depend on other graphs (e.g. the
- // graph containing the ORC runtime RTTI support) so we need to handle with
- // an unknown set of dependencies during bootstrap, and (b) these graphs may
+ // graph containing the ORC runtime RTTI support) so we need to handle an
+ // unknown set of dependencies during bootstrap, and (b) these graphs may
// be linked concurrently if the user has installed a concurrent dispatcher.
//
- // We satisfy these constraint by implementing a bootstrap phase during which
+ // We satisfy these constraints by implementing a bootstrap phase during which
// allocation actions generated by MachOPlatform are appended to a list of
// deferred allocation actions, rather than to the graphs themselves. At the
// end of the bootstrap process the deferred actions are attached to a final
@@ -486,8 +497,7 @@ MachOPlatform::MachOPlatform(
// the support methods callable. The bootstrap is now complete.
// Step (1) Add header materialization unit and request.
- if ((Err = PlatformJD.define(std::make_unique<MachOHeaderMaterializationUnit>(
- *this, MachOHeaderStartSymbol))))
+ if ((Err = PlatformJD.define(this->BuildMachOHeaderMU(*this))))
return;
if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))
return;
@@ -498,6 +508,8 @@ MachOPlatform::MachOPlatform(
SymbolLookupSet(
{PlatformBootstrap.Name, PlatformShutdown.Name,
RegisterJITDylib.Name, DeregisterJITDylib.Name,
+ RegisterObjectSymbolTable.Name,
+ DeregisterObjectSymbolTable.Name,
RegisterObjectPlatformSections.Name,
DeregisterObjectPlatformSections.Name,
CreatePThreadKey.Name}))
@@ -516,9 +528,11 @@ MachOPlatform::MachOPlatform(
if ((Err = PlatformJD.define(
std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>(
*this, PlatformJD.getName(), BootstrapCompleteSymbol,
- std::move(BI.DeferredAAs), PlatformBootstrap.Addr,
+ std::move(BI.SymTab), std::move(BI.DeferredAAs),
+ BI.MachOHeaderAddr, PlatformBootstrap.Addr,
PlatformShutdown.Addr, RegisterJITDylib.Addr,
- DeregisterJITDylib.Addr, BI.MachOHeaderAddr))))
+ DeregisterJITDylib.Addr, RegisterObjectSymbolTable.Addr,
+ DeregisterObjectSymbolTable.Addr))))
return;
if ((Err = ES.lookup(makeJITDylibSearchOrder(
&PlatformJD, JITDylibLookupFlags::MatchAllSymbols),
@@ -540,11 +554,11 @@ Error MachOPlatform::associateRuntimeSupportFunctions() {
ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
this, &MachOPlatform::rt_pushInitializers);
- using LookupSymbolSPSSig =
- SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
- WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] =
- ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
- &MachOPlatform::rt_lookupSymbol);
+ using PushSymbolsSPSSig =
+ SPSError(SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>);
+ WFs[ES.intern("___orc_rt_macho_push_symbols_tag")] =
+ ES.wrapAsyncWithSPS<PushSymbolsSPSSig>(this,
+ &MachOPlatform::rt_pushSymbols);
return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
}
@@ -665,11 +679,9 @@ void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
pushInitializersLoop(std::move(SendResult), JD);
}
-void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
- ExecutorAddr Handle, StringRef SymbolName) {
- LLVM_DEBUG({
- dbgs() << "MachOPlatform::rt_lookupSymbol(\"" << Handle << "\")\n";
- });
+void MachOPlatform::rt_pushSymbols(
+ PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle,
+ const std::vector<std::pair<StringRef, bool>> &SymbolNames) {
JITDylib *JD = nullptr;
@@ -679,39 +691,37 @@ void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
if (I != HeaderAddrToJITDylib.end())
JD = I->second;
}
+ LLVM_DEBUG({
+ dbgs() << "MachOPlatform::rt_pushSymbols(";
+ if (JD)
+ dbgs() << "\"" << JD->getName() << "\", [ ";
+ else
+ dbgs() << "<invalid handle " << Handle << ">, [ ";
+ for (auto &Name : SymbolNames)
+ dbgs() << "\"" << Name.first << "\" ";
+ dbgs() << "])\n";
+ });
if (!JD) {
- LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n");
SendResult(make_error<StringError>("No JITDylib associated with handle " +
formatv("{0:x}", Handle),
inconvertibleErrorCode()));
return;
}
- // Use functor class to work around XL build compiler issue on AIX.
- class RtLookupNotifyComplete {
- public:
- RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
- : SendResult(std::move(SendResult)) {}
- void operator()(Expected<SymbolMap> Result) {
- if (Result) {
- assert(Result->size() == 1 && "Unexpected result map count");
- SendResult(Result->begin()->second.getAddress());
- } else {
- SendResult(Result.takeError());
- }
- }
-
- private:
- SendSymbolAddressFn SendResult;
- };
+ SymbolLookupSet LS;
+ for (auto &[Name, Required] : SymbolNames)
+ LS.add(ES.intern(Name), Required
+ ? SymbolLookupFlags::RequiredSymbol
+ : SymbolLookupFlags::WeaklyReferencedSymbol);
- // FIXME: Proper mangling.
- auto MangledName = ("_" + SymbolName).str();
ES.lookup(
LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
- SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready,
- RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
+ std::move(LS), SymbolState::Ready,
+ [SendResult = std::move(SendResult)](Expected<SymbolMap> Result) mutable {
+ SendResult(Result.takeError());
+ },
+ NoDependenciesToRegister);
}
Expected<uint64_t> MachOPlatform::createPThreadKey() {
@@ -781,6 +791,18 @@ void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
return fixTLVSectionsAndEdges(G, JD);
});
+ // Add symbol table prepare and register passes: These will add strings for
+ // all symbols to the c-strings section, and build a symbol table registration
+ // call.
+ auto JITSymTabInfo = std::make_shared<JITSymTabVector>();
+ Config.PostPrunePasses.push_back([this, JITSymTabInfo](LinkGraph &G) {
+ return prepareSymbolTableRegistration(G, *JITSymTabInfo);
+ });
+ Config.PostFixupPasses.push_back([this, &MR, JITSymTabInfo,
+ InBootstrapPhase](LinkGraph &G) {
+ return addSymbolTableRegistration(G, MR, *JITSymTabInfo, InBootstrapPhase);
+ });
+
// Add a pass to register the final addresses of any special sections in the
// object with the runtime.
Config.PostAllocationPasses.push_back(
@@ -826,6 +848,9 @@ Error MachOPlatform::MachOPlatformPlugin::
{*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},
{*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},
{*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},
+ {*MP.RegisterObjectSymbolTable.Name, &MP.RegisterObjectSymbolTable.Addr},
+ {*MP.DeregisterObjectSymbolTable.Name,
+ &MP.DeregisterObjectSymbolTable.Addr},
{*MP.RegisterObjectPlatformSections.Name,
&MP.RegisterObjectPlatformSections.Addr},
{*MP.DeregisterObjectPlatformSections.Name,
@@ -1029,15 +1054,19 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
" does not match first registered version",
inconvertibleErrorCode());
if (ObjCImageInfoItr->second.Flags != Flags)
- return make_error<StringError>("ObjC flags in " + G.getName() +
- " do not match first registered flags",
- inconvertibleErrorCode());
+ if (Error E = mergeImageInfoFlags(G, MR, ObjCImageInfoItr->second, Flags))
+ return E;
// __objc_imageinfo is valid. Delete the block.
for (auto *S : ObjCImageInfo->symbols())
G.removeDefinedSymbol(*S);
G.removeBlock(ObjCImageInfoBlock);
} else {
+ LLVM_DEBUG({
+ dbgs() << "MachOPlatform: Registered __objc_imageinfo for "
+ << MR.getTargetJITDylib().getName() << " in " << G.getName()
+ << "; flags = " << formatv("{0:x4}", Flags) << "\n";
+ });
// We haven't registered an __objc_imageinfo section yet. Register and
// move on. The section should already be marked no-dead-strip.
G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName,
@@ -1047,12 +1076,66 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
{{MR.getExecutionSession().intern(ObjCImageInfoSymbolName),
JITSymbolFlags()}}))
return Err;
- ObjCImageInfos[&MR.getTargetJITDylib()] = {Version, Flags};
+ ObjCImageInfos[&MR.getTargetJITDylib()] = {Version, Flags, false};
}
return Error::success();
}
+Error MachOPlatform::MachOPlatformPlugin::mergeImageInfoFlags(
+ jitlink::LinkGraph &G, MaterializationResponsibility &MR,
+ ObjCImageInfo &Info, uint32_t NewFlags) {
+ if (Info.Flags == NewFlags)
+ return Error::success();
+
+ ObjCImageInfoFlags Old(Info.Flags);
+ ObjCImageInfoFlags New(NewFlags);
+
+ // Check for incompatible flags.
+ if (Old.SwiftABIVersion && New.SwiftABIVersion &&
+ Old.SwiftABIVersion != New.SwiftABIVersion)
+ return make_error<StringError>("Swift ABI version in " + G.getName() +
+ " does not match first registered flags",
+ inconvertibleErrorCode());
+
+ if (Old.HasCategoryClassProperties != New.HasCategoryClassProperties)
+ return make_error<StringError>("ObjC category class property support in " +
+ G.getName() +
+ " does not match first registered flags",
+ inconvertibleErrorCode());
+ if (Old.HasSignedObjCClassROs != New.HasSignedObjCClassROs)
+ return make_error<StringError>("ObjC class_ro_t pointer signing in " +
+ G.getName() +
+ " does not match first registered flags",
+ inconvertibleErrorCode());
+
+ // If we cannot change the flags, ignore any remaining differences. Adding
+ // Swift or changing its version are unlikely to cause problems in practice.
+ if (Info.Finalized)
+ return Error::success();
+
+ // Use the minimum Swift version.
+ if (Old.SwiftVersion && New.SwiftVersion)
+ New.SwiftVersion = std::min(Old.SwiftVersion, New.SwiftVersion);
+ else if (Old.SwiftVersion)
+ New.SwiftVersion = Old.SwiftVersion;
+ // Add a Swift ABI version if it was pure objc before.
+ if (!New.SwiftABIVersion)
+ New.SwiftABIVersion = Old.SwiftABIVersion;
+
+ LLVM_DEBUG({
+ dbgs() << "MachOPlatform: Merging __objc_imageinfo flags for "
+ << MR.getTargetJITDylib().getName() << " (was "
+ << formatv("{0:x4}", Old.rawFlags()) << ")"
+ << " with " << G.getName() << " (" << formatv("{0:x4}", NewFlags)
+ << ")"
+ << " -> " << formatv("{0:x4}", New.rawFlags()) << "\n";
+ });
+
+ Info.Flags = New.rawFlags();
+ return Error::success();
+}
+
Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
jitlink::LinkGraph &G, JITDylib &JD) {
@@ -1250,15 +1333,6 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
UI->CompactUnwindSection);
if (!MachOPlatformSecs.empty() || UnwindInfo) {
- ExecutorAddr HeaderAddr;
- {
- std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
- auto I = MP.JITDylibToHeaderAddr.find(&JD);
- assert(I != MP.JITDylibToHeaderAddr.end() &&
- "Missing header for JITDylib");
- HeaderAddr = I->second;
- }
-
// Dump the scraped inits.
LLVM_DEBUG({
dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
@@ -1276,6 +1350,15 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
? G.allocActions()
: MP.Bootstrap.load()->DeferredAAs;
+ ExecutorAddr HeaderAddr;
+ {
+ std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
+ auto I = MP.JITDylibToHeaderAddr.find(&JD);
+ assert(I != MP.JITDylibToHeaderAddr.end() &&
+ "No header registered for JD");
+ assert(I->second && "Null header registered for JD");
+ HeaderAddr = I->second;
+ }
allocActions.push_back(
{cantFail(
WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
@@ -1374,17 +1457,7 @@ Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(
strcpy(SD.Sec.segname, "__DATA");
SD.Sec.size = 8;
SD.AddFixups = [&](size_t RecordOffset) {
- jitlink::Edge::Kind PointerEdge = jitlink::Edge::Invalid;
- switch (G.getTargetTriple().getArch()) {
- case Triple::aarch64:
- PointerEdge = jitlink::aarch64::Pointer64;
- break;
- case Triple::x86_64:
- PointerEdge = jitlink::x86_64::Pointer64;
- break;
- default:
- llvm_unreachable("Unsupported architecture");
- }
+ auto PointerEdge = getPointerEdgeKind(G);
// Look for an existing __objc_imageinfo symbol.
jitlink::Symbol *ObjCImageInfoSym = nullptr;
@@ -1403,6 +1476,24 @@ Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(
for (auto *Sym : G.defined_symbols())
if (Sym->hasName() && Sym->getName() == ObjCImageInfoSymbolName) {
ObjCImageInfoSym = Sym;
+ std::optional<uint32_t> Flags;
+ {
+ std::lock_guard<std::mutex> Lock(PluginMutex);
+ auto It = ObjCImageInfos.find(&MR.getTargetJITDylib());
+ if (It != ObjCImageInfos.end()) {
+ It->second.Finalized = true;
+ Flags = It->second.Flags;
+ }
+ }
+
+ if (Flags) {
+ // We own the definition of __objc_image_info; write the final
+ // merged flags value.
+ auto Content = Sym->getBlock().getMutableContent(G);
+ assert(Content.size() == 8 &&
+ "__objc_image_info size should have been verified already");
+ support::endian::write32(&Content[4], *Flags, G.getEndianness());
+ }
break;
}
if (!ObjCImageInfoSym)
@@ -1460,7 +1551,7 @@ Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(
auto SecContent = SecBlock.getAlreadyMutableContent();
char *P = SecContent.data();
auto WriteMachOStruct = [&](auto S) {
- if (G.getEndianness() != support::endian::system_endianness())
+ if (G.getEndianness() != llvm::endianness::native)
MachO::swapStruct(S);
memcpy(P, &S, sizeof(S));
P += sizeof(S);
@@ -1492,5 +1583,179 @@ Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(
return Error::success();
}
+Error MachOPlatform::MachOPlatformPlugin::prepareSymbolTableRegistration(
+ jitlink::LinkGraph &G, JITSymTabVector &JITSymTabInfo) {
+
+ auto *CStringSec = G.findSectionByName(MachOCStringSectionName);
+ if (!CStringSec)
+ CStringSec = &G.createSection(MachOCStringSectionName,
+ MemProt::Read | MemProt::Exec);
+
+ // Make a map of existing strings so that we can re-use them:
+ DenseMap<StringRef, jitlink::Symbol *> ExistingStrings;
+ for (auto *Sym : CStringSec->symbols()) {
+
+ // The LinkGraph builder should have created single strings blocks, and all
+ // plugins should have maintained this invariant.
+ auto Content = Sym->getBlock().getContent();
+ ExistingStrings.insert(
+ std::make_pair(StringRef(Content.data(), Content.size()), Sym));
+ }
+
+ // Add all symbol names to the string section, and record the symbols for
+ // those names.
+ {
+ SmallVector<jitlink::Symbol *> SymsToProcess;
+ for (auto *Sym : G.defined_symbols())
+ SymsToProcess.push_back(Sym);
+
+ for (auto *Sym : SymsToProcess) {
+ if (!Sym->hasName())
+ continue;
+
+ auto I = ExistingStrings.find(Sym->getName());
+ if (I == ExistingStrings.end()) {
+ auto &NameBlock = G.createMutableContentBlock(
+ *CStringSec, G.allocateCString(Sym->getName()), orc::ExecutorAddr(),
+ 1, 0);
+ auto &SymbolNameSym = G.addAnonymousSymbol(
+ NameBlock, 0, NameBlock.getSize(), false, true);
+ JITSymTabInfo.push_back({Sym, &SymbolNameSym});
+ } else
+ JITSymTabInfo.push_back({Sym, I->second});
+ }
+ }
+
+ return Error::success();
+}
+
+Error MachOPlatform::MachOPlatformPlugin::addSymbolTableRegistration(
+ jitlink::LinkGraph &G, MaterializationResponsibility &MR,
+ JITSymTabVector &JITSymTabInfo, bool InBootstrapPhase) {
+
+ ExecutorAddr HeaderAddr;
+ {
+ std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
+ auto I = MP.JITDylibToHeaderAddr.find(&MR.getTargetJITDylib());
+ assert(I != MP.JITDylibToHeaderAddr.end() && "No header registered for JD");
+ assert(I->second && "Null header registered for JD");
+ HeaderAddr = I->second;
+ }
+
+ SymbolTableVector LocalSymTab;
+ auto &SymTab = LLVM_LIKELY(!InBootstrapPhase) ? LocalSymTab
+ : MP.Bootstrap.load()->SymTab;
+ for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo)
+ SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(),
+ flagsForSymbol(*OriginalSymbol)});
+
+ // Bail out if we're in the bootstrap phase -- registration of thees symbols
+ // will be attached to the bootstrap graph.
+ if (LLVM_UNLIKELY(InBootstrapPhase))
+ return Error::success();
+
+ shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase)
+ ? G.allocActions()
+ : MP.Bootstrap.load()->DeferredAAs;
+ allocActions.push_back(
+ {cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>(
+ MP.RegisterObjectSymbolTable.Addr, HeaderAddr, SymTab)),
+ cantFail(WrapperFunctionCall::Create<SPSRegisterSymbolsArgs>(
+ MP.DeregisterObjectSymbolTable.Addr, HeaderAddr, SymTab))});
+
+ return Error::success();
+}
+
+template <typename MachOTraits>
+jitlink::Block &createTrivialHeaderBlock(MachOPlatform &MOP,
+ jitlink::LinkGraph &G,
+ jitlink::Section &HeaderSection) {
+ auto HdrInfo =
+ getMachOHeaderInfoFromTriple(MOP.getExecutionSession().getTargetTriple());
+ MachOBuilder<MachOTraits> B(HdrInfo.PageSize);
+
+ B.Header.filetype = MachO::MH_DYLIB;
+ B.Header.cputype = HdrInfo.CPUType;
+ B.Header.cpusubtype = HdrInfo.CPUSubType;
+
+ auto HeaderContent = G.allocateBuffer(B.layout());
+ B.write(HeaderContent);
+
+ return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
+ 0);
+}
+
+SimpleMachOHeaderMU::SimpleMachOHeaderMU(MachOPlatform &MOP,
+ SymbolStringPtr HeaderStartSymbol)
+ : MaterializationUnit(
+ createHeaderInterface(MOP, std::move(HeaderStartSymbol))),
+ MOP(MOP) {}
+
+void SimpleMachOHeaderMU::materialize(
+ std::unique_ptr<MaterializationResponsibility> R) {
+ auto G = createPlatformGraph(MOP, "<MachOHeaderMU>");
+ addMachOHeader(R->getTargetJITDylib(), *G, R->getInitializerSymbol());
+ MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
+}
+
+void SimpleMachOHeaderMU::discard(const JITDylib &JD,
+ const SymbolStringPtr &Sym) {}
+
+void SimpleMachOHeaderMU::addMachOHeader(
+ JITDylib &JD, jitlink::LinkGraph &G,
+ const SymbolStringPtr &InitializerSymbol) {
+ auto &HeaderSection = G.createSection("__header", MemProt::Read);
+ auto &HeaderBlock = createHeaderBlock(JD, G, HeaderSection);
+
+ // Init symbol is header-start symbol.
+ G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol, HeaderBlock.getSize(),
+ jitlink::Linkage::Strong, jitlink::Scope::Default, false,
+ true);
+ for (auto &HS : AdditionalHeaderSymbols)
+ G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(),
+ jitlink::Linkage::Strong, jitlink::Scope::Default, false,
+ true);
+}
+
+jitlink::Block &
+SimpleMachOHeaderMU::createHeaderBlock(JITDylib &JD, jitlink::LinkGraph &G,
+ jitlink::Section &HeaderSection) {
+ switch (MOP.getExecutionSession().getTargetTriple().getArch()) {
+ case Triple::aarch64:
+ case Triple::x86_64:
+ return createTrivialHeaderBlock<MachO64LE>(MOP, G, HeaderSection);
+ default:
+ llvm_unreachable("Unsupported architecture");
+ }
+}
+
+MaterializationUnit::Interface SimpleMachOHeaderMU::createHeaderInterface(
+ MachOPlatform &MOP, const SymbolStringPtr &HeaderStartSymbol) {
+ SymbolFlagsMap HeaderSymbolFlags;
+
+ HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
+ for (auto &HS : AdditionalHeaderSymbols)
+ HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =
+ JITSymbolFlags::Exported;
+
+ return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
+ HeaderStartSymbol);
+}
+
+MachOHeaderInfo getMachOHeaderInfoFromTriple(const Triple &TT) {
+ switch (TT.getArch()) {
+ case Triple::aarch64:
+ return {/* PageSize = */ 16 * 1024,
+ /* CPUType = */ MachO::CPU_TYPE_ARM64,
+ /* CPUSubType = */ MachO::CPU_SUBTYPE_ARM64_ALL};
+ case Triple::x86_64:
+ return {/* PageSize = */ 4 * 1024,
+ /* CPUType = */ MachO::CPU_TYPE_X86_64,
+ /* CPUSubType = */ MachO::CPU_SUBTYPE_X86_64_ALL};
+ default:
+ llvm_unreachable("Unrecognized architecture");
+ }
+}
+
} // End namespace orc.
} // End namespace llvm.