aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h10
-rw-r--r--llvm/include/llvm/ExecutionEngine/Orc/SectCreate.h61
-rw-r--r--llvm/lib/ExecutionEngine/Orc/CMakeLists.txt1
-rw-r--r--llvm/lib/ExecutionEngine/Orc/SectCreate.cpp52
-rw-r--r--llvm/test/ExecutionEngine/JITLink/Generic/Inputs/sectcreate-data.txt1
-rw-r--r--llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test8
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink.cpp61
7 files changed, 194 insertions, 0 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
index f4d2f56..30a9383 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
@@ -1008,6 +1008,16 @@ public:
: LinkGraph(std::move(Name), TT, SubtargetFeatures(), PointerSize,
Endianness, GetEdgeKindName) {}
+ LinkGraph(std::string Name, const Triple &TT,
+ GetEdgeKindNameFunction GetEdgeKindName)
+ : LinkGraph(std::move(Name), TT, SubtargetFeatures(),
+ Triple::getArchPointerBitWidth(TT.getArch()) / 8,
+ TT.isLittleEndian() ? endianness::little : endianness::big,
+ GetEdgeKindName) {
+ assert(!(Triple::getArchPointerBitWidth(TT.getArch()) % 8) &&
+ "Arch bitwidth is not a multiple of 8");
+ }
+
LinkGraph(const LinkGraph &) = delete;
LinkGraph &operator=(const LinkGraph &) = delete;
LinkGraph(LinkGraph &&) = delete;
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SectCreate.h b/llvm/include/llvm/ExecutionEngine/Orc/SectCreate.h
new file mode 100644
index 0000000..c425424
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SectCreate.h
@@ -0,0 +1,61 @@
+//===---- SectCreate.h -- Emulates ld64's -sectcreate option ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Emulates ld64's -sectcreate option.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H
+#define LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+
+#include <utility>
+#include <vector>
+
+namespace llvm::orc {
+
+class SectCreateMaterializationUnit : public MaterializationUnit {
+public:
+ struct ExtraSymbolInfo {
+ JITSymbolFlags Flags;
+ size_t Offset = 0;
+ };
+
+ using ExtraSymbolsMap = DenseMap<SymbolStringPtr, ExtraSymbolInfo>;
+
+ SectCreateMaterializationUnit(
+ ObjectLinkingLayer &ObjLinkingLayer, std::string SectName, MemProt MP,
+ uint64_t Alignment, std::unique_ptr<MemoryBuffer> Data,
+ ExtraSymbolsMap ExtraSymbols = ExtraSymbolsMap())
+ : MaterializationUnit(getInterface(ExtraSymbols)),
+ ObjLinkingLayer(ObjLinkingLayer), SectName(std::move(SectName)), MP(MP),
+ Alignment(Alignment), Data(std::move(Data)),
+ ExtraSymbols(std::move(ExtraSymbols)) {}
+
+ StringRef getName() const override { return "SectCreate"; }
+
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
+
+private:
+ void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
+
+ static Interface getInterface(const ExtraSymbolsMap &ExtraSymbols);
+
+ ObjectLinkingLayer &ObjLinkingLayer;
+ std::string SectName;
+ MemProt MP;
+ uint64_t Alignment;
+ std::unique_ptr<MemoryBuffer> Data;
+ ExtraSymbolsMap ExtraSymbols;
+};
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index fdb628a..f36605b 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -41,6 +41,7 @@ add_llvm_component_library(LLVMOrcJIT
OrcABISupport.cpp
OrcV2CBindings.cpp
RTDyldObjectLinkingLayer.cpp
+ SectCreate.cpp
SimpleRemoteEPC.cpp
Speculation.cpp
SpeculateAnalyses.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/SectCreate.cpp b/llvm/lib/ExecutionEngine/Orc/SectCreate.cpp
new file mode 100644
index 0000000..4f28b8b
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/SectCreate.cpp
@@ -0,0 +1,52 @@
+//===--------- SectCreate.cpp - Emulate ld64's -sectcreate option ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/SectCreate.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm::jitlink;
+
+namespace llvm::orc {
+
+void SectCreateMaterializationUnit::materialize(
+ std::unique_ptr<MaterializationResponsibility> R) {
+ auto G = std::make_unique<LinkGraph>(
+ "orc_sectcreate_" + SectName,
+ ObjLinkingLayer.getExecutionSession().getTargetTriple(),
+ getGenericEdgeKindName);
+
+ auto &Sect = G->createSection(SectName, MP);
+ auto Content = G->allocateContent(
+ ArrayRef<char>(Data->getBuffer().data(), Data->getBuffer().size()));
+ auto &B = G->createContentBlock(Sect, Content, ExecutorAddr(), Alignment, 0);
+
+ for (auto &[Name, Info] : ExtraSymbols) {
+ auto L = Info.Flags.isStrong() ? Linkage::Strong : Linkage::Weak;
+ auto S = Info.Flags.isExported() ? Scope::Default : Scope::Hidden;
+ G->addDefinedSymbol(B, Info.Offset, *Name, 0, L, S, Info.Flags.isCallable(),
+ true);
+ }
+
+ ObjLinkingLayer.emit(std::move(R), std::move(G));
+}
+
+void SectCreateMaterializationUnit::discard(const JITDylib &JD,
+ const SymbolStringPtr &Name) {
+ ExtraSymbols.erase(Name);
+}
+
+MaterializationUnit::Interface SectCreateMaterializationUnit::getInterface(
+ const ExtraSymbolsMap &ExtraSymbols) {
+ SymbolFlagsMap SymbolFlags;
+ for (auto &[Name, Info] : ExtraSymbols)
+ SymbolFlags[Name] = Info.Flags;
+ return {std::move(SymbolFlags), nullptr};
+}
+
+} // End namespace llvm::orc.
diff --git a/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/sectcreate-data.txt b/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/sectcreate-data.txt
new file mode 100644
index 0000000..bcaec87
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/sectcreate-data.txt
@@ -0,0 +1 @@
+**ZZ \ No newline at end of file
diff --git a/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test b/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test
new file mode 100644
index 0000000..2448271
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test
@@ -0,0 +1,8 @@
+# RUN: llc -filetype=obj -o %t.o %S/Inputs/main-ret-0.ll
+# RUN: llvm-jitlink -noexec \
+# RUN: -sectcreate __data,%S/Inputs/sectcreate-data.txt:foo=0 \
+# RUN: %t.o
+#
+# Use -sectcreate to create a section from a data file.
+
+# jitlink-check: *{4}foo = 0x2a2a5a5a \ No newline at end of file
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 769ed17..f628077 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -30,6 +30,7 @@
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
+#include "llvm/ExecutionEngine/Orc/SectCreate.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
@@ -162,6 +163,12 @@ static cl::list<std::string>
cl::desc("Inject symbol aliases (syntax: <alias-name>=<aliasee>)"),
cl::cat(JITLinkCategory));
+static cl::list<std::string>
+ SectCreate("sectcreate",
+ cl::desc("given <sectname>,<filename>[:<sym>=<offset>,...] "
+ "add the content of <filename> to <sectname>"),
+ cl::cat(JITLinkCategory));
+
static cl::list<std::string> TestHarnesses("harness", cl::Positional,
cl::desc("Test harness files"),
cl::PositionalEatsArgs,
@@ -1666,6 +1673,57 @@ static Error addAliases(Session &S,
return Error::success();
}
+static Error addSectCreates(Session &S,
+ const std::map<unsigned, JITDylib *> &IdxToJD) {
+ for (auto SCItr = SectCreate.begin(), SCEnd = SectCreate.end();
+ SCItr != SCEnd; ++SCItr) {
+
+ unsigned SCArgIdx = SectCreate.getPosition(SCItr - SectCreate.begin());
+ auto &JD = *std::prev(IdxToJD.lower_bound(SCArgIdx))->second;
+
+ StringRef SCArg(*SCItr);
+
+ auto [SectAndFileName, ExtraSymbolsString] = SCArg.split(':');
+ auto [SectName, FileName] = SectAndFileName.rsplit(',');
+ if (SectName.empty())
+ return make_error<StringError>("In -sectcreate=" + SCArg +
+ ", filename component cannot be empty",
+ inconvertibleErrorCode());
+ if (FileName.empty())
+ return make_error<StringError>("In -sectcreate=" + SCArg +
+ ", filename component cannot be empty",
+ inconvertibleErrorCode());
+
+ auto Content = MemoryBuffer::getFile(FileName);
+ if (!Content)
+ return createFileError(FileName, errorCodeToError(Content.getError()));
+
+ SectCreateMaterializationUnit::ExtraSymbolsMap ExtraSymbols;
+ while (!ExtraSymbolsString.empty()) {
+ StringRef NextSymPair;
+ std::tie(NextSymPair, ExtraSymbolsString) = ExtraSymbolsString.split(',');
+
+ auto [Sym, OffsetString] = NextSymPair.split('=');
+ size_t Offset;
+
+ if (OffsetString.getAsInteger(0, Offset))
+ return make_error<StringError>("In -sectcreate=" + SCArg + ", " +
+ OffsetString +
+ " is not a valid integer",
+ inconvertibleErrorCode());
+
+ ExtraSymbols[S.ES.intern(Sym)] = {JITSymbolFlags::Exported, Offset};
+ }
+
+ if (auto Err = JD.define(std::make_unique<SectCreateMaterializationUnit>(
+ S.ObjLayer, SectName.str(), MemProt::Read, 16, std::move(*Content),
+ std::move(ExtraSymbols))))
+ return Err;
+ }
+
+ return Error::success();
+}
+
static Error addTestHarnesses(Session &S) {
LLVM_DEBUG(dbgs() << "Adding test harness objects...\n");
for (auto HarnessFile : TestHarnesses) {
@@ -2016,6 +2074,9 @@ static Error addSessionInputs(Session &S) {
if (auto Err = addAliases(S, IdxToJD))
return Err;
+ if (auto Err = addSectCreates(S, IdxToJD))
+ return Err;
+
if (!TestHarnesses.empty())
if (auto Err = addTestHarnesses(S))
return Err;