1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[JITLink][ORC] Enable creation / linking of raw jitlink::LinkGraphs.

Separates link graph creation from linking. This allows raw LinkGraphs to be
created and passed to a link. ObjectLinkingLayer is updated to support emission
of raw LinkGraphs in addition to object buffers.

Raw LinkGraphs can be created by in-memory compilers to bypass object encoding /
decoding (though this prevents caching, as LinkGraphs have do not have an
on-disk representation), and by utility code to add programatically generated
data structures to the JIT target process.
This commit is contained in:
Lang Hames 2020-12-16 12:18:30 +11:00
parent f62c427dbf
commit 36c0911571
19 changed files with 256 additions and 160 deletions

View File

@ -19,11 +19,20 @@
namespace llvm {
namespace jitlink {
/// jit-link the given ObjBuffer, which must be a ELF object file.
/// Create a LinkGraph from an ELF relocatable object.
///
/// Note: The graph does not take ownership of the underlying buffer, nor copy
/// its contents. The caller is responsible for ensuring that the object buffer
/// outlives the graph.
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer);
/// Link the given graph.
///
/// Uses conservative defaults for GOT and stub handling based on the target
/// platform.
void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx);
void link_ELF(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx);
} // end namespace jitlink
} // end namespace llvm

View File

@ -44,8 +44,18 @@ enum ELFX86RelocationKind : Edge::Kind {
} // end namespace ELF_x86_64_Edges
/// Create a LinkGraph from an ELF/x86-64 relocatable object.
///
/// Note: The graph does not take ownership of the underlying buffer, nor copy
/// its contents. The caller is responsible for ensuring that the object buffer
/// outlives the graph.
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer);
/// jit-link the given object buffer, which must be a ELF x86-64 object file.
void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx);
void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx);
/// Return the string name of the given ELF x86-64 edge kind.
StringRef getELFX86RelocationKindName(Edge::Kind R);
} // end namespace jitlink

View File

@ -786,24 +786,40 @@ public:
Section::const_block_iterator, const Block *,
getSectionConstBlocks>;
LinkGraph(std::string Name, unsigned PointerSize,
LinkGraph(std::string Name, const Triple &TT, unsigned PointerSize,
support::endianness Endianness)
: Name(std::move(Name)), PointerSize(PointerSize),
: Name(std::move(Name)), TT(TT), PointerSize(PointerSize),
Endianness(Endianness) {}
/// Returns the name of this graph (usually the name of the original
/// underlying MemoryBuffer).
const std::string &getName() { return Name; }
/// Returns the target triple for this Graph.
const Triple &getTargetTriple() const { return TT; }
/// Returns the pointer size for use in this graph.
unsigned getPointerSize() const { return PointerSize; }
/// Returns the endianness of content in this graph.
support::endianness getEndianness() const { return Endianness; }
/// Allocate a copy of the given String using the LinkGraph's allocator.
/// Allocate a copy of the given string using the LinkGraph's allocator.
/// This can be useful when renaming symbols or adding new content to the
/// graph.
StringRef allocateString(StringRef Source) {
auto *AllocatedBuffer = Allocator.Allocate<char>(Source.size());
llvm::copy(Source, AllocatedBuffer);
return StringRef(AllocatedBuffer, Source.size());
}
/// Allocate a copy of the given string using the LinkGraph's allocator.
/// This can be useful when renaming symbols or adding new content to the
/// graph.
///
/// Note: This Twine-based overload requires an extra string copy and an
/// extra heap allocation for large strings. The StringRef overload should
/// be preferred where possible.
StringRef allocateString(Twine Source) {
SmallString<256> TmpBuffer;
auto SourceStr = Source.toStringRef(TmpBuffer);
@ -1034,6 +1050,7 @@ private:
BumpPtrAllocator Allocator;
std::string Name;
Triple TT;
unsigned PointerSize;
support::endianness Endianness;
SectionList Sections;
@ -1282,10 +1299,6 @@ public:
/// Return the MemoryManager to be used for this link.
virtual JITLinkMemoryManager &getMemoryManager() = 0;
/// Returns a StringRef for the object buffer.
/// This method can not be called once takeObjectBuffer has been called.
virtual MemoryBufferRef getObjectBuffer() const = 0;
/// Notify this context that linking failed.
/// Called by JITLink if linking cannot be completed.
virtual void notifyFailed(Error Err) = 0;
@ -1339,10 +1352,16 @@ private:
/// conservative mark-live implementation.
Error markAllSymbolsLive(LinkGraph &G);
/// Basic JITLink implementation.
/// Create a LinkGraph from the given object buffer.
///
/// This function will use sensible defaults for GOT and Stub handling.
void jitLink(std::unique_ptr<JITLinkContext> Ctx);
/// Note: The graph does not take ownership of the underlying buffer, nor copy
/// its contents. The caller is responsible for ensuring that the object buffer
/// outlives the graph.
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromObject(MemoryBufferRef ObjectBuffer);
/// Link the given graph.
void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx);
} // end namespace jitlink
} // end namespace llvm

