#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Object/ELF.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+
+#define DEBUG_TYPE "jitlink"
namespace llvm {
namespace jitlink {
/// Common link-graph building code shared between all ELFFiles.
class ELFLinkGraphBuilderBase {
public:
+ ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}
virtual ~ELFLinkGraphBuilderBase();
+
+protected:
+ static bool isDwarfSection(StringRef SectionName) {
+ return llvm::is_contained(DwarfSectionNames, SectionName);
+ }
+
+ Section &getCommonSection() {
+ if (!CommonSection) {
+ auto Prot = static_cast<sys::Memory::ProtectionFlags>(
+ sys::Memory::MF_READ | sys::Memory::MF_WRITE);
+ CommonSection = &G->createSection(CommonSectionName, Prot);
+ }
+ return *CommonSection;
+ }
+
+ std::unique_ptr<LinkGraph> G;
+
+private:
+ static StringRef CommonSectionName;
+ static ArrayRef<const char *> DwarfSectionNames;
+
+ Section *CommonSection = nullptr;
};
/// Ling-graph building code that's specific to the given ELFT, but common
/// across all architectures.
template <typename ELFT>
class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
+ using ELFFile = object::ELFFile<ELFT>;
+
public:
ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj, Triple TT,
StringRef FileName,
LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
+ /// Attempt to construct and return the LinkGraph.
+ Expected<std::unique_ptr<LinkGraph>> buildGraph();
+
+ /// Call to derived class to handle relocations. These require
+ /// architecture specific knowledge to map to JITLink edge kinds.
+ virtual Error addRelocations() = 0;
+
protected:
- std::unique_ptr<LinkGraph> G;
- const object::ELFFile<ELFT> &Obj;
+ using ELFSectionIndex = unsigned;
+ using ELFSymbolIndex = unsigned;
+
+ bool isRelocatable() const {
+ return Obj.getHeader().e_type == llvm::ELF::ET_REL;
+ }
+
+ void setGraphSection(ELFSectionIndex SecIndex, Section &Sec) {
+ assert(!GraphSections.count(SecIndex) && "Duplicate section at index");
+ GraphSections[SecIndex] = &Sec;
+ }
+
+ Section *getGraphSection(ELFSectionIndex SecIndex) {
+ auto I = GraphSections.find(SecIndex);
+ if (I == GraphSections.end())
+ return nullptr;
+ return I->second;
+ }
+
+ void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
+ assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
+ GraphSymbols[SymIndex] = &Sym;
+ }
+
+ Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
+ auto I = GraphSymbols.find(SymIndex);
+ if (I == GraphSymbols.end())
+ return nullptr;
+ return I->second;
+ }
+
+ Expected<std::pair<Linkage, Scope>>
+ getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
+
+ Error prepare();
+ Error graphifySections();
+ Error graphifySymbols();
+
+ const ELFFile &Obj;
+
+ typename ELFFile::Elf_Shdr_Range Sections;
+ const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
+ StringRef SectionStringTab;
+
+ // Maps ELF section indexes to LinkGraph Sections.
+ // Only SHF_ALLOC sections will have graph sections.
+ DenseMap<ELFSectionIndex, Section *> GraphSections;
+ DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
};
template <typename ELFT>
ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
- const object::ELFFile<ELFT> &Obj, Triple TT, StringRef FileName,
+ const ELFFile &Obj, Triple TT, StringRef FileName,
LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
- : G(std::make_unique<LinkGraph>(FileName.str(), Triple(std::move(TT)),
- ELFT::Is64Bits ? 8 : 4,
- support::endianness(ELFT::TargetEndianness),
- std::move(GetEdgeKindName))),
- Obj(Obj) {}
+ : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
+ FileName.str(), Triple(std::move(TT)), ELFT::Is64Bits ? 8 : 4,
+ support::endianness(ELFT::TargetEndianness),
+ std::move(GetEdgeKindName))),
+ Obj(Obj) {
+ LLVM_DEBUG(
+ { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });
+}
+
+template <typename ELFT>
+Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
+ if (!isRelocatable())
+ return make_error<JITLinkError>("Object is not a relocatable ELF file");
+
+ if (auto Err = prepare())
+ return std::move(Err);
+
+ if (auto Err = graphifySections())
+ return std::move(Err);
+
+ if (auto Err = graphifySymbols())
+ return std::move(Err);
+
+ if (auto Err = addRelocations())
+ return std::move(Err);
+
+ return std::move(G);
+}
+
+template <typename ELFT>
+Expected<std::pair<Linkage, Scope>>
+ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
+ const typename ELFT::Sym &Sym, StringRef Name) {
+ Linkage L = Linkage::Strong;
+ Scope S = Scope::Default;
+
+ switch (Sym.getBinding()) {
+ case ELF::STB_LOCAL:
+ S = Scope::Local;
+ break;
+ case ELF::STB_GLOBAL:
+ // Nothing to do here.
+ break;
+ case ELF::STB_WEAK:
+ L = Linkage::Weak;
+ break;
+ default:
+ return make_error<StringError>("Unrecognized symbol binding for " + Name,
+ inconvertibleErrorCode());
+ }
+
+ switch (Sym.getVisibility()) {
+ case ELF::STV_DEFAULT:
+ case ELF::STV_PROTECTED:
+ // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
+ // Orc support.
+ // Otherwise nothing to do here.
+ break;
+ case ELF::STV_HIDDEN:
+ // Default scope -> Hidden scope. No effect on local scope.
+ if (S == Scope::Default)
+ S = Scope::Hidden;
+ break;
+ case ELF::STV_INTERNAL:
+ return make_error<StringError>("Unrecognized symbol visibility for " + Name,
+ inconvertibleErrorCode());
+ }
+
+ return std::make_pair(L, S);
+}
+
+template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
+ LLVM_DEBUG(dbgs() << " Preparing to build...\n");
+
+ // Get the sections array.
+ if (auto SectionsOrErr = Obj.sections())
+ Sections = *SectionsOrErr;
+ else
+ return SectionsOrErr.takeError();
+
+ // Get the section string table.
+ if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
+ SectionStringTab = *SectionStringTabOrErr;
+ else
+ return SectionStringTabOrErr.takeError();
+
+ // Get the SHT_SYMTAB section.
+ for (auto &Sec : Sections)
+ if (Sec.sh_type == ELF::SHT_SYMTAB) {
+ if (!SymTabSec)
+ SymTabSec = &Sec;
+ else
+ return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +
+ G->getName());
+ }
+
+ return Error::success();
+}
+
+template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
+ LLVM_DEBUG(dbgs() << " Creating graph sections...\n");
+
+ // For each section...
+ for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
+
+ auto &Sec = Sections[SecIndex];
+
+ // Start by getting the section name.
+ auto Name = Obj.getSectionName(Sec, SectionStringTab);
+ if (!Name)
+ return Name.takeError();
+
+ // If the name indicates that it's a debug section then skip it: We don't
+ // support those yet.
+ if (isDwarfSection(*Name)) {
+ LLVM_DEBUG({
+ dbgs() << " " << SecIndex << ": \"" << *Name
+ << "\" is a debug section: "
+ "No graph section will be created.\n";
+ });
+ continue;
+ }
+
+ // Skip non-SHF_ALLOC sections
+ if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
+ LLVM_DEBUG({
+ dbgs() << " " << SecIndex << ": \"" << *Name
+ << "\" is not an SHF_ALLOC section: "
+ "No graph section will be created.\n";
+ });
+ continue;
+ }
+
+ LLVM_DEBUG({
+ dbgs() << " " << SecIndex << ": Creating section for \"" << *Name
+ << "\"\n";
+ });
+
+ // Get the section's memory protection flags.
+ sys::Memory::ProtectionFlags Prot;
+ if (Sec.sh_flags & ELF::SHF_EXECINSTR)
+ Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+ sys::Memory::MF_EXEC);
+ else
+ Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+ sys::Memory::MF_WRITE);
+
+ // For now we just use this to skip the "undefined" section, probably need
+ // to revist.
+ if (Sec.sh_size == 0)
+ continue;
+
+ auto &GraphSec = G->createSection(*Name, Prot);
+ if (Sec.sh_type != ELF::SHT_NOBITS) {
+ auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
+ if (!Data)
+ return Data.takeError();
+
+ G->createContentBlock(GraphSec, *Data, Sec.sh_addr, Sec.sh_addralign, 0);
+ } else
+ G->createZeroFillBlock(GraphSec, Sec.sh_size, Sec.sh_addr,
+ Sec.sh_addralign, 0);
+
+ setGraphSection(SecIndex, GraphSec);
+ }
+
+ return Error::success();
+}
+
+template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
+ LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");
+
+ // No SYMTAB -- Bail out early.
+ if (!SymTabSec)
+ return Error::success();
+
+ // Get the section content as a Symbols array.
+ auto Symbols = Obj.symbols(SymTabSec);
+ if (!Symbols)
+ return Symbols.takeError();
+
+ // Get the string table for this section.
+ auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
+ if (!StringTab)
+ return StringTab.takeError();
+
+ LLVM_DEBUG({
+ StringRef SymTabName;
+
+ if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
+ SymTabName = *SymTabNameOrErr;
+ else {
+ dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
+ << toString(SymTabNameOrErr.takeError()) << "\n";
+ SymTabName = "<SHT_SYMTAB section with invalid name>";
+ }
+
+ dbgs() << " Adding symbols from symtab section \"" << SymTabName
+ << "\"\n";
+ });
+
+ for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
+ auto &Sym = (*Symbols)[SymIndex];
+
+ // Check symbol type.
+ switch (Sym.getType()) {
+ case ELF::STT_FILE:
+ LLVM_DEBUG({
+ if (auto Name = Sym.getName(*StringTab))
+ dbgs() << " " << SymIndex << ": Skipping STT_FILE symbol \""
+ << *Name << "\"\n";
+ else {
+ dbgs() << "Could not get STT_FILE symbol name: "
+ << toString(Name.takeError()) << "\n";
+ dbgs() << " " << SymIndex
+ << ": Skipping STT_FILE symbol with invalid name\n";
+ }
+ });
+ continue;
+ break;
+ }
+
+ // Get the symbol name.
+ auto Name = Sym.getName(*StringTab);
+ if (!Name)
+ return Name.takeError();
+
+ // Handle common symbols specially.
+ if (Sym.isCommon()) {
+ Symbol &GSym =
+ G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0,
+ Sym.st_size, Sym.getValue(), false);
+ setGraphSymbol(SymIndex, GSym);
+ continue;
+ }
+
+ // Map Visibility and Binding to Scope and Linkage:
+ Linkage L;
+ Scope S;
+
+ if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))
+ std::tie(L, S) = *LSOrErr;
+ else
+ return LSOrErr.takeError();
+
+ if (Sym.isDefined() &&
+ (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
+ Sym.getType() == ELF::STT_OBJECT ||
+ Sym.getType() == ELF::STT_SECTION)) {
+
+ // FIXME: Handle extended tables.
+ if (auto *GraphSec = getGraphSection(Sym.st_shndx)) {
+ Block *B = nullptr;
+ {
+ auto Blocks = GraphSec->blocks();
+ assert(Blocks.begin() != Blocks.end() && "No blocks for section");
+ assert(std::next(Blocks.begin()) == Blocks.end() &&
+ "Multiple blocks for section");
+ B = *Blocks.begin();
+ }
+
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex
+ << ": Creating defined graph symbol for ELF symbol \"" << *Name
+ << "\"\n";
+ });
+
+ if (Sym.getType() == ELF::STT_SECTION)
+ *Name = GraphSec->getName();
+
+ auto &GSym =
+ G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L, S,
+ Sym.getType() == ELF::STT_FUNC, false);
+ setGraphSymbol(SymIndex, GSym);
+ }
+ } else if (Sym.isUndefined() && Sym.isExternal()) {
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex
+ << ": Creating external graph symbol for ELF symbol \"" << *Name
+ << "\"\n";
+ });
+ auto &GSym = G->addExternalSymbol(*Name, Sym.st_size, L);
+ setGraphSymbol(SymIndex, GSym);
+ } else {
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex
+ << ": Not creating graph symbol for ELF symbol \"" << *Name
+ << "\" with unrecognized type\n";
+ });
+ }
+ }
+
+ return Error::success();
+}
} // end namespace jitlink
} // end namespace llvm
+#undef DEBUG_TYPE
+
#endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
mutable Section *StubsSection = nullptr;
};
-const char *const DwarfSectionNames[] = {
-#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
- ELF_NAME,
-#include "llvm/BinaryFormat/Dwarf.def"
-#undef HANDLE_DWARF_SECTION
-};
-
} // namespace
const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::NullGOTEntryContent[8] =
const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::StubContent[6] = {
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
-static const char *CommonSectionName = "__common";
static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) {
LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
return Error::success();
}
-static bool isDwarfSection(StringRef SectionName) {
- return llvm::is_contained(DwarfSectionNames, SectionName);
-}
-
namespace llvm {
namespace jitlink {
// This should become a template as the ELFFile is so a lot of this could become
// generic
class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
-
private:
- Section *CommonSection = nullptr;
-
- // TODO hack to get this working
- // Find a better way
- using SymbolTable = object::ELFFile<object::ELF64LE>::Elf_Shdr;
- // For now we just assume
- using SymbolMap = std::map<int32_t, Symbol *>;
- SymbolMap JITSymbolTable;
-
- Section &getCommonSection() {
- if (!CommonSection) {
- auto Prot = static_cast<sys::Memory::ProtectionFlags>(
- sys::Memory::MF_READ | sys::Memory::MF_WRITE);
- CommonSection = &G->createSection(CommonSectionName, Prot);
- }
- return *CommonSection;
- }
static Expected<ELF_x86_64_Edges::ELFX86RelocationKind>
getRelocationKind(const uint32_t Type) {
formatv("{0:d}", Type));
}
- // This could be a template
- object::ELFFile<object::ELF64LE>::Elf_Shdr_Range sections;
- SymbolTable SymTab;
-
- bool isRelocatable() { return Obj.getHeader().e_type == llvm::ELF::ET_REL; }
-
- support::endianness
- getEndianness(const object::ELFFile<object::ELF64LE> &Obj) {
- return Obj.isLE() ? support::little : support::big;
- }
-
- // This could also just become part of a template
- unsigned getPointerSize(const object::ELFFile<object::ELF64LE> &Obj) {
- return Obj.getHeader().getFileClass() == ELF::ELFCLASS64 ? 8 : 4;
- }
-
- // We don't technically need this right now
- // But for now going to keep it as it helps me to debug things
-
- Error createNormalizedSymbols() {
- LLVM_DEBUG(dbgs() << "Creating normalized symbols...\n");
-
- for (auto SecRef : sections) {
- if (SecRef.sh_type != ELF::SHT_SYMTAB &&
- SecRef.sh_type != ELF::SHT_DYNSYM)
- continue;
-
- auto Symbols = Obj.symbols(&SecRef);
- // TODO: Currently I use this function to test things
- // I also want to leave it to see if its common between MACH and elf
- // so for now I just want to continue even if there is an error
- if (errorToBool(Symbols.takeError()))
- continue;
-
- auto StrTabSec = Obj.getSection(SecRef.sh_link);
- if (!StrTabSec)
- return StrTabSec.takeError();
- auto StringTable = Obj.getStringTable(**StrTabSec);
- if (!StringTable)
- return StringTable.takeError();
-
- for (auto SymRef : *Symbols) {
- Optional<StringRef> Name;
-
- if (auto NameOrErr = SymRef.getName(*StringTable))
- Name = *NameOrErr;
- else
- return NameOrErr.takeError();
-
- LLVM_DEBUG({
- dbgs() << " value = " << formatv("{0:x16}", SymRef.getValue())
- << ", type = " << formatv("{0:x2}", SymRef.getType())
- << ", binding = " << formatv("{0:x2}", SymRef.getBinding())
- << ", size = "
- << formatv("{0:x16}", static_cast<uint64_t>(SymRef.st_size))
- << ", info = " << formatv("{0:x2}", SymRef.st_info)
- << " :" << (Name ? *Name : "<anonymous symbol>") << "\n";
- });
- }
- }
- return Error::success();
- }
-
- Error createNormalizedSections() {
- LLVM_DEBUG(dbgs() << "Creating normalized sections...\n");
- for (auto &SecRef : sections) {
- auto Name = Obj.getSectionName(SecRef);
- if (!Name)
- return Name.takeError();
-
- // Skip Dwarf sections.
- if (isDwarfSection(*Name)) {
- LLVM_DEBUG({
- dbgs() << *Name
- << " is a debug section: No graph section will be created.\n";
- });
- continue;
- }
-
- sys::Memory::ProtectionFlags Prot;
- if (SecRef.sh_flags & ELF::SHF_EXECINSTR) {
- Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
- sys::Memory::MF_EXEC);
- } else {
- Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
- sys::Memory::MF_WRITE);
- }
- uint64_t Address = SecRef.sh_addr;
- uint64_t Size = SecRef.sh_size;
- uint64_t Flags = SecRef.sh_flags;
- uint64_t Alignment = SecRef.sh_addralign;
- const char *Data = nullptr;
- // for now we just use this to skip the "undefined" section, probably need
- // to revist
- if (Size == 0)
- continue;
-
- // FIXME: Use flags.
- (void)Flags;
-
- LLVM_DEBUG({
- dbgs() << " " << *Name << ": " << formatv("{0:x16}", Address) << " -- "
- << formatv("{0:x16}", Address + Size) << ", align: " << Alignment
- << " Flags: " << formatv("{0:x}", Flags) << "\n";
- });
-
- if (SecRef.sh_type != ELF::SHT_NOBITS) {
- // .sections() already checks that the data is not beyond the end of
- // file
- auto contents = Obj.getSectionContentsAsArray<char>(SecRef);
- if (!contents)
- return contents.takeError();
-
- Data = contents->data();
- // TODO protection flags.
- // for now everything is
- auto §ion = G->createSection(*Name, Prot);
- // Do this here because we have it, but move it into graphify later
- G->createContentBlock(section, ArrayRef<char>(Data, Size), Address,
- Alignment, 0);
- if (SecRef.sh_type == ELF::SHT_SYMTAB)
- // TODO: Dynamic?
- SymTab = SecRef;
- } else {
- auto &Section = G->createSection(*Name, Prot);
- G->createZeroFillBlock(Section, Size, Address, Alignment, 0);
- }
- }
-
- return Error::success();
- }
-
- Error addRelocations() {
+ Error addRelocations() override {
LLVM_DEBUG(dbgs() << "Adding relocations\n");
// TODO a partern is forming of iterate some sections but only give me
// ones I am interested, i should abstract that concept some where
- for (auto &SecRef : sections) {
+ for (auto &SecRef : Sections) {
if (SecRef.sh_type != ELF::SHT_RELA && SecRef.sh_type != ELF::SHT_REL)
continue;
// TODO can the elf obj file do this for me?
<< "Name: " << Obj.getRelocationTypeName(Type) << "\n";
});
auto SymbolIndex = Rela.getSymbol(false);
- auto Symbol = Obj.getRelocationSymbol(Rela, &SymTab);
+ auto Symbol = Obj.getRelocationSymbol(Rela, SymTabSec);
if (!Symbol)
return Symbol.takeError();
auto BlockToFix = *(JITSection->blocks().begin());
- auto *TargetSymbol = JITSymbolTable[SymbolIndex];
+ auto *TargetSymbol = 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(JITSymbolTable.size()),
+ "JITSymbolTable? index: " +
+ std::to_string(SymbolIndex) +
+ ", shndx: " + std::to_string((*Symbol)->st_shndx) +
+ " Size of table: " + std::to_string(GraphSymbols.size()),
llvm::inconvertibleErrorCode());
}
uint64_t Addend = Rela.r_addend;
return Error::success();
}
- Error graphifyRegularSymbols() {
-
- // TODO: ELF supports beyond SHN_LORESERVE,
- // need to perf test how a vector vs map handles those cases
-
- std::vector<std::vector<object::ELFFile<object::ELF64LE>::Elf_Shdr_Range *>>
- SecIndexToSymbols;
-
- LLVM_DEBUG(dbgs() << "Creating graph symbols...\n");
-
- for (auto SecRef : sections) {
-
- if (SecRef.sh_type != ELF::SHT_SYMTAB &&
- SecRef.sh_type != ELF::SHT_DYNSYM)
- continue;
- auto Symbols = Obj.symbols(&SecRef);
- if (!Symbols)
- return Symbols.takeError();
-
- auto StrTabSec = Obj.getSection(SecRef.sh_link);
- if (!StrTabSec)
- return StrTabSec.takeError();
- auto StringTable = Obj.getStringTable(**StrTabSec);
- if (!StringTable)
- return StringTable.takeError();
- auto Name = Obj.getSectionName(SecRef);
- if (!Name)
- return Name.takeError();
-
- LLVM_DEBUG(dbgs() << "Processing symbol section " << *Name << ":\n");
-
- auto Section = G->findSectionByName(*Name);
- if (!Section)
- return make_error<llvm::StringError>("Could not find a section " +
- *Name,
- llvm::inconvertibleErrorCode());
- // we only have one for now
- auto blocks = Section->blocks();
- if (blocks.empty())
- return make_error<llvm::StringError>("Section has no block",
- llvm::inconvertibleErrorCode());
- int SymbolIndex = -1;
- for (auto SymRef : *Symbols) {
- ++SymbolIndex;
- auto Type = SymRef.getType();
-
- if (Type == ELF::STT_FILE || SymbolIndex == 0)
- continue;
- // these should do it for now
- // if(Type != ELF::STT_NOTYPE &&
- // Type != ELF::STT_OBJECT &&
- // Type != ELF::STT_FUNC &&
- // Type != ELF::STT_SECTION &&
- // Type != ELF::STT_COMMON) {
- // continue;
- // }
- auto Name = SymRef.getName(*StringTable);
- // I am not sure on If this is going to hold as an invariant. Revisit.
- if (!Name)
- return Name.takeError();
-
- if (SymRef.isCommon()) {
- // Symbols in SHN_COMMON refer to uninitialized data. The st_value
- // field holds alignment constraints.
- Symbol &S =
- G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0,
- SymRef.st_size, SymRef.getValue(), false);
- JITSymbolTable[SymbolIndex] = &S;
- continue;
- }
-
- // Map Visibility and Binding to Scope and Linkage:
- Linkage L = Linkage::Strong;
- Scope S = Scope::Default;
-
- switch (SymRef.getBinding()) {
- case ELF::STB_LOCAL:
- S = Scope::Local;
- break;
- case ELF::STB_GLOBAL:
- // Nothing to do here.
- break;
- case ELF::STB_WEAK:
- L = Linkage::Weak;
- break;
- default:
- return make_error<StringError>("Unrecognized symbol binding for " +
- *Name,
- inconvertibleErrorCode());
- }
-
- switch (SymRef.getVisibility()) {
- case ELF::STV_DEFAULT:
- case ELF::STV_PROTECTED:
- // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
- // Orc support.
- // Otherwise nothing to do here.
- break;
- case ELF::STV_HIDDEN:
- // Default scope -> Hidden scope. No effect on local scope.
- if (S == Scope::Default)
- S = Scope::Hidden;
- break;
- case ELF::STV_INTERNAL:
- return make_error<StringError>("Unrecognized symbol visibility for " +
- *Name,
- inconvertibleErrorCode());
- }
-
- if (SymRef.isDefined() &&
- (Type == ELF::STT_NOTYPE || Type == ELF::STT_FUNC ||
- Type == ELF::STT_OBJECT || Type == ELF::STT_SECTION)) {
-
- auto DefinedSection = Obj.getSection(SymRef.st_shndx);
- if (!DefinedSection)
- return DefinedSection.takeError();
- auto sectName = Obj.getSectionName(**DefinedSection);
- if (!sectName)
- return Name.takeError();
-
- // Skip debug section symbols.
- if (isDwarfSection(*sectName))
- continue;
-
- auto JitSection = G->findSectionByName(*sectName);
- if (!JitSection)
- return make_error<llvm::StringError>(
- "Could not find the JitSection " + *sectName,
- llvm::inconvertibleErrorCode());
- auto bs = JitSection->blocks();
- if (bs.empty())
- return make_error<llvm::StringError>(
- "Section has no block", llvm::inconvertibleErrorCode());
-
- auto *B = *bs.begin();
- LLVM_DEBUG({ dbgs() << " " << *Name << " at index " << SymbolIndex << "\n"; });
- if (SymRef.getType() == ELF::STT_SECTION)
- *Name = *sectName;
- auto &Sym = G->addDefinedSymbol(
- *B, SymRef.getValue(), *Name, SymRef.st_size, L, S,
- SymRef.getType() == ELF::STT_FUNC, false);
- JITSymbolTable[SymbolIndex] = &Sym;
- } else if (SymRef.isUndefined() && SymRef.isExternal()) {
- auto &Sym = G->addExternalSymbol(*Name, SymRef.st_size, L);
- JITSymbolTable[SymbolIndex] = &Sym;
- } else
- LLVM_DEBUG({
- dbgs()
- << "Not creating graph symbol for normalized symbol at index "
- << SymbolIndex << ", \"" << *Name << "\"\n";
- });
-
- // TODO: The following has to be implmented.
- // leaving commented out to save time for future patchs
- /*
- G->addAbsoluteSymbol(*Name, SymRef.getValue(), SymRef.st_size,
- Linkage::Strong, Scope::Default, false);
- */
- }
- }
- return Error::success();
- }
-
public:
ELFLinkGraphBuilder_x86_64(StringRef FileName,
const object::ELFFile<object::ELF64LE> &Obj)
: ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"), FileName,
getELFX86RelocationKindName) {}
-
- Expected<std::unique_ptr<LinkGraph>> buildGraph() {
- // Sanity check: we only operate on relocatable objects.
- if (!isRelocatable())
- return make_error<JITLinkError>("Object is not a relocatable ELF");
-
- auto Secs = Obj.sections();
-
- if (!Secs) {
- return Secs.takeError();
- }
- sections = *Secs;
-
- if (auto Err = createNormalizedSections())
- return std::move(Err);
-
- if (auto Err = createNormalizedSymbols())
- return std::move(Err);
-
- if (auto Err = graphifyRegularSymbols())
- return std::move(Err);
-
- if (auto Err = addRelocations())
- return std::move(Err);
-
- return std::move(G);
- }
};
class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {