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);
400 setGraphBlock(SecIndex,
B);
414 auto Symbols = Obj.symbols(SymTabSec);
416 return Symbols.takeError();
419 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
421 return StringTab.takeError();
426 if (
auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
427 SymTabName = *SymTabNameOrErr;
429 dbgs() <<
"Could not get ELF SHT_SYMTAB section name for logging: "
430 << toString(SymTabNameOrErr.takeError()) <<
"\n";
431 SymTabName =
"<SHT_SYMTAB section with invalid name>";
434 dbgs() <<
" Adding symbols from symtab section \"" << SymTabName
438 for (
ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
439 auto &
Sym = (*Symbols)[SymIndex];
442 switch (
Sym.getType()) {
446 dbgs() <<
" " << SymIndex <<
": Skipping STT_FILE symbol \""
449 dbgs() <<
"Could not get STT_FILE symbol name: "
451 dbgs() <<
" " << SymIndex
452 <<
": Skipping STT_FILE symbol with invalid name\n";
462 return Name.takeError();
465 if (
Sym.isCommon()) {
466 Symbol &GSym =
G->addDefinedSymbol(
467 G->createZeroFillBlock(getCommonSection(),
Sym.st_size,
470 setGraphSymbol(SymIndex, GSym);
482 if (
auto LSOrErr = getSymbolLinkageAndScope(
Sym, *
Name))
483 std::tie(L, S) = *LSOrErr;
485 return LSOrErr.takeError();
488 unsigned Shndx =
Sym.st_shndx;
490 auto ShndxTable = ShndxTables.find(SymTabSec);
491 if (ShndxTable == ShndxTables.end())
493 auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
494 Sym, SymIndex, ShndxTable->second);
496 return NdxOrErr.takeError();
499 if (
auto *
B = getGraphBlock(Shndx)) {
501 dbgs() <<
" " << SymIndex
502 <<
": Creating defined graph symbol for ELF symbol \"" << *
Name
512 ErrStream <<
"In " <<
G->getName() <<
", symbol ";
516 ErrStream <<
"<anon>";
517 ErrStream <<
" (" << (
B->getAddress() +
Offset) <<
" -- "
518 << (
B->getAddress() +
Offset +
Sym.st_size) <<
") extends "
520 <<
" bytes past the end of its containing block ("
521 <<
B->getRange() <<
")";
522 return make_error<JITLinkError>(std::move(ErrMsg));
538 GSym.setTargetFlags(Flags);
539 setGraphSymbol(SymIndex, GSym);
543 dbgs() <<
" " << SymIndex
544 <<
": Creating external graph symbol for ELF symbol \"" << *
Name
550 return make_error<StringError>(
551 "Invalid symbol binding " +
552 Twine(
static_cast<int>(
Sym.getBinding())) +
553 " for external symbol " + *
Name,
557 auto &GSym =
G->addExternalSymbol(*
Name,
Sym.st_size,
559 setGraphSymbol(SymIndex, GSym);
560 }
else if (
Sym.isUndefined() &&
Sym.st_value == 0 &&
Sym.st_size == 0 &&
566 dbgs() <<
" " << SymIndex <<
": Creating null graph symbol\n";
570 G->allocateContent(
"__jitlink_ELF_SYM_UND_" +
Twine(SymIndex));
571 auto SymNameRef =
StringRef(SymName.data(), SymName.size());
574 setGraphSymbol(SymIndex, GSym);
577 dbgs() <<
" " << SymIndex
578 <<
": Not creating graph symbol for ELF symbol \"" << *
Name
579 <<
"\" with unrecognized type\n";
587template <
typename ELFT>
588template <
typename RelocHandlerFunction>
590 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
597 auto FixupSection = Obj.getSection(RelSect.sh_info);
599 return FixupSection.takeError();
604 return Name.takeError();
612 if (excludeSection(**FixupSection)) {
613 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
618 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
620 return make_error<StringError>(
621 "Refencing a section that wasn't added to the graph: " + *
Name,
624 auto RelEntries = Obj.relas(RelSect);
626 return RelEntries.takeError();
629 for (
const typename ELFT::Rela &R : *RelEntries)
630 if (
Error Err = Func(R, **FixupSection, *BlockToFix))
637template <
typename ELFT>
638template <
typename RelocHandlerFunction>
640 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
647 auto FixupSection = Obj.getSection(RelSect.sh_info);
649 return FixupSection.takeError();
654 return Name.takeError();
662 if (excludeSection(**FixupSection)) {
663 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
668 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
670 return make_error<StringError>(
671 "Refencing a section that wasn't added to the graph: " + *
Name,
674 auto RelEntries = Obj.rels(RelSect);
676 return RelEntries.takeError();
679 for (
const typename ELFT::Rel &R : *RelEntries)
680 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.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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.
Implement std::hash so that hash_code can be used in STL containers.