View File

@ -18,11 +18,20 @@
namespace llvm {
namespace jitlink {
/// Create a LinkGraph from a MachO relocatable object.
///
/// Note: The graph does not take ownership of the underlying buffer, nor copy
/// its contents. The caller is responsible for ensuring that the object buffer
/// outlives the graph.
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer);
/// jit-link the given ObjBuffer, which must be a MachO object file.
///
/// Uses conservative defaults for GOT and stub handling based on the target
/// platform.
void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx);
void link_MachO(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx);
} // end namespace jitlink
} // end namespace llvm

View File

@ -40,6 +40,14 @@ enum MachOARM64RelocationKind : Edge::Kind {
} // namespace MachO_arm64_Edges
/// Create a LinkGraph from a MachO/arm64 relocatable object.
///
/// Note: The graph does not take ownership of the underlying buffer, nor copy
/// its contents. The caller is responsible for ensuring that the object buffer
/// outlives the graph.
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer);
/// jit-link the given object buffer, which must be a MachO arm64 object file.
///
/// If PrePrunePasses is empty then a default mark-live pass will be inserted
@ -49,7 +57,8 @@ enum MachOARM64RelocationKind : Edge::Kind {
/// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will
/// be inserted. If PostPrunePasses is not empty then the caller is responsible
/// for including a pass to insert GOT and stub edges.
void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx);
void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx);
/// Return the string name of the given MachO arm64 edge kind.
StringRef getMachOARM64RelocationKindName(Edge::Kind R);

View File

@ -45,7 +45,15 @@ enum MachOX86RelocationKind : Edge::Kind {
} // namespace MachO_x86_64_Edges
/// jit-link the given object buffer, which must be a MachO x86-64 object file.
/// Create a LinkGraph from a MachO/x86-64 relocatable object.
///
/// Note: The graph does not take ownership of the underlying buffer, nor copy
/// its contents. The caller is responsible for ensuring that the object buffer
/// outlives the graph.
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer);
/// jit-link the given LinkGraph.
///
/// If PrePrunePasses is empty then a default mark-live pass will be inserted
/// that will mark all exported atoms live. If PrePrunePasses is not empty, the
@ -54,7 +62,8 @@ enum MachOX86RelocationKind : Edge::Kind {
/// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will
/// be inserted. If PostPrunePasses is not empty then the caller is responsible
/// for including a pass to insert GOT and stub edges.
void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx);
void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx);
/// Return the string name of the given MachO x86-64 edge kind.
StringRef getMachOX86RelocationKindName(Edge::Kind R);

View File

@ -35,6 +35,7 @@ namespace llvm {
namespace jitlink {
class EHFrameRegistrar;
class LinkGraph;
class Symbol;
} // namespace jitlink
@ -118,10 +119,14 @@ public:
return *this;
}
/// Emit the object.
/// Emit an object file.
void emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) override;
/// Emit a LinkGraph.
void emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<jitlink::LinkGraph> G);
/// Instructs this ObjectLinkingLayer instance to override the symbol flags
/// found in the AtomGraph with the flags supplied by the
/// MaterializationResponsibility instance. This is a workaround to support

View File

