Skip to content

Commit c625b99

Browse files
committed
[ORC] Add SectCreateMaterializationUnit, llvm-jitlink -sectcreate option.
The SectCreateMaterializationUnit creates a LinkGraph with a single named section containing a single named block whose content is given by a MemoryBuffer. It is intended to support emulation of ld64's -sectcreate option.
1 parent 5454991 commit c625b99

File tree

7 files changed

+194
-0
lines changed

7 files changed

+194
-0
lines changed

llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,16 @@ class LinkGraph {
10081008
: LinkGraph(std::move(Name), TT, SubtargetFeatures(), PointerSize,
10091009
Endianness, GetEdgeKindName) {}
10101010

1011+
LinkGraph(std::string Name, const Triple &TT,
1012+
GetEdgeKindNameFunction GetEdgeKindName)
1013+
: LinkGraph(std::move(Name), TT, SubtargetFeatures(),
1014+
Triple::getArchPointerBitWidth(TT.getArch()) / 8,
1015+
TT.isLittleEndian() ? endianness::little : endianness::big,
1016+
GetEdgeKindName) {
1017+
assert(!(Triple::getArchPointerBitWidth(TT.getArch()) % 8) &&
1018+
"Arch bitwidth is not a multiple of 8");
1019+
}
1020+
10111021
LinkGraph(const LinkGraph &) = delete;
10121022
LinkGraph &operator=(const LinkGraph &) = delete;
10131023
LinkGraph(LinkGraph &&) = delete;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===---- SectCreate.h -- Emulates ld64's -sectcreate option ----*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Emulates ld64's -sectcreate option.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H
14+
#define LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H
15+
16+
#include "llvm/ExecutionEngine/Orc/Core.h"
17+
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
18+
19+
#include <utility>
20+
#include <vector>
21+
22+
namespace llvm::orc {
23+
24+
class SectCreateMaterializationUnit : public MaterializationUnit {
25+
public:
26+
struct ExtraSymbolInfo {
27+
JITSymbolFlags Flags;
28+
size_t Offset = 0;
29+
};
30+
31+
using ExtraSymbolsMap = DenseMap<SymbolStringPtr, ExtraSymbolInfo>;
32+
33+
SectCreateMaterializationUnit(
34+
ObjectLinkingLayer &ObjLinkingLayer, std::string SectName, MemProt MP,
35+
uint64_t Alignment, std::unique_ptr<MemoryBuffer> Data,
36+
ExtraSymbolsMap ExtraSymbols = ExtraSymbolsMap())
37+
: MaterializationUnit(getInterface(ExtraSymbols)),
38+
ObjLinkingLayer(ObjLinkingLayer), SectName(std::move(SectName)), MP(MP),
39+
Alignment(Alignment), Data(std::move(Data)),
40+
ExtraSymbols(std::move(ExtraSymbols)) {}
41+
42+
StringRef getName() const override { return "SectCreate"; }
43+
44+
void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
45+
46+
private:
47+
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
48+
49+
static Interface getInterface(const ExtraSymbolsMap &ExtraSymbols);
50+
51+
ObjectLinkingLayer &ObjLinkingLayer;
52+
std::string SectName;
53+
MemProt MP;
54+
uint64_t Alignment;
55+
std::unique_ptr<MemoryBuffer> Data;
56+
ExtraSymbolsMap ExtraSymbols;
57+
};
58+
59+
} // namespace llvm::orc
60+
61+
#endif // LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H

llvm/lib/ExecutionEngine/Orc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ add_llvm_component_library(LLVMOrcJIT
4141
OrcABISupport.cpp
4242
OrcV2CBindings.cpp
4343
RTDyldObjectLinkingLayer.cpp
44+
SectCreate.cpp
4445
SimpleRemoteEPC.cpp
4546
Speculation.cpp
4647
SpeculateAnalyses.cpp
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===--------- SectCreate.cpp - Emulate ld64's -sectcreate option ---------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/ExecutionEngine/Orc/SectCreate.h"
10+
11+
#define DEBUG_TYPE "orc"
12+
13+
using namespace llvm::jitlink;
14+
15+
namespace llvm::orc {
16+
17+
void SectCreateMaterializationUnit::materialize(
18+
std::unique_ptr<MaterializationResponsibility> R) {
19+
auto G = std::make_unique<LinkGraph>(
20+
"orc_sectcreate_" + SectName,
21+
ObjLinkingLayer.getExecutionSession().getTargetTriple(),
22+
getGenericEdgeKindName);
23+
24+
auto &Sect = G->createSection(SectName, MP);
25+
auto Content = G->allocateContent(
26+
ArrayRef<char>(Data->getBuffer().data(), Data->getBuffer().size()));
27+
auto &B = G->createContentBlock(Sect, Content, ExecutorAddr(), Alignment, 0);
28+
29+
for (auto &[Name, Info] : ExtraSymbols) {
30+
auto L = Info.Flags.isStrong() ? Linkage::Strong : Linkage::Weak;
31+
auto S = Info.Flags.isExported() ? Scope::Default : Scope::Hidden;
32+
G->addDefinedSymbol(B, Info.Offset, *Name, 0, L, S, Info.Flags.isCallable(),
33+
true);
34+
}
35+
36+
ObjLinkingLayer.emit(std::move(R), std::move(G));
37+
}
38+
39+
void SectCreateMaterializationUnit::discard(const JITDylib &JD,
40+
const SymbolStringPtr &Name) {
41+
ExtraSymbols.erase(Name);
42+
}
43+
44+
MaterializationUnit::Interface SectCreateMaterializationUnit::getInterface(
45+
const ExtraSymbolsMap &ExtraSymbols) {
46+
SymbolFlagsMap SymbolFlags;
47+
for (auto &[Name, Info] : ExtraSymbols)
48+
SymbolFlags[Name] = Info.Flags;
49+
return {std::move(SymbolFlags), nullptr};
50+
}
51+
52+
} // End namespace llvm::orc.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**ZZ
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# RUN: llc -filetype=obj -o %t.o %S/Inputs/main-ret-0.ll
2+
# RUN: llvm-jitlink -noexec \
3+
# RUN: -sectcreate __data,%S/Inputs/sectcreate-data.txt:foo=0 \
4+
# RUN: %t.o
5+
#
6+
# Use -sectcreate to create a section from a data file.
7+
8+
# jitlink-check: *{4}foo = 0x2a2a5a5a

llvm/tools/llvm-jitlink/llvm-jitlink.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
3131
#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
3232
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
33+
#include "llvm/ExecutionEngine/Orc/SectCreate.h"
3334
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
3435
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
3536
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
@@ -162,6 +163,12 @@ static cl::list<std::string>
162163
cl::desc("Inject symbol aliases (syntax: <alias-name>=<aliasee>)"),
163164
cl::cat(JITLinkCategory));
164165

166+
static cl::list<std::string>
167+
SectCreate("sectcreate",
168+
cl::desc("given <sectname>,<filename>[:<sym>=<offset>,...] "
169+
"add the content of <filename> to <sectname>"),
170+
cl::cat(JITLinkCategory));
171+
165172
static cl::list<std::string> TestHarnesses("harness", cl::Positional,
166173
cl::desc("Test harness files"),
167174
cl::PositionalEatsArgs,
@@ -1666,6 +1673,57 @@ static Error addAliases(Session &S,
16661673
return Error::success();
16671674
}
16681675

1676+
static Error addSectCreates(Session &S,
1677+
const std::map<unsigned, JITDylib *> &IdxToJD) {
1678+
for (auto SCItr = SectCreate.begin(), SCEnd = SectCreate.end();
1679+
SCItr != SCEnd; ++SCItr) {
1680+
1681+
unsigned SCArgIdx = SectCreate.getPosition(SCItr - SectCreate.begin());
1682+
auto &JD = *std::prev(IdxToJD.lower_bound(SCArgIdx))->second;
1683+
1684+
StringRef SCArg(*SCItr);
1685+
1686+
auto [SectAndFileName, ExtraSymbolsString] = SCArg.split(':');
1687+
auto [SectName, FileName] = SectAndFileName.rsplit(',');
1688+
if (SectName.empty())
1689+
return make_error<StringError>("In -sectcreate=" + SCArg +
1690+
", filename component cannot be empty",
1691+
inconvertibleErrorCode());
1692+
if (FileName.empty())
1693+
return make_error<StringError>("In -sectcreate=" + SCArg +
1694+
", filename component cannot be empty",
1695+
inconvertibleErrorCode());
1696+
1697+
auto Content = MemoryBuffer::getFile(FileName);
1698+
if (!Content)
1699+
return createFileError(FileName, errorCodeToError(Content.getError()));
1700+
1701+
SectCreateMaterializationUnit::ExtraSymbolsMap ExtraSymbols;
1702+
while (!ExtraSymbolsString.empty()) {
1703+
StringRef NextSymPair;
1704+
std::tie(NextSymPair, ExtraSymbolsString) = ExtraSymbolsString.split(',');
1705+
1706+
auto [Sym, OffsetString] = NextSymPair.split('=');
1707+
size_t Offset;
1708+
1709+
if (OffsetString.getAsInteger(0, Offset))
1710+
return make_error<StringError>("In -sectcreate=" + SCArg + ", " +
1711+
OffsetString +
1712+
" is not a valid integer",
1713+
inconvertibleErrorCode());
1714+
1715+
ExtraSymbols[S.ES.intern(Sym)] = {JITSymbolFlags::Exported, Offset};
1716+
}
1717+
1718+
if (auto Err = JD.define(std::make_unique<SectCreateMaterializationUnit>(
1719+
S.ObjLayer, SectName.str(), MemProt::Read, 16, std::move(*Content),
1720+
std::move(ExtraSymbols))))
1721+
return Err;
1722+
}
1723+
1724+
return Error::success();
1725+
}
1726+
16691727
static Error addTestHarnesses(Session &S) {
16701728
LLVM_DEBUG(dbgs() << "Adding test harness objects...\n");
16711729
for (auto HarnessFile : TestHarnesses) {
@@ -2016,6 +2074,9 @@ static Error addSessionInputs(Session &S) {
20162074
if (auto Err = addAliases(S, IdxToJD))
20172075
return Err;
20182076

2077+
if (auto Err = addSectCreates(S, IdxToJD))
2078+
return Err;
2079+
20192080
if (!TestHarnesses.empty())
20202081
if (auto Err = addTestHarnesses(S))
20212082
return Err;

0 commit comments

Comments
 (0)