Skip to content

Commit b08aca7

Browse files
committed
[ORC][MachO] Support common load commands in the platform's mach-o header builder
Add a HeaderOptions struct that can be used to configure commonly-used load commands LC_ID_DYLIB, LC_LOAD_DYLIB, and LC_RPATH when setupDylib creates a mach-o header.
1 parent ab244b6 commit b08aca7

File tree

3 files changed

+123
-24
lines changed

3 files changed

+123
-24
lines changed

llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,47 @@ struct MachOBuilderLoadCommand<MachO::LC_ID_DYLIB>
104104
std::string Name;
105105
};
106106

107+
template <>
108+
struct MachOBuilderLoadCommand<MachO::LC_LOAD_DYLIB>
109+
: public MachOBuilderLoadCommandImplBase<MachO::LC_LOAD_DYLIB> {
110+
111+
MachOBuilderLoadCommand(std::string Name, uint32_t Timestamp,
112+
uint32_t CurrentVersion,
113+
uint32_t CompatibilityVersion)
114+
: MachOBuilderLoadCommandImplBase(
115+
MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),
116+
Name(std::move(Name)) {
117+
cmdsize += (this->Name.size() + 1 + 3) & ~0x3;
118+
}
119+
120+
size_t write(MutableArrayRef<char> Buf, size_t Offset,
121+
bool SwapStruct) override {
122+
Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
123+
strcpy(Buf.data() + Offset, Name.data());
124+
return Offset + ((Name.size() + 1 + 3) & ~0x3);
125+
}
126+
127+
std::string Name;
128+
};
129+
130+
template <>
131+
struct MachOBuilderLoadCommand<MachO::LC_RPATH>
132+
: public MachOBuilderLoadCommandImplBase<MachO::LC_RPATH> {
133+
MachOBuilderLoadCommand(std::string Path)
134+
: MachOBuilderLoadCommandImplBase(12u), Path(std::move(Path)) {
135+
cmdsize += (this->Path.size() + 1 + 3) & ~0x3;
136+
}
137+
138+
size_t write(MutableArrayRef<char> Buf, size_t Offset,
139+
bool SwapStruct) override {
140+
Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
141+
strcpy(Buf.data() + Offset, Path.data());
142+
return Offset + ((Path.size() + 1 + 3) & ~0x3);
143+
}
144+
145+
std::string Path;
146+
};
147+
107148
// Builds MachO objects.
108149
template <typename MachOTraits> class MachOBuilder {
109150
private:

llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,38 @@ class MachOPlatform : public Platform {
4747
LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable)
4848
};
4949

50+
/// Configuration for the mach-o header of a JITDylib. Specify common load
51+
/// commands that should be added to the header.
52+
struct HeaderOptions {
53+
/// A dylib for use with a dylib command (e.g. LC_ID_DYLIB, LC_LOAD_DYLIB).
54+
struct Dylib {
55+
std::string Name;
56+
uint32_t Timestamp;
57+
uint32_t CurrentVersion;
58+
uint32_t CompatibilityVersion;
59+
};
60+
61+
/// Override for LC_IC_DYLIB. If this is nullopt, {JD.getName(), 0, 0, 0}
62+
/// will be used.
63+
std::optional<Dylib> IDDylib;
64+
/// List of LC_LOAD_DYLIBs.
65+
std::vector<Dylib> LoadDylibs;
66+
/// List of LC_RPATHs.
67+
std::vector<std::string> RPaths;
68+
69+
HeaderOptions() = default;
70+
HeaderOptions(Dylib D) : IDDylib(std::move(D)) {}
71+
};
72+
5073
/// Used by setupJITDylib to create MachO header MaterializationUnits for
5174
/// JITDylibs.
5275
using MachOHeaderMUBuilder =
53-
unique_function<std::unique_ptr<MaterializationUnit>(MachOPlatform &MOP)>;
76+
unique_function<std::unique_ptr<MaterializationUnit>(MachOPlatform &MOP,
77+
HeaderOptions Opts)>;
5478