@ -50,32 +50,39 @@ Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
return ELF::EM_NONE;
}
void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx) {
StringRef Buffer = Ctx->getObjectBuffer().getBuffer();
if (Buffer.size() < ELF::EI_MAG3 + 1) {
Ctx->notifyFailed(make_error<JITLinkError>("Truncated ELF buffer"));
return;
}
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
StringRef Buffer = ObjectBuffer.getBuffer();
if (Buffer.size() < ELF::EI_MAG3 + 1)
return make_error<JITLinkError>("Truncated ELF buffer");
if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) {
Ctx->notifyFailed(make_error<JITLinkError>("ELF magic not valid"));
return;
}
if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
return make_error<JITLinkError>("ELF magic not valid");
Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
if (!TargetMachineArch) {
Ctx->notifyFailed(TargetMachineArch.takeError());
return;
}
if (!TargetMachineArch)
return TargetMachineArch.takeError();
switch (*TargetMachineArch) {
case ELF::EM_X86_64:
jitLink_ELF_x86_64(std::move(Ctx));
return createLinkGraphFromELFObject_x86_64(std::move(ObjectBuffer));
default:
return make_error<JITLinkError>(
"Unsupported target machine architecture in ELF object " +
ObjectBuffer.getBufferIdentifier());
}
}
void link_ELF(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx) {
switch (G->getTargetTriple().getArch()) {
case Triple::x86_64:
link_ELF_x86_64(std::move(G), std::move(Ctx));
return;
default:
Ctx->notifyFailed(make_error<JITLinkError>(
"Unsupported target machine architecture in ELF object " +
Ctx->getObjectBuffer().getBufferIdentifier()));
"Unsupported target machine architecture in ELF link graph " +
G->getName()));
return;
}
}

View File

