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>
62 std::shared_ptr<orc::SymbolStringPool> SSP,
Triple TT,
118 return Sym.getValue();
136 template <
typename RelocHandlerMethod>
138 RelocHandlerMethod &&Func);
145 template <
typename RelocHandlerMethod>
147 RelocHandlerMethod &&Func);
152 template <
typename ClassT,
typename RelocHandlerMethod>
154 ClassT *Instance, RelocHandlerMethod &&Method) {
157 [Instance, Method](
const auto &Rel,
const auto &
Target,
auto &GS) {
158 return (Instance->*Method)(Rel,
Target, GS);
165 template <
typename ClassT,
typename RelocHandlerMethod>
167 ClassT *Instance, RelocHandlerMethod &&Method) {
170 [Instance, Method](
const auto &Rel,
const auto &
Target,
auto &GS) {
171 return (Instance->*Method)(Rel,
Target, GS);
186 DenseMap<
const typename ELFFile::Elf_Shdr *,
191template <
typename ELFT>
193 const ELFFile &
Obj, std::shared_ptr<orc::SymbolStringPool> SSP,
Triple TT,
201 {
dbgs() <<
"Created ELFLinkGraphBuilder for \"" << FileName <<
"\""; });
204template <
typename ELFT>
210 return std::move(Err);
213 return std::move(Err);
216 return std::move(Err);
219 return std::move(Err);
224template <
typename ELFT>
227 const typename ELFT::Sym &Sym,
StringRef Name) {
231 switch (Sym.getBinding()) {
244 "Unrecognized symbol binding " +
245 Twine(
static_cast<int>(Sym.getBinding())) +
" for " + Name,
249 switch (Sym.getVisibility()) {
263 "Unrecognized symbol visibility " +
264 Twine(
static_cast<int>(Sym.getVisibility())) +
" for " + Name,
268 return std::make_pair(L, S);
275 if (
auto SectionsOrErr =
Obj.sections())
278 return SectionsOrErr.takeError();
281 if (
auto SectionStringTabOrErr =
Obj.getSectionStringTable(
Sections))
284 return SectionStringTabOrErr.takeError();
302 auto ShndxTable =
Obj.getSHNDXTable(Sec);
304 return ShndxTable.takeError();
324 return Name.takeError();
327 dbgs() <<
" " << SecIndex <<
": Skipping section \"" << *Name
328 <<
"\" explicitly\n";
336 dbgs() <<
" " << SecIndex <<
": has type SHT_NULL. Skipping.\n";
345 dbgs() <<
" " << SecIndex <<
": \"" << *Name
346 <<
"\" is a debug section: "
347 "No graph section will be created.\n";
353 dbgs() <<
" " << SecIndex <<
": Creating section for \"" << *Name
365 auto *GraphSec =
G->findSectionByName(*Name);
367 GraphSec = &
G->createSection(*Name, Prot);
372 dbgs() <<
" " << SecIndex <<
": \"" << *Name
373 <<
"\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
378 if (GraphSec->getMemProt() != Prot) {
381 <<
"In " <<
G->getName() <<
", section " << *Name
382 <<
" is present more than once with different permissions: "
383 << GraphSec->getMemProt() <<
" vs " << Prot;
389 auto Data =
Obj.template getSectionContentsAsArray<char>(Sec);
391 return Data.takeError();
393 B = &
G->createContentBlock(*GraphSec, *
Data,
395 Sec.sh_addralign, 0);
397 B = &
G->createZeroFillBlock(*GraphSec, Sec.sh_size,
399 Sec.sh_addralign, 0);
423 return Symbols.takeError();
428 return StringTab.takeError();
434 SymTabName = *SymTabNameOrErr;
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>";
441 dbgs() <<
" Adding symbols from symtab section \"" << SymTabName
445 for (
ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
446 auto &Sym = (*Symbols)[SymIndex];
449 switch (Sym.getType()) {
452 if (
auto Name = Sym.getName(*StringTab))
453 dbgs() <<
" " << SymIndex <<
": Skipping STT_FILE symbol \""
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";
467 auto Name = Sym.getName(*StringTab);
469 return Name.takeError();
472 if (Sym.isCommon()) {
473 Symbol &GSym =
G->addDefinedSymbol(
481 if (Sym.isDefined() &&
490 std::tie(L, S) = *LSOrErr;
492 return LSOrErr.takeError();
495 unsigned Shndx = Sym.st_shndx;
501 Sym, SymIndex, ShndxTable->second);
503 return NdxOrErr.takeError();
508 dbgs() <<
" " << SymIndex
509 <<
": Creating defined graph symbol for ELF symbol \"" << *Name
516 if (
Offset + Sym.st_size >
B->getSize()) {
519 ErrStream <<
"In " <<
G->getName() <<
", symbol ";
523 ErrStream <<
"<anon>";
524 ErrStream <<
" (" << (
B->getAddress() +
Offset) <<
" -- "
525 << (
B->getAddress() +
Offset + Sym.st_size) <<
") extends "
527 <<
" bytes past the end of its containing block ("
528 <<
B->getRange() <<
")";
539 ?
G->addAnonymousSymbol(*
B,
Offset, Sym.st_size,
541 :
G->addDefinedSymbol(*
B,
Offset, *Name, Sym.st_size, L,
545 GSym.setTargetFlags(Flags);
548 }
else if (Sym.isUndefined() && Sym.isExternal()) {
550 dbgs() <<
" " << SymIndex
551 <<
": Creating external graph symbol for ELF symbol \"" << *Name
558 "Invalid symbol binding " +
559 Twine(
static_cast<int>(Sym.getBinding())) +
560 " for external symbol " + *Name,
564 auto &GSym =
G->addExternalSymbol(*Name, Sym.st_size,
567 }
else if (Sym.isUndefined() && Sym.st_value == 0 && Sym.st_size == 0 &&
573 dbgs() <<
" " << SymIndex <<
": Creating null graph symbol\n";
577 G->allocateContent(
"__jitlink_ELF_SYM_UND_" +
Twine(SymIndex));
578 auto SymNameRef =
StringRef(SymName.data(), SymName.size());
584 dbgs() <<
" " << SymIndex
585 <<
": Not creating graph symbol for ELF symbol \"" << *Name
586 <<
"\" with unrecognized type\n";
594template <
typename ELFT>
595template <
typename RelocHandlerFunction>
597 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
604 auto FixupSection =
Obj.getSection(RelSect.sh_info);
606 return FixupSection.takeError();
611 return Name.takeError();
620 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
628 "Refencing a section that wasn't added to the graph: " + *Name,
631 auto RelEntries =
Obj.relas(RelSect);
633 return RelEntries.takeError();
636 for (
const typename ELFT::Rela &R : *RelEntries)
637 if (
Error Err = Func(R, **FixupSection, *BlockToFix))
644template <
typename ELFT>
645template <
typename RelocHandlerFunction>
647 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
654 auto FixupSection =
Obj.getSection(RelSect.sh_info);
656 return FixupSection.takeError();
661 return Name.takeError();
670 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
678 "Refencing a section that wasn't added to the graph: " + *Name,
681 auto RelEntries =
Obj.rels(RelSect);
683 return RelEntries.takeError();
686 for (
const typename ELFT::Rel &R : *RelEntries)
687 if (
Error Err = Func(R, **FixupSection, *BlockToFix))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isDwarfSection(const MCObjectFileInfo *FI, const MCSection *Section)
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.
Section & getCommonSection()
std::unique_ptr< LinkGraph > G
ELFLinkGraphBuilderBase(std::unique_ptr< LinkGraph > G)
virtual ~ELFLinkGraphBuilderBase()
static bool isDwarfSection(StringRef SectionName)
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(const object::ELFFile< ELFT > &Obj, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, SubtargetFeatures Features, StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
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
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.
Represents an address in the executor process.
uint64_t getValue() const
A raw_ostream that writes to an std::string.
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...
Expected< uint32_t > getExtendedSymbolTableIndex(const typename ELFT::Sym &Sym, unsigned SymIndex, DataRegion< typename ELFT::Word > ShndxTable)
MemProt
Describes Read/Write/Exec permissions for memory.
uint64_t ExecutorAddrDiff
@ NoAlloc
NoAlloc memory should not be allocated by the JITLinkMemoryManager at all.
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
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.