LLVM: lib/ExecutionEngine/JITLink/COFF_x86_64.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
21
22#define DEBUG_TYPE "jitlink"
23
24using namespace llvm;
26
27namespace {
28
29enum EdgeKind_coff_x86_64 : Edge::Kind {
31 Pointer32NB,
32 Pointer64,
33 SectionIdx16,
34 SecRel32,
35};
36
37class COFFJITLinker_x86_64 : public JITLinker<COFFJITLinker_x86_64> {
38 friend class JITLinker<COFFJITLinker_x86_64>;
39
40public:
41 COFFJITLinker_x86_64(std::unique_ptr Ctx,
42 std::unique_ptr G,
44 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
45
46private:
49 }
50};
51
53private:
54 Error addRelocations() override {
56
57 for (const auto &RelSect : sections())
59 RelSect, this, &COFFLinkGraphBuilder_x86_64::addSingleRelocation))
60 return Err;
61
63 }
64
67 Block &BlockToFix) {
70 if (SymbolIt == getObject().symbol_end()) {
72 formatv("Invalid symbol index in relocation entry. "
73 "index: {0}, section: {1}",
76 }
77
79 COFFSymbolIndex SymIndex = getObject().getSymbolIndex(COFFSymbol);
80
81 Symbol *GraphSymbol = getGraphSymbol(SymIndex);
82 if (!GraphSymbol)
84 formatv("Could not find symbol at given index, did you add it to "
85 "JITSymbolTable? index: {0}, section: {1}",
86 SymIndex, FixupSect.getIndex()),
88
89 int64_t Addend = 0;
92 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
93
94 Edge::Kind Kind = Edge::Invalid;
97
100 if (!ImageBase)
101 ImageBase = &addImageBaseSymbol();
102 Kind = EdgeKind_coff_x86_64::Pointer32NB;
104 break;
105 }
107 Kind = EdgeKind_coff_x86_64::PCRel32;
109 break;
110 }
112 Kind = EdgeKind_coff_x86_64::PCRel32;
114 Addend -= 1;
115 break;
116 }
118 Kind = EdgeKind_coff_x86_64::PCRel32;
120 Addend -= 2;
121 break;
122 }
124 Kind = EdgeKind_coff_x86_64::PCRel32;
126 Addend -= 3;
127 break;
128 }
130 Kind = EdgeKind_coff_x86_64::PCRel32;
132 Addend -= 4;
133 break;
134 }
136 Kind = EdgeKind_coff_x86_64::PCRel32;
138 Addend -= 5;
139 break;
140 }
142 Kind = EdgeKind_coff_x86_64::Pointer64;
144 break;
145 }
147 Kind = EdgeKind_coff_x86_64::SectionIdx16;
150 if (COFFSymbol.isAbsolute())
151 SectionIdx = getObject().getNumberOfSections() + 1;
152 else
153 SectionIdx = COFFSymbol.getSectionNumber();
154
155 auto *AbsSym = &getGraph().addAbsoluteSymbol(
158 GraphSymbol = AbsSym;
159 break;
160 }
162
165 Kind = EdgeKind_coff_x86_64::SecRel32;
167 break;
168 }
169 default: {
172 }
173 };
174
175 Edge GE(Kind, Offset, *GraphSymbol, Addend);
177 dbgs() << " ";
179 dbgs() << "\n";
180 });
181
182 BlockToFix.addEdge(std::move(GE));
183
185 }
186
187public:
189 std::shared_ptrorc::SymbolStringPool SSP,
192 std::move(Features),
194};
195
196class COFFLinkGraphLowering_x86_64 {
197public:
198
200 for (auto *B : G.blocks()) {
201 for (auto &E : B->edges()) {
202 switch (E.getKind()) {
203 case EdgeKind_coff_x86_64::Pointer32NB: {
204 auto ImageBase = GetImageBase(G);
205 assert(ImageBase && "__ImageBase symbol must be defined");
206 E.setAddend(E.getAddend() - ImageBase->getAddress().getValue());
208 break;
209 }
210 case EdgeKind_coff_x86_64::PCRel32: {
212 break;
213 }
214 case EdgeKind_coff_x86_64::Pointer64: {
216 break;
217 }
218 case EdgeKind_coff_x86_64::SectionIdx16: {
220 break;
221 }
222 case EdgeKind_coff_x86_64::SecRel32: {
223 E.setAddend(E.getAddend() -
224 getSectionStart(E.getTarget().getSection()).getValue());
226 break;
227 }
228 default:
229 break;
230 }
231 }
232 }
234 }
235
236private:
238 auto [It, Inserted] = SectionStartCache.try_emplace(&Sec);
239 if (Inserted) {
241 It->second = Range.getStart();
242 }
243 return It->second;
244 }
245
248};
249}
250
251namespace llvm {
253
254
256 switch (R) {
257 case PCRel32:
258 return "PCRel32";
259 case Pointer32NB:
260 return "Pointer32NB";
261 case Pointer64:
262 return "Pointer64";
263 case SectionIdx16:
264 return "SectionIdx16";
265 case SecRel32:
266 return "SecRel32";
267 default:
269 }
270}
271
273 MemoryBufferRef ObjectBuffer, std::shared_ptrorc::SymbolStringPool SSP) {
275 dbgs() << "Building jitlink graph for new input "
277 });
278
280 if (!COFFObj)
281 return COFFObj.takeError();
282
283 auto Features = (*COFFObj)->getFeatures();
284 if (!Features)
285 return Features.takeError();
286
287 return COFFLinkGraphBuilder_x86_64(**COFFObj, std::move(SSP),
288 (*COFFObj)->makeTriple(),
289 std::move(*Features))
290 .buildGraph();
291}
292
294 std::unique_ptr Ctx) {
296 const Triple &TT = G->getTargetTriple();
297 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
298
299 if (auto MarkLive = Ctx->getMarkLivePass(TT)) {
300 Config.PrePrunePasses.push_back(std::move(MarkLive));
302 } else
304
305
306 Config.PreFixupPasses.push_back(COFFLinkGraphLowering_x86_64());
307 }
308
309 if (auto Err = Ctx->modifyPassConfig(*G, Config))
310 return Ctx->notifyFailed(std::move(Err));
311
312 COFFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
313}
314
315}
316}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
bbsections Prepares for basic block sections
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, const uint64_t Size=sizeof(T))
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
StringRef getBufferIdentifier() const
Manages the enabling and disabling of subtarget specific features.
Triple - Helper class for working with autoconf configuration names.
orc::ExecutorAddr getAddress() const
An Addressable with content and edges.
ArrayRef< char > getContent() const
Get the content for this block. Block must not be a zero-fill block.
void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)
Add an edge to this block.
Error forEachRelocation(const object::SectionRef &RelSec, RelocHandlerFunction &&Func, bool ProcessDebugSections=false)
Traverse all matching relocation records in the given section.
Represents fixups and constraints in the LinkGraph.
This pass adds keep-alive edge from SEH frame sections to the parent function content block.
Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...
Represents an object file section.
bool isDefined() const
Returns true if this Symbol has content (potentially) defined within this object file (i....
static Expected< std::unique_ptr< COFFObjectFile > > createCOFFObjectFile(MemoryBufferRef Object)
This is a value type class that represents a single relocation in the list of relocations in the obje...
uint64_t getOffset() const
symbol_iterator getSymbol() const
This is a value type class that represents a single section in the list of sections in the object fil...
uint64_t getIndex() const
uint64_t getAddress() const
Represents an address in the executor process.
@ IMAGE_REL_AMD64_REL32_5
@ IMAGE_REL_AMD64_REL32_3
@ IMAGE_REL_AMD64_ADDR32NB
@ IMAGE_REL_AMD64_SECTION
@ IMAGE_REL_AMD64_REL32_2
@ IMAGE_REL_AMD64_REL32_1
@ IMAGE_REL_AMD64_REL32_4
LLVM_ABI const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given x86-64 edge.
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const Symbol *GOTSymbol)
Apply fixup expression for edge to block content.
@ Pointer32
A plain 32-bit pointer value relocation.
@ PCRel32
A 32-bit PC-relative relocation.
@ Pointer16
A plain 16-bit pointer value relocation.
@ Pointer64
A plain 64-bit pointer value relocation.
@ FirstPlatformRelocation
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromCOFFObject_x86_64(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from an COFF/x86-64 relocatable object.
Definition COFF_x86_64.cpp:272
LLVM_ABI Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
void link_COFF_x86_64(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be a COFF x86-64 object file.
Definition COFF_x86_64.cpp:293
LLVM_ABI void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
const char * getCOFFX86RelocationKindName(Edge::Kind R)
Return the string name of the given COFF x86-64 edge kind.
Definition COFF_x86_64.cpp:255
detail::packed_endian_specific_integral< int16_t, llvm::endianness::little, unaligned > little16_t
detail::packed_endian_specific_integral< int32_t, llvm::endianness::little, unaligned > little32_t
detail::packed_endian_specific_integral< int64_t, llvm::endianness::little, unaligned > little64_t
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PreFixupPasses
Pre-fixup passes.
LinkGraphPassList PrePrunePasses
Pre-prune passes.
support::ulittle32_t SymbolTableIndex