@ -571,10 +571,11 @@ private:
}
public:
ELFLinkGraphBuilder_x86_64(std::string filename,
ELFLinkGraphBuilder_x86_64(StringRef FileName,
const object::ELFFile<object::ELF64LE> &Obj)
: G(std::make_unique<LinkGraph>(filename, getPointerSize(Obj),
getEndianness(Obj))),
: G(std::make_unique<LinkGraph>(FileName.str(),
Triple("x86_64-unknown-linux"),
getPointerSize(Obj), getEndianness(Obj))),
Obj(Obj) {}
Expected<std::unique_ptr<LinkGraph>> buildGraph() {
@ -610,27 +611,15 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
public:
ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
: JITLinker(std::move(Ctx), std::move(PassConfig)) {}
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
StringRef getEdgeKindName(Edge::Kind R) const override {
return getELFX86RelocationKindName(R);
}
Expected<std::unique_ptr<LinkGraph>>
buildGraph(MemoryBufferRef ObjBuffer) override {
auto ELFObj = object::ObjectFile::createELFObjectFile(ObjBuffer);
if (!ELFObj)
return ELFObj.takeError();
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
std::string fileName(ELFObj->get()->getFileName());
return ELFLinkGraphBuilder_x86_64(std::move(fileName),
ELFObjFile.getELFFile())
.buildGraph();
}
Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
using namespace ELF_x86_64_Edges;
using namespace llvm::support;
@ -655,12 +644,30 @@ private:
}
};
void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) {
LLVM_DEBUG({
dbgs() << "Building jitlink graph for new input "
<< ObjectBuffer.getBufferIdentifier() << "...\n";
});
auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
if (!ELFObj)
return ELFObj.takeError();
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(),
ELFObjFile.getELFFile())
.buildGraph();
}
void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx) {
PassConfiguration Config;
Triple TT("x86_64-linux");
// Construct a JITLinker and run the link function.
// Add a mark-live pass.
if (auto MarkLive = Ctx->getMarkLivePass(TT))
if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
@ -674,10 +681,10 @@ void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
// Add GOT/Stubs optimizer pass.
Config.PostAllocationPasses.push_back(optimizeELF_x86_64_GOTAndStubs);
if (auto Err = Ctx->modifyPassConfig(TT, Config))
if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
ELFJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
}
StringRef getELFX86RelocationKindName(Edge::Kind R) {
switch (R) {

View File

@ -322,15 +322,27 @@ Error markAllSymbolsLive(LinkGraph &G) {
return Error::success();
}
void jitLink(std::unique_ptr<JITLinkContext> Ctx) {
auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer());
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromObject(MemoryBufferRef ObjectBuffer) {
auto Magic = identify_magic(ObjectBuffer.getBuffer());
switch (Magic) {
case file_magic::macho_object:
return jitLink_MachO(std::move(Ctx));
return createLinkGraphFromMachOObject(std::move(ObjectBuffer));
case file_magic::elf_relocatable:
return jitLink_ELF(std::move(Ctx));
return createLinkGraphFromELFObject(std::move(ObjectBuffer));
default:
Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format"));
return make_error<JITLinkError>("Unsupported file format");
};
}
void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) {
switch (G->getTargetTriple().getObjectFormat()) {
case Triple::MachO:
return link_MachO(std::move(G), std::move(Ctx));
case Triple::ELF:
return link_ELF(std::move(G), std::move(Ctx));
default:
Ctx->notifyFailed(make_error<JITLinkError>("Unsupported object format"));
};
}

View File

@ -24,18 +24,6 @@ JITLinkerBase::~JITLinkerBase() {}
void JITLinkerBase::linkPhase1(std::unique_ptr<JITLinkerBase> Self) {
LLVM_DEBUG({
dbgs() << "Building jitlink graph for new input "
<< Ctx->getObjectBuffer().getBufferIdentifier() << "...\n";
});
// Build the link graph.
if (auto GraphOrErr = buildGraph(Ctx->getObjectBuffer()))
G = std::move(*GraphOrErr);
else
return Ctx->notifyFailed(GraphOrErr.takeError());
assert(G && "Graph should have been created by buildGraph above");
LLVM_DEBUG({
dbgs() << "Starting link phase 1 for graph " << G->getName() << "\n";
});

View File

@ -32,9 +32,11 @@ namespace jitlink {
/// remaining linker work) to allow them to be performed asynchronously.
class JITLinkerBase {
public:
JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx, PassConfiguration Passes)
: Ctx(std::move(Ctx)), Passes(std::move(Passes)) {
JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx,
std::unique_ptr<LinkGraph> G, PassConfiguration Passes)
: Ctx(std::move(Ctx)), G(std::move(G)), Passes(std::move(Passes)) {
assert(this->Ctx && "Ctx can not be null");
assert(this->G && "G can not be null");
}
virtual ~JITLinkerBase();
@ -50,8 +52,7 @@ protected:
using SegmentLayoutMap = DenseMap<unsigned, SegmentLayout>;
// Phase 1:
// 1.1: Build link graph
// 1.2: Run pre-prune passes
// 1.1: Run pre-prune passes
// 1.2: Prune graph
// 1.3: Run post-prune passes
// 1.4: Sort blocks into segments
@ -72,11 +73,6 @@ protected:
// 3.1: Call OnFinalized callback, handing off allocation.
void linkPhase3(std::unique_ptr<JITLinkerBase> Self, Error Err);
// Build a graph from the given object buffer.
// To be implemented by the client.
virtual Expected<std::unique_ptr<LinkGraph>>
buildGraph(MemoryBufferRef ObjBuffer) = 0;
// For debug dumping of the link graph.
virtual StringRef getEdgeKindName(Edge::Kind K) const = 0;
@ -113,8 +109,8 @@ private:
void dumpGraph(raw_ostream &OS);
std::unique_ptr<JITLinkContext> Ctx;
PassConfiguration Passes;
std::unique_ptr<LinkGraph> G;
PassConfiguration Passes;
std::unique_ptr<JITLinkMemoryManager::Allocation> Alloc;
};

View File

@ -27,39 +27,29 @@ using namespace llvm;
namespace llvm {
namespace jitlink {
void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx) {
// We don't want to do full MachO validation here. Just parse enough of the
// header to find out what MachO linker to use.
StringRef Data = Ctx->getObjectBuffer().getBuffer();
if (Data.size() < 4) {
StringRef BufferName = Ctx->getObjectBuffer().getBufferIdentifier();
Ctx->notifyFailed(make_error<JITLinkError>("Truncated MachO buffer \"" +
BufferName + "\""));
return;
}
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer) {
StringRef Data = ObjectBuffer.getBuffer();
if (Data.size() < 4)
return make_error<JITLinkError>("Truncated MachO buffer \"" +
ObjectBuffer.getBufferIdentifier() + "\"");
uint32_t Magic;
memcpy(&Magic, Data.data(), sizeof(uint32_t));
LLVM_DEBUG({
dbgs() << "jitLink_MachO: magic = " << format("0x%08" PRIx32, Magic)
<< ", identifier = \""
<< Ctx->getObjectBuffer().getBufferIdentifier() << "\"\n";
<< ", identifier = \"" << ObjectBuffer.getBufferIdentifier()
<< "\"\n";
});
if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM) {
Ctx->notifyFailed(
make_error<JITLinkError>("MachO 32-bit platforms not supported"));
return;
} else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) {
if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM)
return make_error<JITLinkError>("MachO 32-bit platforms not supported");
else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) {
if (Data.size() < sizeof(MachO::mach_header_64)) {
StringRef BufferName = Ctx->getObjectBuffer().getBufferIdentifier();
Ctx->notifyFailed(make_error<JITLinkError>("Truncated MachO buffer \"" +
BufferName + "\""));
return;
}
if (Data.size() < sizeof(MachO::mach_header_64))
return make_error<JITLinkError>("Truncated MachO buffer \"" +
ObjectBuffer.getBufferIdentifier() +
"\"");
// Read the CPU type from the header.
uint32_t CPUType;
@ -74,15 +64,27 @@ void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx) {
switch (CPUType) {
case MachO::CPU_TYPE_ARM64:
return jitLink_MachO_arm64(std::move(Ctx));
return createLinkGraphFromMachOObject_arm64(std::move(ObjectBuffer));
case MachO::CPU_TYPE_X86_64:
return jitLink_MachO_x86_64(std::move(Ctx));
return createLinkGraphFromMachOObject_x86_64(std::move(ObjectBuffer));
}
return make_error<JITLinkError>("MachO-64 CPU type not valid");
} else
return make_error<JITLinkError>("Unrecognized MachO magic value");
}
void link_MachO(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx) {
switch (G->getTargetTriple().getArch()) {
case Triple::aarch64:
return link_MachO_arm64(std::move(G), std::move(Ctx));
case Triple::x86_64:
return link_MachO_x86_64(std::move(G), std::move(Ctx));
default:
Ctx->notifyFailed(make_error<JITLinkError>("MachO-64 CPU type not valid"));
return;
}
Ctx->notifyFailed(make_error<JITLinkError>("MachO magic not valid"));
}
} // end namespace jitlink

