13#ifndef LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
14#define LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
22#define DEBUG_TYPE "jitlink"
40 CommonSection = &
G->createSection(
42 return *CommonSection;
45 std::unique_ptr<LinkGraph>
G;
51 Section *CommonSection =
nullptr;
56template <
typename ELFT>
116 template <
typename RelocHandlerMethod>
118 RelocHandlerMethod &&Func,
119 bool ProcessDebugSections =
false);
126 template <
typename RelocHandlerMethod>
128 RelocHandlerMethod &&Func,
129 bool ProcessDebugSections =
false);
134 template <
typename ClassT,
typename RelocHandlerMethod>
136 ClassT *Instance, RelocHandlerMethod &&Method,
137 bool ProcessDebugSections =
false) {
140 [Instance, Method](
const auto &Rel,
const auto &
Target,
auto &GS) {
141 return (Instance->*Method)(Rel,
Target, GS);
143 ProcessDebugSections);
149 template <
typename ClassT,
typename RelocHandlerMethod>
151 ClassT *Instance, RelocHandlerMethod &&Method,
152 bool ProcessDebugSections =
false) {
155 [Instance, Method](
const auto &Rel,
const auto &
Target,
auto &GS) {
156 return (Instance->*Method)(Rel,
Target, GS);
158 ProcessDebugSections);
171 DenseMap<
const typename ELFFile::Elf_Shdr *,
176template <
typename ELFT>
181 FileName.str(),
Triple(
std::
move(TT)), ELFT::Is64Bits ? 8 : 4,
186 {
dbgs() <<
"Created ELFLinkGraphBuilder for \"" << FileName <<
"\""; });
189template <
typename ELFT>
191 if (!isRelocatable())
192 return make_error<JITLinkError>(
"Object is not a relocatable ELF file");
194 if (
auto Err = prepare())
195 return std::move(Err);
197 if (
auto Err = graphifySections())
198 return std::move(Err);
200 if (
auto Err = graphifySymbols())
201 return std::move(Err);
203 if (
auto Err = addRelocations())
204 return std::move(Err);
209template <
typename ELFT>
216 switch (Sym.getBinding()) {
228 return make_error<StringError>(
229 "Unrecognized symbol binding " +
230 Twine(
static_cast<int>(Sym.getBinding())) +
" for " +
Name,
234 switch (Sym.getVisibility()) {
247 return make_error<StringError>(
248 "Unrecognized symbol visibility " +
249 Twine(
static_cast<int>(Sym.getVisibility())) +
" for " +
Name,
253 return std::make_pair(L, S);
260 if (
auto SectionsOrErr = Obj.sections())
261 Sections = *SectionsOrErr;
263 return SectionsOrErr.takeError();
266 if (
auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
267 SectionStringTab = *SectionStringTabOrErr;
269 return SectionStringTabOrErr.takeError();
272 for (
auto &Sec : Sections) {
277 return make_error<JITLinkError>(
"Multiple SHT_SYMTAB sections in " +
284 if (SymtabNdx >= Sections.size())
285 return make_error<JITLinkError>(
"sh_link is out of bound");
287 auto ShndxTable = Obj.getSHNDXTable(Sec);
289 return ShndxTable.takeError();
291 ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
302 for (
ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
304 auto &Sec = Sections[SecIndex];
307 auto Name = Obj.getSectionName(Sec, SectionStringTab);
309 return Name.takeError();
315 dbgs() <<
" " << SecIndex <<
": \"" << *
Name
316 <<
"\" is a debug section: "
317 "No graph section will be created.\n";
325 dbgs() <<
" " << SecIndex <<
": \"" << *
Name
326 <<
"\" is not an SHF_ALLOC section: "
327 "No graph section will be created.\n";
333 dbgs() <<
" " << SecIndex <<
": Creating section for \"" << *
Name
345 auto *GraphSec =
G->findSectionByName(*
Name);
347 GraphSec = &
G->createSection(*
Name, Prot);
348 assert(GraphSec->getMemProt() == Prot &&
"MemProt should match");
352 auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
354 return Data.takeError();
356 B = &
G->createContentBlock(*GraphSec, *
Data,
358 Sec.sh_addralign, 0);
360 B = &
G->createZeroFillBlock(*GraphSec, Sec.sh_size,
362 Sec.sh_addralign, 0);
364 setGraphBlock(SecIndex,
B);
378 auto Symbols = Obj.symbols(SymTabSec);
380 return Symbols.takeError();
383 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
385 return StringTab.takeError();
390 if (
auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
391 SymTabName = *SymTabNameOrErr;
393 dbgs() <<
"Could not get ELF SHT_SYMTAB section name for logging: "
394 << toString(SymTabNameOrErr.takeError()) <<
"\n";
395 SymTabName =
"<SHT_SYMTAB section with invalid name>";
398 dbgs() <<
" Adding symbols from symtab section \"" << SymTabName
402 for (
ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
403 auto &Sym = (*Symbols)[SymIndex];
406 switch (Sym.getType()) {
409 if (
auto Name = Sym.getName(*StringTab))
410 dbgs() <<
" " << SymIndex <<
": Skipping STT_FILE symbol \""
413 dbgs() <<
"Could not get STT_FILE symbol name: "
415 dbgs() <<
" " << SymIndex
416 <<
": Skipping STT_FILE symbol with invalid name\n";
424 auto Name = Sym.getName(*StringTab);
426 return Name.takeError();
429 if (Sym.isCommon()) {
430 Symbol &GSym =
G->addDefinedSymbol(
431 G->createZeroFillBlock(getCommonSection(), Sym.st_size,
434 setGraphSymbol(SymIndex, GSym);
438 if (Sym.isDefined() &&
446 if (
auto LSOrErr = getSymbolLinkageAndScope(Sym, *
Name))
447 std::tie(L, S) = *LSOrErr;
449 return LSOrErr.takeError();
452 unsigned Shndx = Sym.st_shndx;
454 auto ShndxTable = ShndxTables.find(SymTabSec);
455 if (ShndxTable == ShndxTables.end())
457 auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
458 Sym, SymIndex, ShndxTable->second);
460 return NdxOrErr.takeError();
463 if (
auto *
B = getGraphBlock(Shndx)) {
465 dbgs() <<
" " << SymIndex
466 <<
": Creating defined graph symbol for ELF symbol \"" << *
Name
477 ?
G->addAnonymousSymbol(*
B, Sym.getValue(), Sym.st_size,
479 :
G->addDefinedSymbol(*
B, Sym.getValue(), *
Name, Sym.st_size, L,
481 setGraphSymbol(SymIndex, GSym);
483 }
else if (Sym.isUndefined() && Sym.isExternal()) {
485 dbgs() <<
" " << SymIndex
486 <<
": Creating external graph symbol for ELF symbol \"" << *
Name
492 return make_error<StringError>(
493 "Invalid symbol binding " +
494 Twine(
static_cast<int>(Sym.getBinding())) +
495 " for external symbol " + *
Name,
499 auto &GSym =
G->addExternalSymbol(*
Name, Sym.st_size,
501 setGraphSymbol(SymIndex, GSym);
504 dbgs() <<
" " << SymIndex
505 <<
": Not creating graph symbol for ELF symbol \"" << *
Name
506 <<
"\" with unrecognized type\n";
514template <
typename ELFT>
515template <
typename RelocHandlerFunction>
517 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func,
518 bool ProcessDebugSections) {
525 auto FixupSection = Obj.getSection(RelSect.sh_info);
527 return FixupSection.takeError();
532 return Name.takeError();
542 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
544 return make_error<StringError>(
545 "Refencing a section that wasn't added to the graph: " + *
Name,
548 auto RelEntries = Obj.relas(RelSect);
550 return RelEntries.takeError();
553 for (
const typename ELFT::Rela &R : *RelEntries)
554 if (
Error Err = Func(R, **FixupSection, *BlockToFix))
561template <
typename ELFT>
562template <
typename RelocHandlerFunction>
564 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func,
565 bool ProcessDebugSections) {
572 auto FixupSection = Obj.getSection(RelSect.sh_info);
574 return FixupSection.takeError();
579 return Name.takeError();
589 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
591 return make_error<StringError>(
592 "Refencing a section that wasn't added to the graph: " + *
Name,
595 auto RelEntries = Obj.rels(RelSect);
597 return RelEntries.takeError();
600 for (
const typename ELFT::Rel &R : *RelEntries)
601 if (
Error Err = Func(R, **FixupSection, *BlockToFix))
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isDwarfSection(const MCObjectFileInfo *FI, const MCSection *Section)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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 - Represent a constant reference to a string, i.e.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
An Addressable with content and edges.
Common link-graph building code shared between all ELFFiles.
Section & getCommonSection()
std::unique_ptr< LinkGraph > G
ELFLinkGraphBuilderBase(std::unique_ptr< LinkGraph > G)
virtual ~ELFLinkGraphBuilderBase()
static bool isDwarfSection(StringRef SectionName)
Ling-graph building code that's specific to the given ELFT, but common across all architectures.
const ELFFile::Elf_Shdr * SymTabSec
DenseMap< const typename ELFFile::Elf_Shdr *, ArrayRef< typename ELFFile::Elf_Word > > ShndxTables
virtual Error addRelocations()=0
Call to derived class to handle relocations.
Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect, RelocHandlerMethod &&Func, bool ProcessDebugSections=false)
Traverse all matching ELFT::Rela relocation records in the given section.
Error forEachRelRelocation(const typename ELFT::Shdr &RelSect, ClassT *Instance, RelocHandlerMethod &&Method, bool ProcessDebugSections=false)
Traverse all matching rel relocation records in the given section.
Expected< std::unique_ptr< LinkGraph > > buildGraph()
Attempt to construct and return the LinkGraph.
void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym)
Block * getGraphBlock(ELFSectionIndex SecIndex)
Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect, ClassT *Instance, RelocHandlerMethod &&Method, bool ProcessDebugSections=false)
Traverse all matching rela relocation records in the given section.
Expected< std::pair< Linkage, Scope > > getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name)
StringRef SectionStringTab
ELFLinkGraphBuilder(const object::ELFFile< ELFT > &Obj, Triple TT, StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
bool isRelocatable() const
DenseMap< ELFSymbolIndex, Symbol * > GraphSymbols
ELFFile::Elf_Shdr_Range Sections
Error forEachRelRelocation(const typename ELFT::Shdr &RelSect, RelocHandlerMethod &&Func, bool ProcessDebugSections=false)
Traverse all matching ELFT::Rel relocation records in the given section.
void setGraphBlock(ELFSectionIndex SecIndex, Block *B)
Symbol * getGraphSymbol(ELFSymbolIndex SymIndex)
DenseMap< ELFSectionIndex, Block * > GraphBlocks
const char *(*)(Edge::Kind) GetEdgeKindNameFunction
Represents an object file section.
const Elf_Ehdr & getHeader() const
Represents an address in the executor process.
uint64_t getValue() const
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
Linkage
Describes symbol linkage.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
MemProt
Describes Read/Write/Exec permissions for memory.
This is an optimization pass for GlobalISel generic memory operations.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.