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>
117 return Sym.getValue();
135 template <
typename RelocHandlerMethod>
137 RelocHandlerMethod &&Func);
144 template <
typename RelocHandlerMethod>
146 RelocHandlerMethod &&Func);
151 template <
typename ClassT,
typename RelocHandlerMethod>
153 ClassT *Instance, RelocHandlerMethod &&Method) {
156 [Instance, Method](
const auto &Rel,
const auto &
Target,
auto &GS) {
157 return (Instance->*Method)(Rel,
Target, GS);
164 template <
typename ClassT,
typename RelocHandlerMethod>
166 ClassT *Instance, RelocHandlerMethod &&Method) {
169 [Instance, Method](
const auto &Rel,
const auto &
Target,
auto &GS) {
170 return (Instance->*Method)(Rel,
Target, GS);
185 DenseMap<
const typename ELFFile::Elf_Shdr *,
190template <
typename ELFT>
200 {
dbgs() <<
"Created ELFLinkGraphBuilder for \"" << FileName <<
"\""; });
203template <
typename ELFT>
205 if (!isRelocatable())
206 return make_error<JITLinkError>(
"Object is not a relocatable ELF file");
209 return std::move(Err);
211 if (
auto Err = graphifySections())
212 return std::move(Err);
214 if (
auto Err = graphifySymbols())
215 return std::move(Err);
217 if (
auto Err = addRelocations())
218 return std::move(Err);
223template <
typename ELFT>
230 switch (
Sym.getBinding()) {
242 return make_error<StringError>(
243 "Unrecognized symbol binding " +
244 Twine(
static_cast<int>(
Sym.getBinding())) +
" for " +
Name,
248 switch (
Sym.getVisibility()) {
261 return make_error<StringError>(
262 "Unrecognized symbol visibility " +
263 Twine(
static_cast<int>(
Sym.getVisibility())) +
" for " +
Name,
267 return std::make_pair(L, S);
274 if (
auto SectionsOrErr = Obj.sections())
275 Sections = *SectionsOrErr;
277 return SectionsOrErr.takeError();
280 if (
auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
281 SectionStringTab = *SectionStringTabOrErr;
283 return SectionStringTabOrErr.takeError();
286 for (
auto &Sec : Sections) {
291 return make_error<JITLinkError>(
"Multiple SHT_SYMTAB sections in " +
298 if (SymtabNdx >= Sections.size())
299 return make_error<JITLinkError>(
"sh_link is out of bound");
301 auto ShndxTable = Obj.getSHNDXTable(Sec);
303 return ShndxTable.takeError();
305 ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
316 for (
ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
318 auto &Sec = Sections[SecIndex];
321 auto Name = Obj.getSectionName(Sec, SectionStringTab);
323 return Name.takeError();
324 if (excludeSection(Sec)) {
326 dbgs() <<
" " << SecIndex <<
": Skipping section \"" << *
Name
327 <<
"\" explicitly\n";
335 dbgs() <<
" " << SecIndex <<
": has type SHT_NULL. Skipping.\n";
344 dbgs() <<
" " << SecIndex <<
": \"" << *
Name
345 <<
"\" is a debug section: "
346 "No graph section will be created.\n";
352 dbgs() <<
" " << SecIndex <<
": Creating section for \"" << *
Name
364 auto *GraphSec =
G->findSectionByName(*
Name);
366 GraphSec = &
G->createSection(*
Name, Prot);
371 dbgs() <<
" " << SecIndex <<
": \"" << *
Name
372 <<
"\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
377 if (GraphSec->getMemProt() != Prot) {
380 <<
"In " <<
G->getName() <<
", section " << *
Name
381 <<
" is present more than once with different permissions: "
382 << GraphSec->getMemProt() <<
" vs " << Prot;
383 return make_error<JITLinkError>(std::move(ErrMsg));
388 auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
390 return Data.takeError();
392 B = &
G->createContentBlock(*GraphSec, *
Data,
394 Sec.sh_addralign, 0);
396 B = &
G->createZeroFillBlock(*GraphSec, Sec.sh_size,
398 Sec.sh_addralign, 0);
406 setGraphBlock(SecIndex,
B);
420 auto Symbols = Obj.symbols(SymTabSec);
422 return Symbols.takeError();
425 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
427 return StringTab.takeError();
432 if (
auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
433 SymTabName = *SymTabNameOrErr;
435 dbgs() <<
"Could not get ELF SHT_SYMTAB section name for logging: "
436 << toString(SymTabNameOrErr.takeError()) <<
"\n";
437 SymTabName =
"<SHT_SYMTAB section with invalid name>";
440 dbgs() <<
" Adding symbols from symtab section \"" << SymTabName
444 for (
ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
445 auto &
Sym = (*Symbols)[SymIndex];
448 switch (
Sym.getType()) {
452 dbgs() <<
" " << SymIndex <<
": Skipping STT_FILE symbol \""
455 dbgs() <<
"Could not get STT_FILE symbol name: "
457 dbgs() <<
" " << SymIndex
458 <<
": Skipping STT_FILE symbol with invalid name\n";
468 return Name.takeError();
471 if (
Sym.isCommon()) {
472 Symbol &GSym =
G->addDefinedSymbol(
473 G->createZeroFillBlock(getCommonSection(),
Sym.st_size,
476 setGraphSymbol(SymIndex, GSym);
488 if (
auto LSOrErr = getSymbolLinkageAndScope(
Sym, *
Name))
489 std::tie(L, S) = *LSOrErr;
491 return LSOrErr.takeError();
494 unsigned Shndx =
Sym.st_shndx;
496 auto ShndxTable = ShndxTables.find(SymTabSec);
497 if (ShndxTable == ShndxTables.end())
499 auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
500 Sym, SymIndex, ShndxTable->second);
502 return NdxOrErr.takeError();
505 if (
auto *
B = getGraphBlock(Shndx)) {
507 dbgs() <<
" " << SymIndex
508 <<
": Creating defined graph symbol for ELF symbol \"" << *
Name
518 ErrStream <<
"In " <<
G->getName() <<
", symbol ";
522 ErrStream <<
"<anon>";
523 ErrStream <<
" (" << (
B->getAddress() +
Offset) <<
" -- "
524 << (
B->getAddress() +
Offset +
Sym.st_size) <<
") extends "
526 <<
" bytes past the end of its containing block ("
527 <<
B->getRange() <<
")";
528 return make_error<JITLinkError>(std::move(ErrMsg));
544 GSym.setTargetFlags(Flags);
545 setGraphSymbol(SymIndex, GSym);
549 dbgs() <<
" " << SymIndex
550 <<
": Creating external graph symbol for ELF symbol \"" << *
Name
556 return make_error<StringError>(
557 "Invalid symbol binding " +
558 Twine(
static_cast<int>(
Sym.getBinding())) +
559 " for external symbol " + *
Name,
563 auto &GSym =
G->addExternalSymbol(*
Name,
Sym.st_size,
565 setGraphSymbol(SymIndex, GSym);
566 }
else if (
Sym.isUndefined() &&
Sym.st_value == 0 &&
Sym.st_size == 0 &&
572 dbgs() <<
" " << SymIndex <<
": Creating null graph symbol\n";
576 G->allocateContent(
"__jitlink_ELF_SYM_UND_" +
Twine(SymIndex));
577 auto SymNameRef =
StringRef(SymName.data(), SymName.size());
580 setGraphSymbol(SymIndex, GSym);
583 dbgs() <<
" " << SymIndex
584 <<
": Not creating graph symbol for ELF symbol \"" << *
Name
585 <<
"\" with unrecognized type\n";
593template <
typename ELFT>
594template <
typename RelocHandlerFunction>
596 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
603 auto FixupSection = Obj.getSection(RelSect.sh_info);
605 return FixupSection.takeError();
610 return Name.takeError();
618 if (excludeSection(**FixupSection)) {
619 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
624 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
626 return make_error<StringError>(
627 "Refencing a section that wasn't added to the graph: " + *
Name,
630 auto RelEntries = Obj.relas(RelSect);
632 return RelEntries.takeError();
635 for (
const typename ELFT::Rela &R : *RelEntries)
636 if (
Error Err = Func(R, **FixupSection, *BlockToFix))
643template <
typename ELFT>
644template <
typename RelocHandlerFunction>
646 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
653 auto FixupSection = Obj.getSection(RelSect.sh_info);
655 return FixupSection.takeError();
660 return Name.takeError();
668 if (excludeSection(**FixupSection)) {
669 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
674 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
676 return make_error<StringError>(
677 "Refencing a section that wasn't added to the graph: " + *
Name,
680 auto RelEntries = Obj.rels(RelSect);
682 return RelEntries.takeError();
685 for (
const typename ELFT::Rel &R : *RelEntries)
686 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.
Manages the enabling and disabling of subtarget specific features.
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)
LinkGraph building code that's specific to the given ELFT, but common across all architectures.
const ELFFile::Elf_Shdr * SymTabSec
Error forEachRelRelocation(const typename ELFT::Shdr &RelSect, RelocHandlerMethod &&Func)
Traverse all matching ELFT::Rel relocation records in the given section.
virtual orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym, TargetFlagsType Flags)
Get the physical offset of the symbol on the target platform.
virtual bool excludeSection(const typename ELFT::Shdr &Sect) const
Override in derived classes to suppress certain sections in the link graph.
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, ClassT *Instance, RelocHandlerMethod &&Method)
Traverse all matching rela relocation records in the given section.
ELFLinkGraphBuilder & setProcessDebugSections(bool ProcessDebugSections)
Debug sections are included in the graph by default.
Expected< std::unique_ptr< LinkGraph > > buildGraph()
Attempt to construct and return the LinkGraph.
virtual TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym)
Set the target flags on the given Symbol.
void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym)
Block * getGraphBlock(ELFSectionIndex SecIndex)
Error forEachRelRelocation(const typename ELFT::Shdr &RelSect, ClassT *Instance, RelocHandlerMethod &&Method)
Traverse all matching rel 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, SubtargetFeatures Features, StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
bool isRelocatable() const
DenseMap< ELFSymbolIndex, Symbol * > GraphSymbols
bool ProcessDebugSections
ELFFile::Elf_Shdr_Range Sections
void setGraphBlock(ELFSectionIndex SecIndex, Block *B)
Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect, RelocHandlerMethod &&Func)
Traverse all matching ELFT::Rela relocation records in the given section.
Symbol * getGraphSymbol(ELFSymbolIndex SymIndex)
DenseMap< ELFSectionIndex, Block * > GraphBlocks
const char *(*)(Edge::Kind) GetEdgeKindNameFunction
Represents an object file section.
bool isExternal() const
Returns true if the underlying addressable is an unresolved external.
bool isDefined() const
Returns true if this Symbol has content (potentially) defined within this object file (i....
StringRef getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
const Elf_Ehdr & getHeader() const
Represents an address in the executor process.
A raw_ostream that writes to an std::string.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
uint8_t TargetFlagsType
Holds target-specific properties for a symbol.
Linkage
Describes symbol linkage. This can be used to resolve definition clashes.
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.
@ NoAlloc
NoAlloc memory should not be allocated by the JITLinkMemoryManager at all.
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...
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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)
Returns true if Element is found in Range.
Implement std::hash so that hash_code can be used in STL containers.