View File

@ -45,10 +45,12 @@ Expected<std::unique_ptr<LinkGraph>> MachOLinkGraphBuilder::buildGraph() {
return std::move(G);
}
MachOLinkGraphBuilder::MachOLinkGraphBuilder(const object::MachOObjectFile &Obj)
MachOLinkGraphBuilder::MachOLinkGraphBuilder(const object::MachOObjectFile &Obj,
Triple TT)
: Obj(Obj),
G(std::make_unique<LinkGraph>(std::string(Obj.getFileName()),
getPointerSize(Obj), getEndianness(Obj))) {}
std::move(TT), getPointerSize(Obj),
getEndianness(Obj))) {}
void MachOLinkGraphBuilder::addCustomSectionParser(
StringRef SectionName, SectionParserFunction Parser) {

View File

@ -81,7 +81,7 @@ protected:
using SectionParserFunction = std::function<Error(NormalizedSection &S)>;
MachOLinkGraphBuilder(const object::MachOObjectFile &Obj);
MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT);
LinkGraph &getGraph() const { return *G; }

View File

@ -26,7 +26,7 @@ namespace {
class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder {
public:
MachOLinkGraphBuilder_arm64(const object::MachOObjectFile &Obj)
: MachOLinkGraphBuilder(Obj),
: MachOLinkGraphBuilder(Obj, Triple("arm64-apple-darwin")),
NumSymbols(Obj.getSymtabLoadCommand().nsyms) {}
private:
@ -501,22 +501,15 @@ class MachOJITLinker_arm64 : public JITLinker<MachOJITLinker_arm64> {
public:
MachOJITLinker_arm64(std::unique_ptr<JITLinkContext> Ctx,
std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
: JITLinker(std::move(Ctx), std::move(PassConfig)) {}
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
StringRef getEdgeKindName(Edge::Kind R) const override {
return getMachOARM64RelocationKindName(R);
}
Expected<std::unique_ptr<LinkGraph>>
buildGraph(MemoryBufferRef ObjBuffer) override {
auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
if (!MachOObj)
return MachOObj.takeError();
return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
}
static Error targetOutOfRangeError(const Block &B, const Edge &E) {
std::string ErrMsg;
{
@ -681,13 +674,22 @@ private:
uint64_t NullValue = 0;
};
void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx) {
PassConfiguration Config;
Triple TT("arm64-apple-ios");
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer) {
auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
if (!MachOObj)
return MachOObj.takeError();
return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
}
if (Ctx->shouldAddDefaultTargetPasses(TT)) {
void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx) {
PassConfiguration Config;
if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
// Add a mark-live pass.
if (auto MarkLive = Ctx->getMarkLivePass(TT))
if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
@ -699,11 +701,11 @@ void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx) {
});
}
if (auto Err = Ctx->modifyPassConfig(TT, Config))
if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
// Construct a JITLinker and run the link function.
MachOJITLinker_arm64::link(std::move(Ctx), std::move(Config));
MachOJITLinker_arm64::link(std::move(Ctx), std::move(G), std::move(Config));
}
StringRef getMachOARM64RelocationKindName(Edge::Kind R) {

View File

@ -26,7 +26,7 @@ namespace {
class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
public:
MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
: MachOLinkGraphBuilder(Obj) {}
: MachOLinkGraphBuilder(Obj, Triple("x86_64-apple-darwin")) {}
private:
static Expected<MachOX86RelocationKind>
@ -548,22 +548,15 @@ class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
public:
MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
: JITLinker(std::move(Ctx), std::move(PassConfig)) {}
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
StringRef getEdgeKindName(Edge::Kind R) const override {
return getMachOX86RelocationKindName(R);
}
Expected<std::unique_ptr<LinkGraph>>
buildGraph(MemoryBufferRef ObjBuffer) override {
auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
if (!MachOObj)
return MachOObj.takeError();
return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
}
static Error targetOutOfRangeError(const Block &B, const Edge &E) {
std::string ErrMsg;
{
@ -660,18 +653,27 @@ private:
uint64_t NullValue = 0;
};
void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
PassConfiguration Config;
Triple TT("x86_64-apple-macosx");
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer) {
auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
if (!MachOObj)
return MachOObj.takeError();
return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
}
if (Ctx->shouldAddDefaultTargetPasses(TT)) {
void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx) {
PassConfiguration Config;
if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
// Add eh-frame passses.
Config.PrePrunePasses.push_back(EHFrameSplitter("__eh_frame"));
Config.PrePrunePasses.push_back(
EHFrameEdgeFixer("__eh_frame", NegDelta32, Delta64, Delta64));
// Add a mark-live pass.
if (auto MarkLive = Ctx->getMarkLivePass(TT))
if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
@ -686,11 +688,11 @@ void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
Config.PostAllocationPasses.push_back(optimizeMachO_x86_64_GOTAndStubs);
}
if (auto Err = Ctx->modifyPassConfig(TT, Config))
if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
// Construct a JITLinker and run the link function.
MachOJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
MachOJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
}
StringRef getMachOX86RelocationKindName(Edge::Kind R) {

View File

@ -34,16 +34,12 @@ public:
~ObjectLinkingLayerJITLinkContext() {
// If there is an object buffer return function then use it to
// return ownership of the buffer.
if (Layer.ReturnObjectBuffer)
if (Layer.ReturnObjectBuffer && ObjBuffer)
Layer.ReturnObjectBuffer(std::move(ObjBuffer));
}
JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
MemoryBufferRef getObjectBuffer() const override {
return ObjBuffer->getMemBufferRef();
}
void notifyFailed(Error Err) override {
for (auto &P : Layer.Plugins)
Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
@ -463,8 +459,19 @@ ObjectLinkingLayer::~ObjectLinkingLayer() {
void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) {
assert(O && "Object must not be null");
jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
*this, std::move(R), std::move(O)));
auto ObjBuffer = O->getMemBufferRef();
auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
*this, std::move(R), std::move(O));
if (auto G = createLinkGraphFromObject(std::move(ObjBuffer)))
link(std::move(*G), std::move(Ctx));
else
Ctx->notifyFailed(G.takeError());
}
void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<LinkGraph> G) {
link(std::move(G), std::make_unique<ObjectLinkingLayerJITLinkContext>(
*this, std::move(R), nullptr));
}
void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,

View File

@ -20,8 +20,9 @@ static auto RWFlags =
TEST(LinkGraphTest, Construction) {
// Check that LinkGraph construction works as expected.
LinkGraph G("foo", 8, support::little);
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
EXPECT_EQ(G.getName(), "foo");
EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin");
EXPECT_EQ(G.getPointerSize(), 8U);
EXPECT_EQ(G.getEndianness(), support::little);
EXPECT_TRUE(llvm::empty(G.external_symbols()));
@ -38,7 +39,7 @@ TEST(LinkGraphTest, BlockAndSymbolIteration) {
0x1C, 0x1D, 0x1E, 0x1F, 0x00};
StringRef BlockContent(BlockContentBytes);
LinkGraph G("foo", 8, support::little);
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
auto &Sec1 = G.createSection("__data.1", RWFlags);
auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0);
auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0);
@ -90,7 +91,7 @@ TEST(LinkGraphTest, SplitBlock) {
0x1C, 0x1D, 0x1E, 0x1F, 0x00};
StringRef BlockContent(BlockContentBytes);
LinkGraph G("foo", 8, support::little);
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
auto &Sec = G.createSection("__data", RWFlags);
// Create the block to split.