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,
198 std::
move(Features), ELFT::Is64Bits ? 8 : 4,
202 {
dbgs() <<
"Created ELFLinkGraphBuilder for \"" << FileName <<
"\""; });
205template <
typename ELFT>
207 if (!isRelocatable())
208 return make_error<JITLinkError>(
"Object is not a relocatable ELF file");
211 return std::move(Err);
213 if (
auto Err = graphifySections())
214 return std::move(Err);
216 if (
auto Err = graphifySymbols())
217 return std::move(Err);
219 if (
auto Err = addRelocations())
220 return std::move(Err);
225template <
typename ELFT>
232 switch (
Sym.getBinding()) {
244 return make_error<StringError>(
245 "Unrecognized symbol binding " +
246 Twine(
static_cast<int>(
Sym.getBinding())) +
" for " +
Name,
250 switch (
Sym.getVisibility()) {
263 return make_error<StringError>(
264 "Unrecognized symbol visibility " +
265 Twine(
static_cast<int>(
Sym.getVisibility())) +
" for " +
Name,
269 return std::make_pair(L, S);
276 if (
auto SectionsOrErr = Obj.sections())
277 Sections = *SectionsOrErr;
279 return SectionsOrErr.takeError();
282 if (
auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
283 SectionStringTab = *SectionStringTabOrErr;
285 return SectionStringTabOrErr.takeError();
288 for (
auto &Sec : Sections) {
293 return make_error<JITLinkError>(
"Multiple SHT_SYMTAB sections in " +
300 if (SymtabNdx >= Sections.size())
301 return make_error<JITLinkError>(
"sh_link is out of bound");
303 auto ShndxTable = Obj.getSHNDXTable(Sec);
305 return ShndxTable.takeError();
307 ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
318 for (
ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
320 auto &Sec = Sections[SecIndex];
323 auto Name = Obj.getSectionName(Sec, SectionStringTab);
325 return Name.takeError();
326 if (excludeSection(Sec)) {
328 dbgs() <<
" " << SecIndex <<
": Skipping section \"" << *
Name
329 <<
"\" explicitly\n";
337 dbgs() <<
" " << SecIndex <<
": has type SHT_NULL. Skipping.\n";
346 dbgs() <<
" " << SecIndex <<
": \"" << *
Name
347 <<
"\" is a debug section: "
348 "No graph section will be created.\n";
354 dbgs() <<
" " << SecIndex <<
": Creating section for \"" << *
Name
366 auto *GraphSec =
G->findSectionByName(*
Name);
368 GraphSec = &
G->createSection(*
Name, Prot);
373 dbgs() <<
" " << SecIndex <<
": \"" << *
Name
374 <<
"\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
379 if (GraphSec->getMemProt() != Prot) {
382 <<
"In " <<
G->getName() <<
", section " << *
Name
383 <<
" is present more than once with different permissions: "
384 << GraphSec->getMemProt() <<
" vs " << Prot;
385 return make_error<JITLinkError>(std::move(ErrMsg));
390 auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
392 return Data.takeError();
394 B = &
G->createContentBlock(*GraphSec, *
Data,
396 Sec.sh_addralign, 0);
398 B = &
G->createZeroFillBlock(*GraphSec, Sec.sh_size,
400 Sec.sh_addralign, 0);
408 setGraphBlock(SecIndex,
B);
422 auto Symbols = Obj.symbols(SymTabSec);
424 return Symbols.takeError();
427 auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
429 return StringTab.takeError();
434 if (
auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
435 SymTabName = *SymTabNameOrErr;
437 dbgs() <<
"Could not get ELF SHT_SYMTAB section name for logging: "
438 << toString(SymTabNameOrErr.takeError()) <<
"\n";
439 SymTabName =
"<SHT_SYMTAB section with invalid name>";
442 dbgs() <<
" Adding symbols from symtab section \"" << SymTabName
446 for (
ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
447 auto &
Sym = (*Symbols)[SymIndex];
450 switch (
Sym.getType()) {
454 dbgs() <<
" " << SymIndex <<
": Skipping STT_FILE symbol \""
457 dbgs() <<
"Could not get STT_FILE symbol name: "
459 dbgs() <<
" " << SymIndex
460 <<
": Skipping STT_FILE symbol with invalid name\n";
470 return Name.takeError();
473 if (
Sym.isCommon()) {
474 Symbol &GSym =
G->addDefinedSymbol(
475 G->createZeroFillBlock(getCommonSection(),
Sym.st_size,
478 setGraphSymbol(SymIndex, GSym);
490 if (
auto LSOrErr = getSymbolLinkageAndScope(
Sym, *
Name))
491 std::tie(L, S) = *LSOrErr;
493 return LSOrErr.takeError();
496 unsigned Shndx =
Sym.st_shndx;
498 auto ShndxTable = ShndxTables.find(SymTabSec);
499 if (ShndxTable == ShndxTables.end())
501 auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
502 Sym, SymIndex, ShndxTable->second);
504 return NdxOrErr.takeError();
507 if (
auto *
B = getGraphBlock(Shndx)) {
509 dbgs() <<
" " << SymIndex
510 <<
": Creating defined graph symbol for ELF symbol \"" << *
Name
520 ErrStream <<
"In " <<
G->getName() <<
", symbol ";
524 ErrStream <<
"<anon>";
525 ErrStream <<
" (" << (
B->getAddress() +
Offset) <<
" -- "
526 << (
B->getAddress() +
Offset +
Sym.st_size) <<
") extends "
528 <<
" bytes past the end of its containing block ("
529 <<
B->getRange() <<
")";
530 return make_error<JITLinkError>(std::move(ErrMsg));
546 GSym.setTargetFlags(Flags);
547 setGraphSymbol(SymIndex, GSym);
551 dbgs() <<
" " << SymIndex
552 <<
": Creating external graph symbol for ELF symbol \"" << *
Name
558 return make_error<StringError>(
559 "Invalid symbol binding " +
560 Twine(
static_cast<int>(
Sym.getBinding())) +
561 " for external symbol " + *
Name,
565 auto &GSym =
G->addExternalSymbol(*
Name,
Sym.st_size,
567 setGraphSymbol(SymIndex, GSym);
568 }
else if (
Sym.isUndefined() &&
Sym.st_value == 0 &&
Sym.st_size == 0 &&
574 dbgs() <<
" " << SymIndex <<
": Creating null graph symbol\n";
578 G->allocateContent(
"__jitlink_ELF_SYM_UND_" +
Twine(SymIndex));
579 auto SymNameRef =
StringRef(SymName.data(), SymName.size());
582 setGraphSymbol(SymIndex, GSym);
585 dbgs() <<
" " << SymIndex
586 <<
": Not creating graph symbol for ELF symbol \"" << *
Name
587 <<
"\" with unrecognized type\n";
595template <
typename ELFT>
596template <
typename RelocHandlerFunction>
598 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
605 auto FixupSection = Obj.getSection(RelSect.sh_info);
607 return FixupSection.takeError();
612 return Name.takeError();
620 if (excludeSection(**FixupSection)) {
621 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
626 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
628 return make_error<StringError>(
629 "Refencing a section that wasn't added to the graph: " + *
Name,
632 auto RelEntries = Obj.relas(RelSect);
634 return RelEntries.takeError();
637 for (
const typename ELFT::Rela &R : *RelEntries)
638 if (
Error Err = Func(R, **FixupSection, *BlockToFix))
645template <
typename ELFT>
646template <
typename RelocHandlerFunction>
648 const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
655 auto FixupSection = Obj.getSection(RelSect.sh_info);
657 return FixupSection.takeError();
662 return Name.takeError();
670 if (excludeSection(**FixupSection)) {
671 LLVM_DEBUG(
dbgs() <<
" skipped (fixup section excluded explicitly)\n\n");
676 auto *BlockToFix = getGraphBlock(RelSect.sh_info);
678 return make_error<StringError>(
679 "Refencing a section that wasn't added to the graph: " + *
Name,
682 auto RelEntries = Obj.rels(RelSect);
684 return RelEntries.takeError();
687 for (
const typename ELFT::Rel &R : *RelEntries)
688 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.