5579
/// Simple MachO header graph builder.
5680
static inline std::unique_ptr<MaterializationUnit>
57-
buildSimpleMachOHeaderMU(MachOPlatform &MOP);
81+
buildSimpleMachOHeaderMU(MachOPlatform &MOP, HeaderOptions Opts);
5882

5983
/// Try to create a MachOPlatform instance, adding the ORC runtime to the
6084
/// given JITDylib.
@@ -97,13 +121,15 @@ class MachOPlatform : public Platform {
97121
static Expected<std::unique_ptr<MachOPlatform>>
98122
Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
99123
JITDylib &PlatformJD, std::unique_ptr<DefinitionGenerator> OrcRuntime,
124+
HeaderOptions PlatformJDOpts = {},
100125
MachOHeaderMUBuilder BuildMachOHeaderMU = buildSimpleMachOHeaderMU,
101126
std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
102127

103128
/// Construct using a path to the ORC runtime.
104129
static Expected<std::unique_ptr<MachOPlatform>>
105130
Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
106131
JITDylib &PlatformJD, const char *OrcRuntimePath,
132+
HeaderOptions PlatformJDOpts = {},
107133
MachOHeaderMUBuilder BuildMachOHeaderMU = buildSimpleMachOHeaderMU,
108134
std::optional<SymbolAliasMap> RuntimeAliases = std::nullopt);
109135

@@ -115,6 +141,11 @@ class MachOPlatform : public Platform {
115141
}
116142

117143
Error setupJITDylib(JITDylib &JD) override;
144+
145+
/// Install any platform-specific symbols (e.g. `__dso_handle`) and create a
146+
/// mach-o header based on the given options.
147+
Error setupJITDylib(JITDylib &JD, HeaderOptions Opts);
148+
118149
Error teardownJITDylib(JITDylib &JD) override;
119150
Error notifyAdding(ResourceTracker &RT,
120151
const MaterializationUnit &MU) override;
@@ -258,6 +289,7 @@ class MachOPlatform : public Platform {
258289
MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
259290
JITDylib &PlatformJD,
260291
std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
292+
HeaderOptions PlatformJDOpts,
261293
MachOHeaderMUBuilder BuildMachOHeaderMU, Error &Err);
262294

