summaryrefslogtreecommitdiff
path: root/include/llvm/Object/ELFObjectFile.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Object/ELFObjectFile.h')
-rw-r--r--include/llvm/Object/ELFObjectFile.h146
1 files changed, 90 insertions, 56 deletions
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 5d826da4c2fc2..07c6364a68949 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -14,23 +14,28 @@
#ifndef LLVM_OBJECT_ELFOBJECTFILE_H
#define LLVM_OBJECT_ELFOBJECTFILE_H
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Object/Binary.h"
#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFTypes.h"
+#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cctype>
-#include <limits>
-#include <utility>
+#include <cassert>
+#include <cstdint>
+#include <system_error>
namespace llvm {
namespace object {
@@ -47,6 +52,7 @@ class ELFObjectFileBase : public ObjectFile {
protected:
ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source);
+ virtual uint16_t getEMachine() const = 0;
virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0;
virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0;
virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0;
@@ -55,14 +61,16 @@ protected:
virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0;
virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0;
-public:
+public:
typedef iterator_range<elf_symbol_iterator> elf_symbol_iterator_range;
virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0;
elf_symbol_iterator_range symbols() const;
static inline bool classof(const Binary *v) { return v->isELF(); }
+
+ SubtargetFeatures getFeatures() const override;
};
class ELFSectionRef : public SectionRef {
@@ -175,6 +183,7 @@ ELFObjectFileBase::symbols() const {
}
template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
+ uint16_t getEMachine() const override;
uint64_t getSymbolSize(DataRefImpl Sym) const override;
public:
@@ -197,18 +206,18 @@ protected:
ArrayRef<Elf_Word> ShndxTable;
void moveSymbolNext(DataRefImpl &Symb) const override;
- ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
- ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
+ Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
+ Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
uint8_t getSymbolOther(DataRefImpl Symb) const override;
uint8_t getSymbolELFType(DataRefImpl Symb) const override;
- SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
- ErrorOr<section_iterator> getSymbolSection(const Elf_Sym *Symb,
- const Elf_Shdr *SymTab) const;
- ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
+ Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
+ Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb,
+ const Elf_Shdr *SymTab) const;
+ Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
void moveSectionNext(DataRefImpl &Sec) const override;
std::error_code getSectionName(DataRefImpl Sec,
@@ -218,6 +227,7 @@ protected:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
@@ -284,11 +294,9 @@ protected:
// A symbol is exported if its binding is either GLOBAL or WEAK, and its
// visibility is either DEFAULT or PROTECTED. All other symbols are not
// exported.
- if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) &&
- (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED))
- return true;
-
- return false;
+ return ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) &&
+ (Visibility == ELF::STV_DEFAULT ||
+ Visibility == ELF::STV_PROTECTED));
}
// This flag is used for classof, to distinguish ELFObjectFile from
@@ -354,7 +362,7 @@ void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const {
}
template <class ELFT>
-ErrorOr<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
+Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
const Elf_Sym *ESym = getSymbol(Sym);
const Elf_Shdr *SymTableSec = *EF.getSection(Sym.d.a);
const Elf_Shdr *StringTableSec = *EF.getSection(SymTableSec->sh_link);
@@ -389,7 +397,7 @@ uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const {
}
template <class ELFT>
-ErrorOr<uint64_t>
+Expected<uint64_t>
ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const {
uint64_t Result = getSymbolValue(Symb);
const Elf_Sym *ESym = getSymbol(Symb);
@@ -407,7 +415,7 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const {
ErrorOr<const Elf_Shdr *> SectionOrErr =
EF.getSection(ESym, SymTab, ShndxTable);
if (std::error_code EC = SectionOrErr.getError())
- return EC;
+ return errorCodeToError(EC);
const Elf_Shdr *Section = *SectionOrErr;
if (Section)
Result += Section->sh_addr;
@@ -425,6 +433,11 @@ uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
}
template <class ELFT>
+uint16_t ELFObjectFile<ELFT>::getEMachine() const {
+ return EF.getHeader()->e_machine;
+}
+
+template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const {
return getSymbol(Sym)->st_size;
}
@@ -445,7 +458,8 @@ uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const {
}
template <class ELFT>
-SymbolRef::Type ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const {
+Expected<SymbolRef::Type>
+ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const {
const Elf_Sym *ESym = getSymbol(Symb);
switch (ESym->getType()) {
@@ -487,12 +501,17 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
Result |= SymbolRef::SF_FormatSpecific;
if (EF.getHeader()->e_machine == ELF::EM_ARM) {
- if (ErrorOr<StringRef> NameOrErr = getSymbolName(Sym)) {
+ if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) {
StringRef Name = *NameOrErr;
if (Name.startswith("$d") || Name.startswith("$t") ||
Name.startswith("$a"))
Result |= SymbolRef::SF_FormatSpecific;
+ } else {
+ // TODO: Actually report errors helpfully.
+ consumeError(NameOrErr.takeError());
}
+ if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1)
+ Result |= SymbolRef::SF_Thumb;
}
if (ESym->st_shndx == ELF::SHN_UNDEF)
@@ -511,12 +530,12 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
}
template <class ELFT>
-ErrorOr<section_iterator>
+Expected<section_iterator>
ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym,
const Elf_Shdr *SymTab) const {
ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable);
if (std::error_code EC = ESecOrErr.getError())
- return EC;
+ return errorCodeToError(EC);
const Elf_Shdr *ESec = *ESecOrErr;
if (!ESec)
@@ -528,7 +547,7 @@ ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym,
}
template <class ELFT>
-ErrorOr<section_iterator>
+Expected<section_iterator>
ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const {
const Elf_Sym *Sym = getSymbol(Symb);
const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a);
@@ -576,6 +595,11 @@ uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const {
}
template <class ELFT>
+bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const {
+ return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED;
+}
+
+template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR;
}
@@ -606,22 +630,6 @@ ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.section_begin());
RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize;
RelData.d.b = 0;
-
- const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
- return relocation_iterator(RelocationRef(RelData, this));
-
- const Elf_Shdr *RelSec = getRelSection(RelData);
- ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link);
- if (std::error_code EC = SymSecOrErr.getError())
- report_fatal_error(EC.message());
- const Elf_Shdr *SymSec = *SymSecOrErr;
- uint32_t SymSecType = SymSec->sh_type;
- if (SymSecType != ELF::SHT_SYMTAB && SymSecType != ELF::SHT_DYNSYM)
- report_fatal_error("Invalid symbol table section type!");
- if (SymSecType == ELF::SHT_DYNSYM)
- RelData.d.b = 1;
-
return relocation_iterator(RelocationRef(RelData, this));
}
@@ -633,7 +641,14 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const {
if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
return Begin;
DataRefImpl RelData = Begin->getRawDataRefImpl();
- RelData.d.b += (S->sh_size / S->sh_entsize) << 1;
+ const Elf_Shdr *RelSec = getRelSection(RelData);
+
+ // Error check sh_link here so that getRelocationSymbol can just use it.
+ ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link);
+ if (std::error_code EC = SymSecOrErr.getError())
+ report_fatal_error(EC.message());
+
+ RelData.d.b += S->sh_size / S->sh_entsize;
return relocation_iterator(RelocationRef(RelData, this));
}
@@ -657,7 +672,7 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
// Relocations
template <class ELFT>
void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const {
- Rel.d.b += 2;
+ ++Rel.d.b;
}
template <class ELFT>
@@ -672,12 +687,10 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
if (!symbolIdx)
return symbol_end();
- bool IsDyn = Rel.d.b & 1;
+ // FIXME: error check symbolIdx
DataRefImpl SymbolData;
- if (IsDyn)
- SymbolData = toDRI(DotDynSymSec, symbolIdx);
- else
- SymbolData = toDRI(DotSymtabSec, symbolIdx);
+ SymbolData.d.a = sec->sh_link;
+ SymbolData.d.b = symbolIdx;
return symbol_iterator(SymbolRef(SymbolData, this));
}
@@ -725,14 +738,14 @@ template <class ELFT>
const typename ELFObjectFile<ELFT>::Elf_Rel *
ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const {
assert(getRelSection(Rel)->sh_type == ELF::SHT_REL);
- return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b >> 1);
+ return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b);
}
template <class ELFT>
const typename ELFObjectFile<ELFT>::Elf_Rela *
ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA);
- return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b >> 1);
+ return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b);
}
template <class ELFT>
@@ -835,6 +848,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF32-avr";
case ELF::EM_HEXAGON:
return "ELF32-hexagon";
+ case ELF::EM_LANAI:
+ return "ELF32-lanai";
case ELF::EM_MIPS:
return "ELF32-mips";
case ELF::EM_PPC:
@@ -844,6 +859,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF32-sparc";
case ELF::EM_WEBASSEMBLY:
return "ELF32-wasm";
+ case ELF::EM_AMDGPU:
+ return "ELF32-amdgpu";
default:
return "ELF32-unknown";
}
@@ -865,6 +882,12 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "ELF64-mips";
case ELF::EM_WEBASSEMBLY:
return "ELF64-wasm";
+ case ELF::EM_AMDGPU:
+ return (EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA
+ && IsLittleEndian) ?
+ "ELF64-amdgpu-hsacobj" : "ELF64-amdgpu";
+ case ELF::EM_BPF:
+ return "ELF64-BPF";
default:
return "ELF64-unknown";
}
@@ -891,6 +914,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
return Triple::avr;
case ELF::EM_HEXAGON:
return Triple::hexagon;
+ case ELF::EM_LANAI:
+ return Triple::lanai;
case ELF::EM_MIPS:
switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) {
case ELF::ELFCLASS32:
@@ -919,6 +944,15 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
default: return Triple::UnknownArch;
}
+ case ELF::EM_AMDGPU:
+ return (EF.getHeader()->e_ident[ELF::EI_CLASS] == ELF::ELFCLASS64
+ && EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA
+ && IsLittleEndian) ?
+ Triple::amdgcn : Triple::UnknownArch;
+
+ case ELF::EM_BPF:
+ return IsLittleEndian ? Triple::bpfel : Triple::bpfeb;
+
default:
return Triple::UnknownArch;
}
@@ -934,7 +968,7 @@ template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const {
return EF.getHeader()->e_type == ELF::ET_REL;
}
-}
-}
+} // end namespace object
+} // end namespace llvm
-#endif
+#endif // LLVM_OBJECT_ELFOBJECTFILE_H