diff options
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; |