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>
123 return Sym.getValue();
141 template <
typename RelocHandlerMethod>
143 RelocHandlerMethod &&Func);
150 template <
typename RelocHandlerMethod>
152 RelocHandlerMethod &&Func);
157 template <
typename ClassT,
typename RelocHandlerMethod>
159 ClassT *Instance, RelocHandlerMethod &&Method) {
162 [Instance, Method](
const auto &Rel,
const auto &
Target,
auto &GS) {
163 return (Instance->*Method)(Rel,
Target, GS);
170 template <
typename ClassT,
typename RelocHandlerMethod>
172 ClassT *Instance, RelocHandlerMethod &&Method) {
175 [Instance, Method](
const auto &Rel,
const auto &
Target,
auto &GS) {
176 return (Instance->*Method)(Rel,
Target, GS);
191 DenseMap<
const typename ELFFile::Elf_Shdr *,
196template <
typename ELFT>
202 ELFT::Is64Bits ? 8 : 4, support::
endianness(ELFT::TargetEndianness),
206 {
dbgs() <<
"Created ELFLinkGraphBuilder for \"" << FileName <<
"\""; });
209template <
typename ELFT>
211 if (!isRelocatable())
212 return make_error<JITLinkError>(
"Object is not a relocatable ELF file");
214 if (
auto Err = prepare())
215 return std::move(Err);
217 if (
auto Err = graphifySections())
218 return std::move(Err);
220 if (
auto Err = graphifySymbols())
221 return std::move(Err);
223 if (
auto Err = addRelocations())
224 return std::move(Err);
229template <
typename ELFT>
236 switch (
Sym.getBinding()) {
248 return make_error<StringError>(
249 "Unrecognized symbol binding " +
250 Twine(
static_cast<int>(
Sym.getBinding())) +
" for " +
Name,
254 switch (
Sym.getVisibility()) {
267 return make_error<StringError>(
268 "Unrecognized symbol visibility " +
269 Twine(
static_cast<int>(
Sym.getVisibility())) +
" for " +
Name,
273 return std::make_pair(L, S);
280 if (
auto SectionsOrErr = Obj.sections())
281 Sections = *SectionsOrErr;
283 return SectionsOrErr.takeError();
286 if (
auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
287 SectionStringTab = *SectionStringTabOrErr;
289 return SectionStringTabOrErr.takeError();
292 for (
auto &Sec : Sections) {
297 return make_error<JITLinkError>(
"Multiple SHT_SYMTAB sections in " +
304 if (SymtabNdx >= Sections.size())
305 return make_error<JITLinkError>(
"sh_link is out of bound");
307 auto ShndxTable = Obj.getSHNDXTable(Sec);
309 return ShndxTable.takeError();
311 ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
322 for (
ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
324 auto &Sec = Sections[SecIndex];
327 auto Name = Obj.getSectionName(Sec, SectionStringTab);
329 return Name.takeError();
330 if (excludeSection(Sec)) {
332 dbgs() <<
" " << SecIndex <<
": Skipping section \"" << *
Name
333 <<
"\" explicitly\n";
341 dbgs() <<
" " << SecIndex <<
": has type SHT_NULL. Skipping.\n";
350 dbgs() <<
" " << SecIndex <<
": \"" << *
Name
351 <<
"\" is a debug section: "
352 "No graph section will be created.\n";
358 dbgs() <<
" " << SecIndex <<
": Creating section for \"" << *
Name
370 auto *GraphSec =
G->findSectionByName(*
Name);
372 GraphSec = &
G->createSection(*
Name, Prot);
377 dbgs() <<
" " << SecIndex <<
": \"" << *
Name
378 <<
"\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
383 assert(GraphSec->getMemProt() == Prot &&
"MemProt should match");
387 auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
389 return Data.takeError();
391 B = &
G->createContentBlock(*GraphSec, *
Data,
393 Sec.sh_addralign, 0);
395 B = &
G->createZeroFillBlock(*GraphSec, Sec.sh_size,
397 Sec.sh_addralign, 0);
399 setGraphBlock(SecIndex,
B);
413 auto Symbols = Obj.symbols(SymTabSec);
415 return Symbols.takeError();
418 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
420 return StringTab.takeError();
425 if (
auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
426 SymTabName = *SymTabNameOrErr;
428 dbgs() <<
"Could not get ELF SHT_SYMTAB section name for logging: "
429 << toString(SymTabNameOrErr.takeError()) <<
"\n";
430 SymTabName =
"<SHT_SYMTAB section with invalid name>";
433 dbgs() <<
" Adding symbols from symtab section \"" << SymTabName
437 for (
ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
438 auto &
Sym = (*Symbols)[SymIndex];
441 switch (
Sym.getType()) {
445 dbgs() <<
" " << SymIndex <<
": Skipping STT_FILE symbol \""
448 dbgs() <<
"Could not get STT_FILE symbol name: "
450 dbgs() <<
" " << SymIndex
451 <<
": Skipping STT_FILE symbol with invalid name\n";
461 return Name.takeError();
464 if (
Sym.isCommon()) {
465 Symbol &GSym =
G->addDefinedSymbol(
466 G->createZeroFillBlock(getCommonSection(),
Sym.st_size,
469 setGraphSymbol(SymIndex, GSym);
481 if (
auto LSOrErr = getSymbolLinkageAndScope(
Sym, *
Name))
482 std::tie(L, S) = *LSOrErr;
484 return LSOrErr.takeError();
487 unsigned Shndx =
Sym.st_shndx;
489 auto ShndxTable = ShndxTables.find(SymTabSec);
490 if (ShndxTable == ShndxTables.end())
492 auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
493 Sym, SymIndex, ShndxTable->second);
495 return NdxOrErr.takeError();
498 if (
auto *
B = getGraphBlock(Shndx)) {
500 dbgs() <<
" " << SymIndex
501 <<
": Creating defined graph symbol for ELF symbol \"" << *
Name
521 GSym.setTargetFlags(
Flags);
522 setGraphSymbol(SymIndex, GSym);
526 dbgs() <<
" " << SymIndex
527 <<
": Creating external graph symbol for ELF symbol \"" << *
Name
533 return make_error<StringError>(
534 "Invalid symbol binding " +
535 Twine(
static_cast<int>(
Sym.getBinding())) +
536 " for external symbol " + *
Name,
540 auto &GSym =
G->addExternalSymbol(*
Name,
Sym.st_size,
542 setGraphSymbol(SymIndex, GSym);
543 }
else if (
Sym.isUndefined() &&
Sym.st_value == 0 &&
Sym.st_size == 0 &&
549 dbgs() <<
" " << SymIndex <<
": Creating null graph symbol\n";
553 G->allocateContent(
"__jitlink_ELF_SYM_UND_" +
Twine(SymIndex));
554 auto SymNameRef =
StringRef(SymName.data(), SymName.size());
557 setGraphSymbol(SymIndex, GSym);
560 dbgs() <<
" " << SymIndex
561 <<
": Not creating graph symbol for ELF symbol \"" << *
Name
562 <<
"\" with unrecognized type\n";
570template <
typename ELFT>
571template <
typename RelocHandlerFunction>
573 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
580 auto FixupSection = Obj.getSection(RelSect.sh_info);
582 return FixupSection.takeError();
587 return Name.takeError();
595 if (excludeSection(**FixupSection)) {
596 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
601 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
603 return make_error<StringError>(
604 "Refencing a section that wasn't added to the graph: " + *
Name,
607 auto RelEntries = Obj.relas(RelSect);
609 return RelEntries.takeError();
612 for (
const typename ELFT::Rela &R : *RelEntries)
613 if (
Error Err = Func(R, **FixupSection, *BlockToFix))
620template <
typename ELFT>
621template <
typename RelocHandlerFunction>
623 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
630 auto FixupSection = Obj.getSection(RelSect.sh_info);
632 return FixupSection.takeError();
637 return Name.takeError();
645 if (excludeSection(**FixupSection)) {
646 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
651 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
653 return make_error<StringError>(
654 "Refencing a section that wasn't added to the graph: " + *
Name,
657 auto RelEntries = Obj.rels(RelSect);
659 return RelEntries.takeError();
662 for (
const typename ELFT::Rel &R : *RelEntries)
663 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
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
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)
ELFLinkGraphBuilder(const object::ELFFile< ELFT > &Obj, Triple TT, LinkGraph::FeatureVector Features, StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
DenseMap< ELFSectionIndex, Block * > GraphBlocks
std::vector< std::string > FeatureVector
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.
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...
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.