Error graphifySections();
Error graphifySymbols();
+ /// Traverse all matching relocation records in the given section. The handler
+ /// function Func should be callable with this signature:
+ /// Error(const typename ELFT::Rela &,
+ /// const typename ELFT::Shdr &, Section &)
+ ///
+ template <typename RelocHandlerFunction>
+ Error forEachRelocation(const typename ELFT::Shdr &RelSect,
+ RelocHandlerFunction &&Func,
+ bool ProcessDebugSections = false);
+
+ /// Traverse all matching relocation records in the given section. Convenience
+ /// wrapper to allow passing a member function for the handler.
+ ///
+ template <typename ClassT, typename RelocHandlerMethod>
+ Error forEachRelocation(const typename ELFT::Shdr &RelSect, ClassT *Instance,
+ RelocHandlerMethod &&Method,
+ bool ProcessDebugSections = false) {
+ return forEachRelocation(
+ RelSect,
+ [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
+ return (Instance->*Method)(Rel, Target, GS);
+ },
+ ProcessDebugSections);
+ }
+
const ELFFile &Obj;
typename ELFFile::Elf_Shdr_Range Sections;
return Error::success();
}
+template <typename ELFT>
+template <typename RelocHandlerFunction>
+Error ELFLinkGraphBuilder<ELFT>::forEachRelocation(
+ const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func,
+ bool ProcessDebugSections) {
+
+ // Only look into sections that store relocation entries.
+ if (RelSect.sh_type != ELF::SHT_RELA && RelSect.sh_type != ELF::SHT_REL)
+ return Error::success();
+
+ // sh_info contains the section header index of the target (FixupSection),
+ // which is the section to which all relocations in RelSect apply.
+ auto FixupSection = Obj.getSection(RelSect.sh_info);
+ if (!FixupSection)
+ return FixupSection.takeError();
+
+ // Target sections have names in valid ELF object files.
+ Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
+ if (!Name)
+ return Name.takeError();
+ LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
+
+ // Consider skipping these relocations.
+ if (!ProcessDebugSections && isDwarfSection(*Name)) {
+ LLVM_DEBUG(dbgs() << " skipped (dwarf section)\n\n");
+ return Error::success();
+ }
+
+ // Lookup the link-graph node corresponding to the target section name.
+ Section *GraphSect = G->findSectionByName(*Name);
+ if (!GraphSect)
+ return make_error<StringError>(
+ "Refencing a section that wasn't added to the graph: " + *Name,
+ inconvertibleErrorCode());
+
+ auto RelEntries = Obj.relas(RelSect);
+ if (!RelEntries)
+ return RelEntries.takeError();
+
+ // Let the callee process relocation entries one by one.
+ for (const typename ELFT::Rela &R : *RelEntries)
+ if (Error Err = Func(R, **FixupSection, *GraphSect))
+ return Err;
+
+ LLVM_DEBUG(dbgs() << "\n");
+ return Error::success();
+}
+
} // end namespace jitlink
} // end namespace llvm
}
Error addRelocations() override {
+ LLVM_DEBUG(dbgs() << "Processing relocations:\n");
+
using Base = ELFLinkGraphBuilder<ELFT>;
- LLVM_DEBUG(dbgs() << "Adding relocations\n");
-
- // Iterate sections and only process the interesting ones.
- for (auto &SecRef : Base::Sections) {
- if (SecRef.sh_type != ELF::SHT_RELA && SecRef.sh_type != ELF::SHT_REL)
- continue;
- auto RelSectName = Base::Obj.getSectionName(SecRef);
- if (!RelSectName)
- return RelSectName.takeError();
-
- LLVM_DEBUG({
- dbgs() << "Adding relocations from section " << *RelSectName << "\n";
- });
-
- auto UpdateSect = Base::Obj.getSection(SecRef.sh_info);
- if (!UpdateSect)
- return UpdateSect.takeError();
-
- auto UpdateSectName = Base::Obj.getSectionName(**UpdateSect);
- if (!UpdateSectName)
- return UpdateSectName.takeError();
-
- // Don't process relocations for debug sections.
- if (Base::isDwarfSection(*UpdateSectName)) {
- LLVM_DEBUG({
- dbgs() << " Target is dwarf section " << *UpdateSectName
- << ". Skipping.\n";
- });
- continue;
- }
- LLVM_DEBUG(dbgs() << " For target section " << *UpdateSectName << "\n");
-
- auto *JITSection = Base::G->findSectionByName(*UpdateSectName);
- if (!JITSection)
- return make_error<llvm::StringError>(
- "Refencing a section that wasn't added to graph" + *UpdateSectName,
- llvm::inconvertibleErrorCode());
-
- auto Relocations = Base::Obj.relas(SecRef);
- if (!Relocations)
- return Relocations.takeError();
-
- for (const auto &Rela : *Relocations) {
- auto Type = Rela.getType(false);
-
- LLVM_DEBUG({
- dbgs() << "Relocation Type: " << Type << "\n"
- << "Name: " << Base::Obj.getRelocationTypeName(Type) << "\n";
- });
-
- auto SymbolIndex = Rela.getSymbol(false);
- auto Symbol = Base::Obj.getRelocationSymbol(Rela, Base::SymTabSec);
- if (!Symbol)
- return Symbol.takeError();
-
- auto BlockToFix = *(JITSection->blocks().begin());
- auto *TargetSymbol = Base::getGraphSymbol(SymbolIndex);
-
- if (!TargetSymbol) {
- return make_error<llvm::StringError>(
- "Could not find symbol at given index, did you add it to "
- "JITSymbolTable? index: " +
- std::to_string(SymbolIndex) + ", shndx: " +
- std::to_string((*Symbol)->st_shndx) + " Size of table: " +
- std::to_string(Base::GraphSymbols.size()),
- llvm::inconvertibleErrorCode());
- }
- int64_t Addend = Rela.r_addend;
- JITTargetAddress FixupAddress = (*UpdateSect)->sh_addr + Rela.r_offset;
-
- LLVM_DEBUG({
- dbgs() << "Processing relocation at "
- << format("0x%016" PRIx64, FixupAddress) << "\n";
- });
- auto Kind = getRelocationKind(Type);
- if (!Kind)
- return Kind.takeError();
-
- BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
- *TargetSymbol, Addend);
- }
- }
+ using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
+ for (const auto &RelSect : Base::Sections)
+ if (Error Err = Base::forEachRelocation(RelSect, this,
+ &Self::addSingleRelocation))
+ return Err;
+
+ return Error::success();
+ }
+
+ Error addSingleRelocation(const typename ELFT::Rela &Rel,
+ const typename ELFT::Shdr &FixupSect,
+ Section &GraphSection) {
+ using Base = ELFLinkGraphBuilder<ELFT>;
+
+ uint32_t SymbolIndex = Rel.getSymbol(false);
+ auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
+ if (!ObjSymbol)
+ return ObjSymbol.takeError();
+
+ Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
+ if (!GraphSymbol)
+ return make_error<StringError>(
+ formatv("Could not find symbol at given index, did you add it to "
+ "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
+ SymbolIndex, (*ObjSymbol)->st_shndx,
+ Base::GraphSymbols.size()),
+ inconvertibleErrorCode());
+
+ uint32_t Type = Rel.getType(false);
+ Expected<aarch64::EdgeKind_aarch64> Kind = getRelocationKind(Type);
+ if (!Kind)
+ return Kind.takeError();
+
+ int64_t Addend = Rel.r_addend;
+ Block *BlockToFix = *(GraphSection.blocks().begin());
+ JITTargetAddress FixupAddress = FixupSect.sh_addr + Rel.r_offset;
+ Edge::OffsetT Offset = FixupAddress - BlockToFix->getAddress();
+ Edge GE(*Kind, Offset, *GraphSymbol, Addend);
+ LLVM_DEBUG({
+ dbgs() << " ";
+ printEdge(dbgs(), *BlockToFix, GE, aarch64::getEdgeKindName(*Kind));
+ dbgs() << "\n";
+ });
+
+ BlockToFix->addEdge(std::move(GE));
return Error::success();
}