263295
// Associate MachOPlatform JIT-side runtime support functions with handlers.
@@ -336,7 +368,8 @@ class MachOPlatform : public Platform {
336368
// Generates a MachO header.
337369
class SimpleMachOHeaderMU : public MaterializationUnit {
338370
public:
339-
SimpleMachOHeaderMU(MachOPlatform &MOP, SymbolStringPtr HeaderStartSymbol);
371+
SimpleMachOHeaderMU(MachOPlatform &MOP, SymbolStringPtr HeaderStartSymbol,
372+
MachOPlatform::HeaderOptions Opts);
340373
StringRef getName() const override { return "MachOHeaderMU"; }
341374
void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
342375
void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override;
@@ -346,6 +379,7 @@ class SimpleMachOHeaderMU : public MaterializationUnit {
346379
jitlink::Section &HeaderSection);
347380

348381
MachOPlatform &MOP;
382+
MachOPlatform::HeaderOptions Opts;
349383

350384
private:
351385
struct HeaderSymbol {
@@ -365,8 +399,10 @@ class SimpleMachOHeaderMU : public MaterializationUnit {
365399

366400
/// Simple MachO header graph builder.
367401
inline std::unique_ptr<MaterializationUnit>
368-
MachOPlatform::buildSimpleMachOHeaderMU(MachOPlatform &MOP) {
369-
return std::make_unique<SimpleMachOHeaderMU>(MOP, MOP.MachOHeaderStartSymbol);
402+
MachOPlatform::buildSimpleMachOHeaderMU(MachOPlatform &MOP,
403+
HeaderOptions Opts) {
404+
return std::make_unique<SimpleMachOHeaderMU>(MOP, MOP.MachOHeaderStartSymbol,
405+
std::move(Opts));
370406
}
371407

372408
struct MachOHeaderInfo {

llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,11 @@ struct ObjCImageInfoFlags {
255255
namespace llvm {
256256
namespace orc {
257257

258-
Expected<std::unique_ptr<MachOPlatform>>
259-
MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
260-
JITDylib &PlatformJD,
261-
std::unique_ptr<DefinitionGenerator> OrcRuntime,
262-
MachOHeaderMUBuilder BuildMachOHeaderMU,
263-
std::optional<SymbolAliasMap> RuntimeAliases) {
258+
Expected<std::unique_ptr<MachOPlatform>> MachOPlatform::Create(
259+
ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
260+
JITDylib &PlatformJD, std::unique_ptr<DefinitionGenerator> OrcRuntime,
261+
HeaderOptions PlatformJDOpts, MachOHeaderMUBuilder BuildMachOHeaderMU,
262+
std::optional<SymbolAliasMap> RuntimeAliases) {
264263

265264
// If the target is not supported then bail out immediately.
266265
if (!supportedTarget(ES.getTargetTriple()))
@@ -290,9 +289,9 @@ MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
290289

291290
// Create the instance.
292291
Error Err = Error::success();
293-
auto P = std::unique_ptr<MachOPlatform>(
294-
new MachOPlatform(ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime),
295-
std::move(BuildMachOHeaderMU), Err));
292+
auto P = std::unique_ptr<MachOPlatform>(new MachOPlatform(
293+
ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime),
294+
std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU), Err));
296295
if (Err)
297296
return std::move(Err);
298297
return std::move(P);
@@ -301,6 +300,7 @@ MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
301300
Expected<std::unique_ptr<MachOPlatform>>
302301
MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
303302
JITDylib &PlatformJD, const char *OrcRuntimePath,
303+
HeaderOptions PlatformJDOpts,
304304
MachOHeaderMUBuilder BuildMachOHeaderMU,
305305
std::optional<SymbolAliasMap> RuntimeAliases) {
306306

@@ -312,11 +312,16 @@ MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
312312

313313
return Create(ES, ObjLinkingLayer, PlatformJD,
314314
std::move(*OrcRuntimeArchiveGenerator),
315-
std::move(BuildMachOHeaderMU), std::move(RuntimeAliases));
315+
std::move(PlatformJDOpts), std::move(BuildMachOHeaderMU),
316+
std::move(RuntimeAliases));
316317
}
317318

318319
Error MachOPlatform::setupJITDylib(JITDylib &JD) {
319-
if (auto Err = JD.define(BuildMachOHeaderMU(*this)))
320+
return setupJITDylib(JD, /*Opts=*/{});
321+
}
322+
323+
Error MachOPlatform::setupJITDylib(JITDylib &JD, HeaderOptions Opts) {
324+
if (auto Err = JD.define(BuildMachOHeaderMU(*this, std::move(Opts))))
320325
return Err;
321326

322327
return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();
@@ -432,7 +437,8 @@ MachOPlatform::MachOPlatform(
432437
ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
433438
JITDylib &PlatformJD,
434439
std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
435-
MachOHeaderMUBuilder BuildMachOHeaderMU, Error &Err)
440+
HeaderOptions PlatformJDOpts, MachOHeaderMUBuilder BuildMachOHeaderMU,
441+
Error &Err)
436442
: ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer),
437443
BuildMachOHeaderMU(std::move(BuildMachOHeaderMU)) {
438444
ErrorAsOutParameter _(&Err);
@@ -497,7 +503,8 @@ MachOPlatform::MachOPlatform(
497503
// the support methods callable. The bootstrap is now complete.
498504

499505
// Step (1) Add header materialization unit and request.
500-
if ((Err = PlatformJD.define(this->BuildMachOHeaderMU(*this))))
506+
if ((Err = PlatformJD.define(
507+
this->BuildMachOHeaderMU(*this, std::move(PlatformJDOpts)))))
501508
return;
502509
if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))
503510
return;
@@ -1669,9 +1676,10 @@ Error MachOPlatform::MachOPlatformPlugin::addSymbolTableRegistration(
16691676
}
16701677

16711678
template <typename MachOTraits>
1672-
jitlink::Block &createTrivialHeaderBlock(MachOPlatform &MOP,
1673-
jitlink::LinkGraph &G,
1674-
jitlink::Section &HeaderSection) {
1679+
jitlink::Block &createHeaderBlock(MachOPlatform &MOP,
1680+
const MachOPlatform::HeaderOptions &Opts,
1681+
JITDylib &JD, jitlink::LinkGraph &G,
1682+
jitlink::Section &HeaderSection) {
16751683
auto HdrInfo =
16761684
getMachOHeaderInfoFromTriple(MOP.getExecutionSession().getTargetTriple());
16771685
MachOBuilder<MachOTraits> B(HdrInfo.PageSize);
@@ -1680,6 +1688,19 @@ jitlink::Block &createTrivialHeaderBlock(MachOPlatform &MOP,
16801688
B.Header.cputype = HdrInfo.CPUType;
16811689
B.Header.cpusubtype = HdrInfo.CPUSubType;
16821690

1691+
if (Opts.IDDylib)
1692+
B.template addLoadCommand<MachO::LC_ID_DYLIB>(
1693+
Opts.IDDylib->Name, Opts.IDDylib->Timestamp,
1694+
Opts.IDDylib->CurrentVersion, Opts.IDDylib->CompatibilityVersion);
1695+
else
1696+
B.template addLoadCommand<MachO::LC_ID_DYLIB>(JD.getName(), 0, 0, 0);
1697+
1698+
for (auto &D : Opts.LoadDylibs)
1699+
B.template addLoadCommand<MachO::LC_LOAD_DYLIB>(
1700+
D.Name, D.Timestamp, D.CurrentVersion, D.CompatibilityVersion);
1701+
for (auto &P : Opts.RPaths)
1702+
B.template addLoadCommand<MachO::LC_RPATH>(P);
1703+
16831704
auto HeaderContent = G.allocateBuffer(B.layout());
16841705
B.write(HeaderContent);
16851706

@@ -1688,10 +1709,11 @@ jitlink::Block &createTrivialHeaderBlock(MachOPlatform &MOP,
16881709
}
16891710

16901711
SimpleMachOHeaderMU::SimpleMachOHeaderMU(MachOPlatform &MOP,
1691-
SymbolStringPtr HeaderStartSymbol)
1712+
SymbolStringPtr HeaderStartSymbol,
1713+
MachOPlatform::HeaderOptions Opts)
16921714
: MaterializationUnit(
16931715
createHeaderInterface(MOP, std::move(HeaderStartSymbol))),
1694-
MOP(MOP) {}
1716+
MOP(MOP), Opts(std::move(Opts)) {}
16951717

16961718
void SimpleMachOHeaderMU::materialize(
16971719
std::unique_ptr<MaterializationResponsibility> R) {
@@ -1725,7 +1747,7 @@ SimpleMachOHeaderMU::createHeaderBlock(JITDylib &JD, jitlink::LinkGraph &G,
17251747
switch (MOP.getExecutionSession().getTargetTriple().getArch()) {
17261748
case Triple::aarch64:
17271749
case Triple::x86_64:
1728-
return createTrivialHeaderBlock<MachO64LE>(MOP, G, HeaderSection);
1750+
return ::createHeaderBlock<MachO64LE>(MOP, Opts, JD, G, HeaderSection);
17291751
default:
17301752
llvm_unreachable("Unsupported architecture");
17311753
}

0 commit comments

Comments
 (0)