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>
206 if (!isRelocatable())
207 return make_error<JITLinkError>(
"Object is not a relocatable ELF file");
210 return std::move(Err);
212 if (
auto Err = graphifySections())
213 return std::move(Err);
215 if (
auto Err = graphifySymbols())
216 return std::move(Err);
218 if (
auto Err = addRelocations())
219 return std::move(Err);
224template <
typename ELFT>
231 switch (
Sym.getBinding()) {
243 return make_error<StringError>(
244 "Unrecognized symbol binding " +
245 Twine(
static_cast<int>(
Sym.getBinding())) +
" for " +
Name,
249 switch (
Sym.getVisibility()) {
262 return make_error<StringError>(
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())
276 Sections = *SectionsOrErr;
278 return SectionsOrErr.takeError();
281 if (
auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
282 SectionStringTab = *SectionStringTabOrErr;
284 return SectionStringTabOrErr.takeError();
287 for (
auto &Sec : Sections) {
292 return make_error<JITLinkError>(
"Multiple SHT_SYMTAB sections in " +
299 if (SymtabNdx >= Sections.size())
300 return make_error<JITLinkError>(
"sh_link is out of bound");
302 auto ShndxTable = Obj.getSHNDXTable(Sec);
304 return ShndxTable.takeError();
306 ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
317 for (
ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
319 auto &Sec = Sections[SecIndex];
322 auto Name = Obj.getSectionName(Sec, SectionStringTab);
324 return Name.takeError();
325 if (excludeSection(Sec)) {
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;
384 return make_error<JITLinkError>(std::move(ErrMsg));
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);
407 setGraphBlock(SecIndex,
B);
421 auto Symbols = Obj.symbols(SymTabSec);
423 return Symbols.takeError();
426 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
428 return StringTab.takeError();
433 if (
auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
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()) {
453 dbgs() <<
" " << SymIndex <<
": Skipping STT_FILE symbol \""
456 dbgs() <<
"Could not get STT_FILE symbol name: "
458 dbgs() <<
" " << SymIndex
459 <<
": Skipping STT_FILE symbol with invalid name\n";
469 return Name.takeError();
472 if (
Sym.isCommon()) {
473 Symbol &GSym =
G->addDefinedSymbol(
474 G->createZeroFillBlock(getCommonSection(),
Sym.st_size,
477 setGraphSymbol(SymIndex, GSym);
489 if (
auto LSOrErr = getSymbolLinkageAndScope(
Sym, *
Name))
490 std::tie(L, S) = *LSOrErr;
492 return LSOrErr.takeError();
495 unsigned Shndx =
Sym.st_shndx;
497 auto ShndxTable = ShndxTables.find(SymTabSec);
498 if (ShndxTable == ShndxTables.end())
500 auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
501 Sym, SymIndex, ShndxTable->second);
503 return NdxOrErr.takeError();
506 if (
auto *
B = getGraphBlock(Shndx)) {
508 dbgs() <<
" " << SymIndex
509 <<
": Creating defined graph symbol for ELF symbol \"" << *
Name
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() <<
")";
529 return make_error<JITLinkError>(std::move(ErrMsg));
545 GSym.setTargetFlags(Flags);
546 setGraphSymbol(SymIndex, GSym);
550 dbgs() <<
" " << SymIndex
551 <<
": Creating external graph symbol for ELF symbol \"" << *
Name
557 return make_error<StringError>(
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,
566 setGraphSymbol(SymIndex, GSym);
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());
581 setGraphSymbol(SymIndex, GSym);
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();
619 if (excludeSection(**FixupSection)) {
620 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
625 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
627 return make_error<StringError>(
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();
669 if (excludeSection(**FixupSection)) {
670 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
675 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
677 return make_error<StringError>(
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))
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(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.
bool isExternal() const
Returns true if the underlying addressable is an unresolved external.
const orc::SymbolStringPtr & getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
bool isDefined() const
Returns true if this Symbol has content (potentially) defined within this object file (i....
const Elf_Ehdr & getHeader() const
Represents an address in the executor process.
A raw_ostream that writes to an std::string.
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(bool Validate, const char *Fmt, 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.
const char * toString(DWARFSectionKind Kind)
Implement std::hash so that hash_code can be used in STL containers.