1//===------- ELFLinkGraphBuilder.h - ELF LinkGraph builder ------*- 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// Generic ELF LinkGraph building code.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
14#define LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
15
16#include "llvm/ExecutionEngine/JITLink/JITLink.h"
17#include "llvm/Object/ELF.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/Error.h"
20#include "llvm/Support/FormatVariadic.h"
21
22#define DEBUG_TYPE "jitlink"
23
24namespace llvm {
25namespace jitlink {
26
27/// Common link-graph building code shared between all ELFFiles.
28class ELFLinkGraphBuilderBase {
29public:
30 ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}
31 virtual ~ELFLinkGraphBuilderBase();
32
33protected:
34 static bool isDwarfSection(StringRef SectionName) {
35 return llvm::is_contained(Range&: DwarfSectionNames, Element: SectionName);
36 }
37
38 Section &getCommonSection() {
39 if (!CommonSection)
40 CommonSection = &G->createSection(
41 Name: CommonSectionName, Prot: orc::MemProt::Read | orc::MemProt::Write);
42 return *CommonSection;
43 }
44
45 std::unique_ptr<LinkGraph> G;
46
47private:
48 static StringRef CommonSectionName;
49 static ArrayRef<const char *> DwarfSectionNames;
50
51 Section *CommonSection = nullptr;
52};
53
54/// LinkGraph building code that's specific to the given ELFT, but common
55/// across all architectures.
56template <typename ELFT>
57class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
58 using ELFFile = object::ELFFile<ELFT>;
59
60public:
61 ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj,
62 std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
63 SubtargetFeatures Features, StringRef FileName,
64 LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
65
66 /// Debug sections are included in the graph by default. Use
67 /// setProcessDebugSections(false) to ignore them if debug info is not
68 /// needed.
69 ELFLinkGraphBuilder &setProcessDebugSections(bool ProcessDebugSections) {
70 this->ProcessDebugSections = ProcessDebugSections;
71 return *this;
72 }
73
74 /// Attempt to construct and return the LinkGraph.
75 Expected<std::unique_ptr<LinkGraph>> buildGraph();
76
77 /// Call to derived class to handle relocations. These require
78 /// architecture specific knowledge to map to JITLink edge kinds.
79 virtual Error addRelocations() = 0;
80
81protected:
82 using ELFSectionIndex = unsigned;
83 using ELFSymbolIndex = unsigned;
84
85 bool isRelocatable() const {
86 return Obj.getHeader().e_type == llvm::ELF::ET_REL;
87 }
88
89 void setGraphBlock(ELFSectionIndex SecIndex, Block *B) {
90 assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index");
91 GraphBlocks[SecIndex] = B;
92 }
93
94 Block *getGraphBlock(ELFSectionIndex SecIndex) {
95 return GraphBlocks.lookup(Val: SecIndex);
96 }
97
98 void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
99 assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
100 GraphSymbols[SymIndex] = &Sym;
101 }
102
103 Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
104 return GraphSymbols.lookup(Val: SymIndex);
105 }
106
107 Expected<std::pair<Linkage, Scope>>
108 getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
109
110 /// Set the target flags on the given Symbol.
111 virtual TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) {
112 return TargetFlagsType{};
113 }
114
115 /// Get the physical offset of the symbol on the target platform.
116 virtual orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym,
117 TargetFlagsType Flags) {
118 return Sym.getValue();
119 }
120
121 Error prepare();
122 Error graphifySections();
123 Error graphifySymbols();
124
125 /// Override in derived classes to suppress certain sections in the link
126 /// graph.
127 virtual bool excludeSection(const typename ELFT::Shdr &Sect) const {
128 return false;
129 }
130
131 /// Traverse all matching ELFT::Rela relocation records in the given section.
132 /// The handler function Func should be callable with this signature:
133 /// Error(const typename ELFT::Rela &,
134 /// const typename ELFT::Shdr &, Section &)
135 ///
136 template <typename RelocHandlerMethod>
137 Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
138 RelocHandlerMethod &&Func);
139
140 /// Traverse all matching ELFT::Rel relocation records in the given section.
141 /// The handler function Func should be callable with this signature:
142 /// Error(const typename ELFT::Rel &,
143 /// const typename ELFT::Shdr &, Section &)
144 ///
145 template <typename RelocHandlerMethod>
146 Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
147 RelocHandlerMethod &&Func);
148
149 /// Traverse all matching rela relocation records in the given section.
150 /// Convenience wrapper to allow passing a member function for the handler.
151 ///
152 template <typename ClassT, typename RelocHandlerMethod>
153 Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
154 ClassT *Instance, RelocHandlerMethod &&Method) {
155 return forEachRelaRelocation(
156 RelSect,
157 [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
158 return (Instance->*Method)(Rel, Target, GS);
159 });
160 }
161
162 /// Traverse all matching rel relocation records in the given section.
163 /// Convenience wrapper to allow passing a member function for the handler.
164 ///
165 template <typename ClassT, typename RelocHandlerMethod>
166 Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
167 ClassT *Instance, RelocHandlerMethod &&Method) {
168 return forEachRelRelocation(
169 RelSect,
170 [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
171 return (Instance->*Method)(Rel, Target, GS);
172 });
173 }
174
175 const ELFFile &Obj;
176
177 typename ELFFile::Elf_Shdr_Range Sections;
178 const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
179 StringRef SectionStringTab;
180 bool ProcessDebugSections = true;
181
182 // Maps ELF section indexes to LinkGraph Blocks.
183 // Only SHF_ALLOC sections will have graph blocks.
184 DenseMap<ELFSectionIndex, Block *> GraphBlocks;
185 DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
186 DenseMap<const typename ELFFile::Elf_Shdr *,
187 ArrayRef<typename ELFFile::Elf_Word>>
188 ShndxTables;
189};
190
191template <typename ELFT>
192ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
193 const ELFFile &Obj, std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
194 SubtargetFeatures Features, StringRef FileName,
195 LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
196 : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
197 args: FileName.str(), args: std::move(SSP), args: std::move(TT), args: std::move(Features),
198 args: std::move(GetEdgeKindName))),
199 Obj(Obj) {
200 LLVM_DEBUG(
201 { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });
202}
203
204template <typename ELFT>
205Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
206 if (!isRelocatable())
207 return make_error<JITLinkError>(Args: "Object is not a relocatable ELF file");
208
209 if (auto Err = prepare())
210 return std::move(Err);
211
212 if (auto Err = graphifySections())
213 return std::move(Err);
214
215 if (auto Err = graphifySymbols())
216 return std::move(Err);
217
218 if (auto Err = addRelocations())
219 return std::move(Err);
220
221 return std::move(G);
222}
223
224template <typename ELFT>
225Expected<std::pair<Linkage, Scope>>
226ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
227 const typename ELFT::Sym &Sym, StringRef Name) {
228 Linkage L = Linkage::Strong;
229 Scope S = Scope::Default;
230
231 switch (Sym.getBinding()) {
232 case ELF::STB_LOCAL:
233 S = Scope::Local;
234 break;
235 case ELF::STB_GLOBAL:
236 // Nothing to do here.
237 break;
238 case ELF::STB_WEAK:
239 case ELF::STB_GNU_UNIQUE:
240 L = Linkage::Weak;
241 break;
242 default:
243 return make_error<StringError>(
244 Args: "Unrecognized symbol binding " +
245 Twine(static_cast<int>(Sym.getBinding())) + " for " + Name,
246 Args: inconvertibleErrorCode());
247 }
248
249 switch (Sym.getVisibility()) {
250 case ELF::STV_DEFAULT:
251 case ELF::STV_PROTECTED:
252 // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
253 // Orc support.
254 // Otherwise nothing to do here.
255 break;
256 case ELF::STV_HIDDEN:
257 // Default scope -> Hidden scope. No effect on local scope.
258 if (S == Scope::Default)
259 S = Scope::Hidden;
260 break;
261 case ELF::STV_INTERNAL:
262 return make_error<StringError>(
263 Args: "Unrecognized symbol visibility " +
264 Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name,
265 Args: inconvertibleErrorCode());
266 }
267
268 return std::make_pair(x&: L, y&: S);
269}
270
271template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
272 LLVM_DEBUG(dbgs() << " Preparing to build...\n");
273
274 // Get the sections array.
275 if (auto SectionsOrErr = Obj.sections())
276 Sections = *SectionsOrErr;
277 else
278 return SectionsOrErr.takeError();
279
280 // Get the section string table.
281 if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
282 SectionStringTab = *SectionStringTabOrErr;
283 else
284 return SectionStringTabOrErr.takeError();
285
286 // Get the SHT_SYMTAB section.
287 for (auto &Sec : Sections) {
288 if (Sec.sh_type == ELF::SHT_SYMTAB) {
289 if (!SymTabSec)
290 SymTabSec = &Sec;
291 else
292 return make_error<JITLinkError>(Args: "Multiple SHT_SYMTAB sections in " +
293 G->getName());
294 }
295
296 // Extended table.
297 if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) {
298 uint32_t SymtabNdx = Sec.sh_link;
299 if (SymtabNdx >= Sections.size())
300 return make_error<JITLinkError>(Args: "sh_link is out of bound");
301
302 auto ShndxTable = Obj.getSHNDXTable(Sec);
303 if (!ShndxTable)
304 return ShndxTable.takeError();
305
306 ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
307 }
308 }
309
310 return Error::success();
311}
312
313template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
314 LLVM_DEBUG(dbgs() << " Creating graph sections...\n");
315
316 // For each section...
317 for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
318
319 auto &Sec = Sections[SecIndex];
320
321 // Start by getting the section name.
322 auto Name = Obj.getSectionName(Sec, SectionStringTab);
323 if (!Name)
324 return Name.takeError();
325 if (excludeSection(Sect: Sec)) {
326 LLVM_DEBUG({
327 dbgs() << " " << SecIndex << ": Skipping section \"" << *Name
328 << "\" explicitly\n";
329 });
330 continue;
331 }
332
333 // Skip null sections.
334 if (Sec.sh_type == ELF::SHT_NULL) {
335 LLVM_DEBUG({
336 dbgs() << " " << SecIndex << ": has type SHT_NULL. Skipping.\n";
337 });
338 continue;
339 }
340
341 // If the name indicates that it's a debug section then skip it: We don't
342 // support those yet.
343 if (!ProcessDebugSections && isDwarfSection(SectionName: *Name)) {
344 LLVM_DEBUG({
345 dbgs() << " " << SecIndex << ": \"" << *Name
346 << "\" is a debug section: "
347 "No graph section will be created.\n";
348 });
349 continue;
350 }
351
352 LLVM_DEBUG({
353 dbgs() << " " << SecIndex << ": Creating section for \"" << *Name
354 << "\"\n";
355 });
356
357 // Get the section's memory protection flags.
358 orc::MemProt Prot = orc::MemProt::Read;
359 if (Sec.sh_flags & ELF::SHF_EXECINSTR)
360 Prot |= orc::MemProt::Exec;
361 if (Sec.sh_flags & ELF::SHF_WRITE)
362 Prot |= orc::MemProt::Write;
363
364 // Look for existing sections first.
365 auto *GraphSec = G->findSectionByName(Name: *Name);
366 if (!GraphSec) {
367 GraphSec = &G->createSection(Name: *Name, Prot);
368 // Non-SHF_ALLOC sections get NoAlloc memory lifetimes.
369 if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
370 GraphSec->setMemLifetime(orc::MemLifetime::NoAlloc);
371 LLVM_DEBUG({
372 dbgs() << " " << SecIndex << ": \"" << *Name
373 << "\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
374 });
375 }
376 }
377
378 if (GraphSec->getMemProt() != Prot) {
379 std::string ErrMsg;
380 raw_string_ostream(ErrMsg)
381 << "In " << G->getName() << ", section " << *Name
382 << " is present more than once with different permissions: "
383 << GraphSec->getMemProt() << " vs " << Prot;
384 return make_error<JITLinkError>(Args: std::move(ErrMsg));
385 }
386
387 Block *B = nullptr;
388 if (Sec.sh_type != ELF::SHT_NOBITS) {
389 auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
390 if (!Data)
391 return Data.takeError();
392
393 B = &G->createContentBlock(Parent&: *GraphSec, Content: *Data,
394 Address: orc::ExecutorAddr(Sec.sh_addr),
395 Alignment: Sec.sh_addralign, AlignmentOffset: 0);
396 } else
397 B = &G->createZeroFillBlock(Parent&: *GraphSec, Size: Sec.sh_size,
398 Address: orc::ExecutorAddr(Sec.sh_addr),
399 Alignment: Sec.sh_addralign, AlignmentOffset: 0);
400
401 if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {
402 // Add live symbol to avoid dead-stripping for .ARM.exidx sections
403 G->addAnonymousSymbol(Content&: *B, Offset: orc::ExecutorAddrDiff(),
404 Size: orc::ExecutorAddrDiff(), IsCallable: false, IsLive: true);
405 }
406
407 setGraphBlock(SecIndex, B);
408 }
409
410 return Error::success();
411}
412
413template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
414 LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");
415
416 // No SYMTAB -- Bail out early.
417 if (!SymTabSec)
418 return Error::success();
419
420 // Get the section content as a Symbols array.
421 auto Symbols = Obj.symbols(SymTabSec);
422 if (!Symbols)
423 return Symbols.takeError();
424
425 // Get the string table for this section.
426 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
427 if (!StringTab)
428 return StringTab.takeError();
429
430 LLVM_DEBUG({
431 StringRef SymTabName;
432
433 if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
434 SymTabName = *SymTabNameOrErr;
435 else {
436 dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
437 << toString(SymTabNameOrErr.takeError()) << "\n";
438 SymTabName = "<SHT_SYMTAB section with invalid name>";
439 }
440
441 dbgs() << " Adding symbols from symtab section \"" << SymTabName
442 << "\"\n";
443 });
444
445 for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
446 auto &Sym = (*Symbols)[SymIndex];
447
448 // Check symbol type.
449 switch (Sym.getType()) {
450 case ELF::STT_FILE:
451 LLVM_DEBUG({
452 if (auto Name = Sym.getName(*StringTab))
453 dbgs() << " " << SymIndex << ": Skipping STT_FILE symbol \""
454 << *Name << "\"\n";
455 else {
456 dbgs() << "Could not get STT_FILE symbol name: "
457 << toString(Name.takeError()) << "\n";
458 dbgs() << " " << SymIndex
459 << ": Skipping STT_FILE symbol with invalid name\n";
460 }
461 });
462 continue;
463 break;
464 }
465
466 // Get the symbol name.
467 auto Name = Sym.getName(*StringTab);
468 if (!Name)
469 return Name.takeError();
470
471 // Handle common symbols specially.
472 if (Sym.isCommon()) {
473 Symbol &GSym = G->addDefinedSymbol(
474 G->createZeroFillBlock(Parent&: getCommonSection(), Size: Sym.st_size,
475 Address: orc::ExecutorAddr(), Alignment: Sym.getValue(), AlignmentOffset: 0),
476 0, *Name, Sym.st_size, Linkage::Weak, Scope::Default, false, false);
477 setGraphSymbol(SymIndex, Sym&: GSym);
478 continue;
479 }
480
481 if (Sym.isDefined() &&
482 (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
483 Sym.getType() == ELF::STT_OBJECT ||
484 Sym.getType() == ELF::STT_SECTION || Sym.getType() == ELF::STT_TLS)) {
485
486 // Map Visibility and Binding to Scope and Linkage:
487 Linkage L;
488 Scope S;
489 if (auto LSOrErr = getSymbolLinkageAndScope(Sym, Name: *Name))
490 std::tie(args&: L, args&: S) = *LSOrErr;
491 else
492 return LSOrErr.takeError();
493
494 // Handle extended tables.
495 unsigned Shndx = Sym.st_shndx;
496 if (Shndx == ELF::SHN_XINDEX) {
497 auto ShndxTable = ShndxTables.find(SymTabSec);
498 if (ShndxTable == ShndxTables.end())
499 continue;
500 auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
501 Sym, SymIndex, ShndxTable->second);
502 if (!NdxOrErr)
503 return NdxOrErr.takeError();
504 Shndx = *NdxOrErr;
505 }
506 if (auto *B = getGraphBlock(SecIndex: Shndx)) {
507 LLVM_DEBUG({
508 dbgs() << " " << SymIndex
509 << ": Creating defined graph symbol for ELF symbol \"" << *Name
510 << "\"\n";
511 });
512
513 TargetFlagsType Flags = makeTargetFlags(Sym);
514 orc::ExecutorAddrDiff Offset = getRawOffset(Sym, Flags);
515
516 if (Offset + Sym.st_size > B->getSize()) {
517 std::string ErrMsg;
518 raw_string_ostream ErrStream(ErrMsg);
519 ErrStream << "In " << G->getName() << ", symbol ";
520 if (!Name->empty())
521 ErrStream << *Name;
522 else
523 ErrStream << "<anon>";
524 ErrStream << " (" << (B->getAddress() + Offset) << " -- "
525 << (B->getAddress() + Offset + Sym.st_size) << ") extends "
526 << formatv("{0:x}", Offset + Sym.st_size - B->getSize())
527 << " bytes past the end of its containing block ("
528 << B->getRange() << ")";
529 return make_error<JITLinkError>(Args: std::move(ErrMsg));
530 }
531
532 // In RISCV, temporary symbols (Used to generate dwarf, eh_frame
533 // sections...) will appear in object code's symbol table, and LLVM does
534 // not use names on these temporary symbols (RISCV gnu toolchain uses
535 // names on these temporary symbols). If the symbol is unnamed, add an
536 // anonymous symbol.
537 auto &GSym =
538 Name->empty()
539 ? G->addAnonymousSymbol(Content&: *B, Offset, Size: Sym.st_size,
540 IsCallable: false, IsLive: false)
541 : G->addDefinedSymbol(*B, Offset, *Name, Sym.st_size, L,
542 S, Sym.getType() == ELF::STT_FUNC,
543 false);
544
545 GSym.setTargetFlags(Flags);
546 setGraphSymbol(SymIndex, Sym&: GSym);
547 }
548 } else if (Sym.isUndefined() && Sym.isExternal()) {
549 LLVM_DEBUG({
550 dbgs() << " " << SymIndex
551 << ": Creating external graph symbol for ELF symbol \"" << *Name
552 << "\"\n";
553 });
554
555 if (Sym.getBinding() != ELF::STB_GLOBAL &&
556 Sym.getBinding() != ELF::STB_WEAK)
557 return make_error<StringError>(
558 "Invalid symbol binding " +
559 Twine(static_cast<int>(Sym.getBinding())) +
560 " for external symbol " + *Name,
561 inconvertibleErrorCode());
562
563 // If L is Linkage::Weak that means this is a weakly referenced symbol.
564 auto &GSym = G->addExternalSymbol(*Name, Sym.st_size,
565 Sym.getBinding() == ELF::STB_WEAK);
566 setGraphSymbol(SymIndex, Sym&: GSym);
567 } else if (Sym.isUndefined() && Sym.st_value == 0 && Sym.st_size == 0 &&
568 Sym.getType() == ELF::STT_NOTYPE &&
569 Sym.getBinding() == ELF::STB_LOCAL && Name->empty()) {
570 // Some relocations (e.g., R_RISCV_ALIGN) don't have a target symbol and
571 // use this kind of null symbol as a placeholder.
572 LLVM_DEBUG({
573 dbgs() << " " << SymIndex << ": Creating null graph symbol\n";
574 });
575
576 auto SymName =
577 G->allocateContent(Source: "__jitlink_ELF_SYM_UND_" + Twine(SymIndex));
578 auto SymNameRef = StringRef(SymName.data(), SymName.size());
579 auto &GSym = G->addAbsoluteSymbol(Name: SymNameRef, Address: orc::ExecutorAddr(0), Size: 0,
580 L: Linkage::Strong, S: Scope::Local, IsLive: false);
581 setGraphSymbol(SymIndex, Sym&: GSym);
582 } else {
583 LLVM_DEBUG({
584 dbgs() << " " << SymIndex
585 << ": Not creating graph symbol for ELF symbol \"" << *Name
586 << "\" with unrecognized type\n";
587 });
588 }
589 }
590
591 return Error::success();
592}
593
594template <typename ELFT>
595template <typename RelocHandlerFunction>
596Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
597 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
598 // Only look into sections that store relocation entries.
599 if (RelSect.sh_type != ELF::SHT_RELA)
600 return Error::success();
601
602 // sh_info contains the section header index of the target (FixupSection),
603 // which is the section to which all relocations in RelSect apply.
604 auto FixupSection = Obj.getSection(RelSect.sh_info);
605 if (!FixupSection)
606 return FixupSection.takeError();
607
608 // Target sections have names in valid ELF object files.
609 Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
610 if (!Name)
611 return Name.takeError();
612 LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
613
614 // Consider skipping these relocations.
615 if (!ProcessDebugSections && isDwarfSection(SectionName: *Name)) {
616 LLVM_DEBUG(dbgs() << " skipped (dwarf section)\n\n");
617 return Error::success();
618 }
619 if (excludeSection(Sect: **FixupSection)) {
620 LLVM_DEBUG(dbgs() << " skipped (fixup section excluded explicitly)\n\n");
621 return Error::success();
622 }
623
624 // Lookup the link-graph node corresponding to the target section name.
625 auto *BlockToFix = getGraphBlock(SecIndex: RelSect.sh_info);
626 if (!BlockToFix)
627 return make_error<StringError>(
628 Args: "Refencing a section that wasn't added to the graph: " + *Name,
629 Args: inconvertibleErrorCode());
630
631 auto RelEntries = Obj.relas(RelSect);
632 if (!RelEntries)
633 return RelEntries.takeError();
634
635 // Let the callee process relocation entries one by one.
636 for (const typename ELFT::Rela &R : *RelEntries)
637 if (Error Err = Func(R, **FixupSection, *BlockToFix))
638 return Err;
639
640 LLVM_DEBUG(dbgs() << "\n");
641 return Error::success();
642}
643
644template <typename ELFT>
645template <typename RelocHandlerFunction>
646Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
647 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
648 // Only look into sections that store relocation entries.
649 if (RelSect.sh_type != ELF::SHT_REL)
650 return Error::success();
651
652 // sh_info contains the section header index of the target (FixupSection),
653 // which is the section to which all relocations in RelSect apply.
654 auto FixupSection = Obj.getSection(RelSect.sh_info);
655 if (!FixupSection)
656 return FixupSection.takeError();
657
658 // Target sections have names in valid ELF object files.
659 Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
660 if (!Name)
661 return Name.takeError();
662 LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
663
664 // Consider skipping these relocations.
665 if (!ProcessDebugSections && isDwarfSection(SectionName: *Name)) {
666 LLVM_DEBUG(dbgs() << " skipped (dwarf section)\n\n");
667 return Error::success();
668 }
669 if (excludeSection(Sect: **FixupSection)) {
670 LLVM_DEBUG(dbgs() << " skipped (fixup section excluded explicitly)\n\n");
671 return Error::success();
672 }
673
674 // Lookup the link-graph node corresponding to the target section name.
675 auto *BlockToFix = getGraphBlock(SecIndex: RelSect.sh_info);
676 if (!BlockToFix)
677 return make_error<StringError>(
678 Args: "Refencing a section that wasn't added to the graph: " + *Name,
679 Args: inconvertibleErrorCode());
680
681 auto RelEntries = Obj.rels(RelSect);
682 if (!RelEntries)
683 return RelEntries.takeError();
684
685 // Let the callee process relocation entries one by one.
686 for (const typename ELFT::Rel &R : *RelEntries)
687 if (Error Err = Func(R, **FixupSection, *BlockToFix))
688 return Err;
689
690 LLVM_DEBUG(dbgs() << "\n");
691 return Error::success();
692}
693
694} // end namespace jitlink
695} // end namespace llvm
696
697#undef DEBUG_TYPE
698
699#endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
700