summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2018-04-06 14:26:03 +0000
committerpatrick <patrick@openbsd.org>2018-04-06 14:26:03 +0000
commitbdabc2f19ffb9e20600dad6e8a300842a7bda50e (patch)
treec50e7b2e5449b074651bb82a58517a8ebc4a8cf7 /gnu/llvm/tools/llvm-readobj/ELFDumper.cpp
parentPrint a 'p' flag for file descriptors that were opened after pledge(2). (diff)
downloadwireguard-openbsd-bdabc2f19ffb9e20600dad6e8a300842a7bda50e.tar.xz
wireguard-openbsd-bdabc2f19ffb9e20600dad6e8a300842a7bda50e.zip
Import LLVM 6.0.1 release including clang, lld and lldb.
"where is the kaboom?" deraadt@
Diffstat (limited to 'gnu/llvm/tools/llvm-readobj/ELFDumper.cpp')
-rw-r--r--gnu/llvm/tools/llvm-readobj/ELFDumper.cpp1054
1 files changed, 705 insertions, 349 deletions
diff --git a/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp b/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp
index 5698420bbcc..5605eaea755 100644
--- a/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -18,6 +18,7 @@
#include "StackMapPrinter.h"
#include "llvm-readobj.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallString.h"
@@ -33,6 +34,7 @@
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/StackMapParser.h"
+#include "llvm/Support/AMDGPUMetadata.h"
#include "llvm/Support/ARMAttributeParser.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/Casting.h"
@@ -75,6 +77,7 @@ using namespace ELF;
#define TYPEDEF_ELF_TYPES(ELFT) \
using ELFO = ELFFile<ELFT>; \
+ using Elf_Addr = typename ELFO::Elf_Addr; \
using Elf_Shdr = typename ELFO::Elf_Shdr; \
using Elf_Sym = typename ELFO::Elf_Sym; \
using Elf_Dyn = typename ELFO::Elf_Dyn; \
@@ -155,8 +158,6 @@ public:
void printMipsReginfo() override;
void printMipsOptions() override;
- void printAMDGPUCodeObjectMetadata() override;
-
void printStackMap() const override;
void printHashHistogram() override;
@@ -249,6 +250,9 @@ public:
Elf_Rela_Range dyn_relas() const;
std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
bool IsDynamic) const;
+ void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
+ StringRef &SectionName,
+ unsigned &SectionIndex) const;
void printSymbolsHelper(bool IsDynamic) const;
const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
@@ -287,6 +291,8 @@ void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic);
}
+template <class ELFT> class MipsGOTParser;
+
template <typename ELFT> class DumpStyle {
public:
using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr;
@@ -310,6 +316,8 @@ public:
virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0;
virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0;
virtual void printNotes(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
+ virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;
const ELFDumper<ELFT> *dumper() const { return Dumper; }
private:
@@ -337,6 +345,8 @@ public:
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
+ void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
+ void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
private:
struct Field {
@@ -395,6 +405,8 @@ public:
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
+ void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
+ void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
private:
void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab);
@@ -735,11 +747,10 @@ std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
}
template <typename ELFT>
-static void
-getSectionNameIndex(const ELFFile<ELFT> &Obj, const typename ELFT::Sym *Symbol,
- const typename ELFT::Sym *FirstSym,
- ArrayRef<typename ELFT::Word> ShndxTable,
- StringRef &SectionName, unsigned &SectionIndex) {
+void ELFDumper<ELFT>::getSectionNameIndex(const Elf_Sym *Symbol,
+ const Elf_Sym *FirstSym,
+ StringRef &SectionName,
+ unsigned &SectionIndex) const {
SectionIndex = Symbol->st_shndx;
if (Symbol->isUndefined())
SectionName = "Undefined";
@@ -758,8 +769,8 @@ getSectionNameIndex(const ELFFile<ELFT> &Obj, const typename ELFT::Sym *Symbol,
SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>(
Symbol, FirstSym, ShndxTable));
const typename ELFT::Shdr *Sec =
- unwrapOrError(Obj.getSection(SectionIndex));
- SectionName = unwrapOrError(Obj.getSectionName(Sec));
+ unwrapOrError(Obj->getSection(SectionIndex));
+ SectionName = unwrapOrError(Obj->getSectionName(Sec));
}
}
@@ -820,12 +831,24 @@ static const EnumEntry<unsigned> ElfOSABI[] = {
{"AROS", "AROS", ELF::ELFOSABI_AROS},
{"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS},
{"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI},
- {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI},
- {"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX},
- {"ARM", "ARM", ELF::ELFOSABI_ARM},
{"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE}
};
+static const EnumEntry<unsigned> AMDGPUElfOSABI[] = {
+ {"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA},
+ {"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL},
+ {"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D}
+};
+
+static const EnumEntry<unsigned> ARMElfOSABI[] = {
+ {"ARM", "ARM", ELF::ELFOSABI_ARM}
+};
+
+static const EnumEntry<unsigned> C6000ElfOSABI[] = {
+ {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI},
+ {"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX}
+};
+
static const EnumEntry<unsigned> ElfMachineType[] = {
ENUM_ENT(EM_NONE, "None"),
ENUM_ENT(EM_M32, "WE32100"),
@@ -967,7 +990,7 @@ static const EnumEntry<unsigned> ElfMachineType[] = {
ENUM_ENT(EM_L10M, "EM_L10M"),
ENUM_ENT(EM_K10M, "EM_K10M"),
ENUM_ENT(EM_AARCH64, "AArch64"),
- ENUM_ENT(EM_AVR32, "Atmel AVR 8-bit microcontroller"),
+ ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"),
ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"),
ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"),
ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"),
@@ -1231,6 +1254,20 @@ static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6)
};
+static const EnumEntry<unsigned> ElfHeaderAMDGPUFlags[] = {
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_NONE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_R600),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_GCN)
+};
+
+static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_RVC),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_SINGLE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_DOUBLE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_QUAD),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_RVE)
+};
+
static const EnumEntry<unsigned> ElfSymOtherFlags[] = {
LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL),
LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN),
@@ -1287,15 +1324,16 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer)
switch (Sec.sh_type) {
case ELF::SHT_SYMTAB:
if (DotSymtabSec != nullptr)
- reportError("Multilpe SHT_SYMTAB");
+ reportError("Multiple SHT_SYMTAB");
DotSymtabSec = &Sec;
break;
case ELF::SHT_DYNSYM:
if (DynSymRegion.Size)
- reportError("Multilpe SHT_DYNSYM");
+ reportError("Multiple SHT_DYNSYM");
DynSymRegion = createDRIFrom(&Sec);
// This is only used (if Elf_Shdr present)for naming section in GNU style
DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec));
+ DynamicStringTable = unwrapOrError(Obj->getStringTableForSymtab(Sec));
break;
case ELF::SHT_SYMTAB_SHNDX:
ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec));
@@ -1312,7 +1350,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer)
break;
case ELF::SHT_GNU_verneed:
if (dot_gnu_version_r_sec != nullptr)
- reportError("Multilpe SHT_GNU_verneed");
+ reportError("Multiple SHT_GNU_verneed");
dot_gnu_version_r_sec = &Sec;
break;
}
@@ -1330,8 +1368,11 @@ template <typename ELFT>
void ELFDumper<ELFT>::parseDynamicTable(
ArrayRef<const Elf_Phdr *> LoadSegments) {
auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {
- const Elf_Phdr *const *I = std::upper_bound(
- LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr<ELFT>);
+ const Elf_Phdr *const *I =
+ std::upper_bound(LoadSegments.begin(), LoadSegments.end(), VAddr,
+ [](uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) {
+ return VAddr < Phdr->p_vaddr;
+ });
if (I == LoadSegments.begin())
report_fatal_error("Virtual address is not in any segment");
--I;
@@ -1487,6 +1528,10 @@ static const char *getTypeString(unsigned Arch, uint64_t Type) {
}
}
switch (Type) {
+ LLVM_READOBJ_TYPE_CASE(ANDROID_REL);
+ LLVM_READOBJ_TYPE_CASE(ANDROID_RELSZ);
+ LLVM_READOBJ_TYPE_CASE(ANDROID_RELA);
+ LLVM_READOBJ_TYPE_CASE(ANDROID_RELASZ);
LLVM_READOBJ_TYPE_CASE(BIND_NOW);
LLVM_READOBJ_TYPE_CASE(DEBUG);
LLVM_READOBJ_TYPE_CASE(FINI);
@@ -1689,6 +1734,8 @@ void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) {
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
case DT_PREINIT_ARRAYSZ:
+ case DT_ANDROID_RELSZ:
+ case DT_ANDROID_RELASZ:
OS << Value << " (bytes)";
break;
case DT_NEEDED:
@@ -1853,8 +1900,8 @@ template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() {
ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Sec));
if (Contents[0] != ARMBuildAttrs::Format_Version) {
- errs() << "unrecognised FormatVersion: 0x" << utohexstr(Contents[0])
- << '\n';
+ errs() << "unrecognised FormatVersion: 0x"
+ << Twine::utohexstr(Contents[0]) << '\n';
continue;
}
@@ -1869,45 +1916,83 @@ template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() {
template <class ELFT> class MipsGOTParser {
public:
TYPEDEF_ELF_TYPES(ELFT)
- using GOTEntry = typename ELFO::Elf_Addr;
+ using Entry = typename ELFO::Elf_Addr;
+ using Entries = ArrayRef<Entry>;
- MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
- Elf_Dyn_Range DynTable, ScopedPrinter &W);
+ const bool IsStatic;
+ const ELFO * const Obj;
- void parseGOT();
- void parsePLT();
+ MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms);
-private:
- ELFDumper<ELFT> *Dumper;
- const ELFO *Obj;
- ScopedPrinter &W;
- Optional<uint64_t> DtPltGot;
- Optional<uint64_t> DtLocalGotNum;
- Optional<uint64_t> DtGotSym;
- Optional<uint64_t> DtMipsPltGot;
- Optional<uint64_t> DtJmpRel;
+ bool hasGot() const { return !GotEntries.empty(); }
+ bool hasPlt() const { return !PltEntries.empty(); }
+
+ uint64_t getGp() const;
+
+ const Entry *getGotLazyResolver() const;
+ const Entry *getGotModulePointer() const;
+ const Entry *getPltLazyResolver() const;
+ const Entry *getPltModulePointer() const;
+
+ Entries getLocalEntries() const;
+ Entries getGlobalEntries() const;
+ Entries getOtherEntries() const;
+ Entries getPltEntries() const;
+
+ uint64_t getGotAddress(const Entry * E) const;
+ int64_t getGotOffset(const Entry * E) const;
+ const Elf_Sym *getGotSym(const Entry *E) const;
- std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const;
- const GOTEntry *makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
-
- void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
- const GOTEntry *It);
- void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
- const GOTEntry *It, const Elf_Sym *Sym,
- StringRef StrTable, bool IsDynamic);
- void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt,
- const GOTEntry *It, StringRef Purpose);
- void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt,
- const GOTEntry *It, StringRef StrTable,
- const Elf_Sym *Sym);
+ uint64_t getPltAddress(const Entry * E) const;
+ const Elf_Sym *getPltSym(const Entry *E) const;
+
+ StringRef getPltStrTable() const { return PltStrTable; }
+
+private:
+ const Elf_Shdr *GotSec;
+ size_t LocalNum;
+ size_t GlobalNum;
+
+ const Elf_Shdr *PltSec;
+ const Elf_Shdr *PltRelSec;
+ const Elf_Shdr *PltSymTable;
+ Elf_Sym_Range GotDynSyms;
+ StringRef PltStrTable;
+
+ Entries GotEntries;
+ Entries PltEntries;
};
} // end anonymous namespace
template <class ELFT>
-MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
- Elf_Dyn_Range DynTable, ScopedPrinter &W)
- : Dumper(Dumper), Obj(Obj), W(W) {
+MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable,
+ Elf_Sym_Range DynSyms)
+ : IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0),
+ GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr) {
+ // See "Global Offset Table" in Chapter 5 in the following document
+ // for detailed GOT description.
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+
+ // Find static GOT secton.
+ if (IsStatic) {
+ GotSec = findSectionByName(*Obj, ".got");
+ if (!GotSec)
+ reportError("Cannot find .got section");
+
+ ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec));
+ GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),
+ Content.size() / sizeof(Entry));
+ LocalNum = GotEntries.size();
+ return;
+ }
+
+ // Lookup dynamic table tags which define GOT/PLT layouts.
+ Optional<uint64_t> DtPltGot;
+ Optional<uint64_t> DtLocalGotNum;
+ Optional<uint64_t> DtGotSym;
+ Optional<uint64_t> DtMipsPltGot;
+ Optional<uint64_t> DtJmpRel;
for (const auto &Entry : DynTable) {
switch (Entry.getTag()) {
case ELF::DT_PLTGOT:
@@ -1927,241 +2012,175 @@ MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
break;
}
}
-}
-template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
- // See "Global Offset Table" in Chapter 5 in the following document
- // for detailed GOT description.
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- if (!DtPltGot) {
- W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
- return;
+ // Find dynamic GOT section.
+ if (DtPltGot || DtLocalGotNum || DtGotSym) {
+ if (!DtPltGot)
+ report_fatal_error("Cannot find PLTGOT dynamic table tag.");
+ if (!DtLocalGotNum)
+ report_fatal_error("Cannot find MIPS_LOCAL_GOTNO dynamic table tag.");
+ if (!DtGotSym)
+ report_fatal_error("Cannot find MIPS_GOTSYM dynamic table tag.");
+
+ size_t DynSymTotal = DynSyms.size();
+ if (*DtGotSym > DynSymTotal)
+ reportError("MIPS_GOTSYM exceeds a number of dynamic symbols");
+
+ GotSec = findNotEmptySectionByAddress(Obj, *DtPltGot);
+ if (!GotSec)
+ reportError("There is no not empty GOT section at 0x" +
+ Twine::utohexstr(*DtPltGot));
+
+ LocalNum = *DtLocalGotNum;
+ GlobalNum = DynSymTotal - *DtGotSym;
+
+ ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec));
+ GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),
+ Content.size() / sizeof(Entry));
+ GotDynSyms = DynSyms.drop_front(*DtGotSym);
}
- if (!DtLocalGotNum) {
- W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
- return;
- }
- if (!DtGotSym) {
- W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
- return;
- }
-
- StringRef StrTable = Dumper->getDynamicStringTable();
- const Elf_Sym *DynSymBegin = Dumper->dynamic_symbols().begin();
- const Elf_Sym *DynSymEnd = Dumper->dynamic_symbols().end();
- std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
-
- if (*DtGotSym > DynSymTotal)
- report_fatal_error("MIPS_GOTSYM exceeds a number of dynamic symbols");
-
- std::size_t GlobalGotNum = DynSymTotal - *DtGotSym;
- if (*DtLocalGotNum + GlobalGotNum == 0) {
- W.startLine() << "GOT is empty.\n";
- return;
+ // Find PLT section.
+ if (DtMipsPltGot || DtJmpRel) {
+ if (!DtMipsPltGot)
+ report_fatal_error("Cannot find MIPS_PLTGOT dynamic table tag.");
+ if (!DtJmpRel)
+ report_fatal_error("Cannot find JMPREL dynamic table tag.");
+
+ PltSec = findNotEmptySectionByAddress(Obj, *DtMipsPltGot);
+ if (!PltSec)
+ report_fatal_error("There is no not empty PLTGOT section at 0x " +
+ Twine::utohexstr(*DtMipsPltGot));
+
+ PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel);
+ if (!PltRelSec)
+ report_fatal_error("There is no not empty RELPLT section at 0x" +
+ Twine::utohexstr(*DtJmpRel));
+
+ ArrayRef<uint8_t> PltContent =
+ unwrapOrError(Obj->getSectionContents(PltSec));
+ PltEntries = Entries(reinterpret_cast<const Entry *>(PltContent.data()),
+ PltContent.size() / sizeof(Entry));
+
+ PltSymTable = unwrapOrError(Obj->getSection(PltRelSec->sh_link));
+ PltStrTable = unwrapOrError(Obj->getStringTableForSymtab(*PltSymTable));
}
-
- const Elf_Shdr *GOTShdr = findNotEmptySectionByAddress(Obj, *DtPltGot);
- if (!GOTShdr)
- report_fatal_error("There is no not empty GOT section at 0x" +
- Twine::utohexstr(*DtPltGot));
-
- ArrayRef<uint8_t> GOT = unwrapOrError(Obj->getSectionContents(GOTShdr));
-
- if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(GOT))
- report_fatal_error("Number of GOT entries exceeds the size of GOT section");
-
- const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
- const GOTEntry *GotLocalEnd = makeGOTIter(GOT, *DtLocalGotNum);
- const GOTEntry *It = GotBegin;
-
- DictScope GS(W, "Primary GOT");
-
- W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0);
- {
- ListScope RS(W, "Reserved entries");
-
- {
- DictScope D(W, "Entry");
- printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
- W.printString("Purpose", StringRef("Lazy resolver"));
- }
-
- if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
- DictScope D(W, "Entry");
- printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
- W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
- }
- }
- {
- ListScope LS(W, "Local entries");
- for (; It != GotLocalEnd; ++It) {
- DictScope D(W, "Entry");
- printGotEntry(GOTShdr->sh_addr, GotBegin, It);
- }
- }
- {
- ListScope GS(W, "Global entries");
-
- const GOTEntry *GotGlobalEnd =
- makeGOTIter(GOT, *DtLocalGotNum + GlobalGotNum);
- const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
- for (; It != GotGlobalEnd; ++It) {
- DictScope D(W, "Entry");
- printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, StrTable,
- true);
- }
- }
-
- std::size_t SpecGotNum = getGOTTotal(GOT) - *DtLocalGotNum - GlobalGotNum;
- W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum));
}
-template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() {
- if (!DtMipsPltGot) {
- W.startLine() << "Cannot find MIPS_PLTGOT dynamic table tag.\n";
- return;
- }
- if (!DtJmpRel) {
- W.startLine() << "Cannot find JMPREL dynamic table tag.\n";
- return;
- }
-
- const Elf_Shdr *PLTShdr = findNotEmptySectionByAddress(Obj, *DtMipsPltGot);
- if (!PLTShdr)
- report_fatal_error("There is no not empty PLTGOT section at 0x " +
- Twine::utohexstr(*DtMipsPltGot));
- ArrayRef<uint8_t> PLT = unwrapOrError(Obj->getSectionContents(PLTShdr));
-
- const Elf_Shdr *PLTRelShdr = findNotEmptySectionByAddress(Obj, *DtJmpRel);
- if (!PLTRelShdr)
- report_fatal_error("There is no not empty RELPLT section at 0x" +
- Twine::utohexstr(*DtJmpRel));
- const Elf_Shdr *SymTable =
- unwrapOrError(Obj->getSection(PLTRelShdr->sh_link));
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTable));
-
- const GOTEntry *PLTBegin = makeGOTIter(PLT, 0);
- const GOTEntry *PLTEnd = makeGOTIter(PLT, getGOTTotal(PLT));
- const GOTEntry *It = PLTBegin;
-
- DictScope GS(W, "PLT GOT");
- {
- ListScope RS(W, "Reserved entries");
- printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "PLT lazy resolver");
- if (It != PLTEnd)
- printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "Module pointer");
- }
- {
- ListScope GS(W, "Entries");
+template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const {
+ return GotSec->sh_addr + 0x7ff0;
+}
- switch (PLTRelShdr->sh_type) {
- case ELF::SHT_REL:
- for (const Elf_Rel &Rel : unwrapOrError(Obj->rels(PLTRelShdr))) {
- const Elf_Sym *Sym =
- unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTable));
- printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, StrTable, Sym);
- if (++It == PLTEnd)
- break;
- }
- break;
- case ELF::SHT_RELA:
- for (const Elf_Rela &Rel : unwrapOrError(Obj->relas(PLTRelShdr))) {
- const Elf_Sym *Sym =
- unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTable));
- printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, StrTable, Sym);
- if (++It == PLTEnd)
- break;
- }
- break;
- }
- }
+template <class ELFT>
+const typename MipsGOTParser<ELFT>::Entry *
+MipsGOTParser<ELFT>::getGotLazyResolver() const {
+ return LocalNum > 0 ? &GotEntries[0] : nullptr;
}
template <class ELFT>
-std::size_t MipsGOTParser<ELFT>::getGOTTotal(ArrayRef<uint8_t> GOT) const {
- return GOT.size() / sizeof(GOTEntry);
+const typename MipsGOTParser<ELFT>::Entry *
+MipsGOTParser<ELFT>::getGotModulePointer() const {
+ if (LocalNum < 2)
+ return nullptr;
+ const Entry &E = GotEntries[1];
+ if ((E >> (sizeof(Entry) * 8 - 1)) == 0)
+ return nullptr;
+ return &E;
}
template <class ELFT>
-const typename MipsGOTParser<ELFT>::GOTEntry *
-MipsGOTParser<ELFT>::makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) {
- const char *Data = reinterpret_cast<const char *>(GOT.data());
- return reinterpret_cast<const GOTEntry *>(Data + EntryNum * sizeof(GOTEntry));
+typename MipsGOTParser<ELFT>::Entries
+MipsGOTParser<ELFT>::getLocalEntries() const {
+ size_t Skip = getGotModulePointer() ? 2 : 1;
+ if (LocalNum - Skip <= 0)
+ return Entries();
+ return GotEntries.slice(Skip, LocalNum - Skip);
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr,
- const GOTEntry *BeginIt,
- const GOTEntry *It) {
- int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
- W.printHex("Address", GotAddr + Offset);
- W.printNumber("Access", Offset - 0x7ff0);
- W.printHex("Initial", *It);
+typename MipsGOTParser<ELFT>::Entries
+MipsGOTParser<ELFT>::getGlobalEntries() const {
+ if (GlobalNum == 0)
+ return Entries();
+ return GotEntries.slice(LocalNum, GlobalNum);
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printGlobalGotEntry(
- uint64_t GotAddr, const GOTEntry *BeginIt, const GOTEntry *It,
- const Elf_Sym *Sym, StringRef StrTable, bool IsDynamic) {
- printGotEntry(GotAddr, BeginIt, It);
+typename MipsGOTParser<ELFT>::Entries
+MipsGOTParser<ELFT>::getOtherEntries() const {
+ size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum;
+ if (OtherNum == 0)
+ return Entries();
+ return GotEntries.slice(LocalNum + GlobalNum, OtherNum);
+}
- W.printHex("Value", Sym->st_value);
- W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
+template <class ELFT>
+uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const {
+ int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);
+ return GotSec->sh_addr + Offset;
+}
- unsigned SectionIndex = 0;
- StringRef SectionName;
- getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(),
- Dumper->getShndxTable(), SectionName, SectionIndex);
- W.printHex("Section", SectionName, SectionIndex);
+template <class ELFT>
+int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const {
+ int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);
+ return Offset - 0x7ff0;
+}
- std::string FullSymbolName =
- Dumper->getFullSymbolName(Sym, StrTable, IsDynamic);
- W.printNumber("Name", FullSymbolName, Sym->st_name);
+template <class ELFT>
+const typename MipsGOTParser<ELFT>::Elf_Sym *
+MipsGOTParser<ELFT>::getGotSym(const Entry *E) const {
+ int64_t Offset = std::distance(GotEntries.data(), E);
+ return &GotDynSyms[Offset - LocalNum];
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr,
- const GOTEntry *BeginIt,
- const GOTEntry *It, StringRef Purpose) {
- DictScope D(W, "Entry");
- int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
- W.printHex("Address", PLTAddr + Offset);
- W.printHex("Initial", *It);
- W.printString("Purpose", Purpose);
+const typename MipsGOTParser<ELFT>::Entry *
+MipsGOTParser<ELFT>::getPltLazyResolver() const {
+ return PltEntries.empty() ? nullptr : &PltEntries[0];
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr,
- const GOTEntry *BeginIt,
- const GOTEntry *It, StringRef StrTable,
- const Elf_Sym *Sym) {
- DictScope D(W, "Entry");
- int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
- W.printHex("Address", PLTAddr + Offset);
- W.printHex("Initial", *It);
- W.printHex("Value", Sym->st_value);
- W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
+const typename MipsGOTParser<ELFT>::Entry *
+MipsGOTParser<ELFT>::getPltModulePointer() const {
+ return PltEntries.size() < 2 ? nullptr : &PltEntries[1];
+}
- unsigned SectionIndex = 0;
- StringRef SectionName;
- getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(),
- Dumper->getShndxTable(), SectionName, SectionIndex);
- W.printHex("Section", SectionName, SectionIndex);
+template <class ELFT>
+typename MipsGOTParser<ELFT>::Entries
+MipsGOTParser<ELFT>::getPltEntries() const {
+ if (PltEntries.size() <= 2)
+ return Entries();
+ return PltEntries.slice(2, PltEntries.size() - 2);
+}
- std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true);
- W.printNumber("Name", FullSymbolName, Sym->st_name);
+template <class ELFT>
+uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const {
+ int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry);
+ return PltSec->sh_addr + Offset;
}
-template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
- if (Obj->getHeader()->e_machine != EM_MIPS) {
- W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
- return;
+template <class ELFT>
+const typename MipsGOTParser<ELFT>::Elf_Sym *
+MipsGOTParser<ELFT>::getPltSym(const Entry *E) const {
+ int64_t Offset = std::distance(getPltEntries().data(), E);
+ if (PltRelSec->sh_type == ELF::SHT_REL) {
+ Elf_Rel_Range Rels = unwrapOrError(Obj->rels(PltRelSec));
+ return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
+ } else {
+ Elf_Rela_Range Rels = unwrapOrError(Obj->relas(PltRelSec));
+ return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
}
+}
- MipsGOTParser<ELFT> GOTParser(this, Obj, dynamic_table(), W);
- GOTParser.parseGOT();
- GOTParser.parsePLT();
+template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
+ if (Obj->getHeader()->e_machine != EM_MIPS)
+ reportError("MIPS PLT GOT is available for MIPS targets only");
+
+ MipsGOTParser<ELFT> Parser(Obj, dynamic_table(), dynamic_symbols());
+ if (Parser.hasGot())
+ ELFDumperStyle->printMipsGOT(Parser);
+ if (Parser.hasPlt())
+ ELFDumperStyle->printMipsPLT(Parser);
}
static const EnumEntry<unsigned> ElfMipsISAExtType[] = {
@@ -2326,36 +2345,6 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {
}
}
-template <class ELFT> void ELFDumper<ELFT>::printAMDGPUCodeObjectMetadata() {
- const Elf_Shdr *Shdr = findSectionByName(*Obj, ".note");
- if (!Shdr) {
- W.startLine() << "There is no .note section in the file.\n";
- return;
- }
- ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr));
-
- const uint32_t CodeObjectMetadataNoteType = 10;
- for (auto I = reinterpret_cast<const Elf_Word *>(&Sec[0]),
- E = I + Sec.size()/4; I != E;) {
- uint32_t NameSZ = I[0];
- uint32_t DescSZ = I[1];
- uint32_t Type = I[2];
- I += 3;
-
- StringRef Name;
- if (NameSZ) {
- Name = StringRef(reinterpret_cast<const char *>(I), NameSZ - 1);
- I += alignTo<4>(NameSZ)/4;
- }
-
- if (Name == "AMD" && Type == CodeObjectMetadataNoteType) {
- StringRef Desc(reinterpret_cast<const char *>(I), DescSZ);
- W.printString(Desc);
- }
- I += alignTo<4>(DescSZ)/4;
- }
-}
-
template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
const Elf_Shdr *StackMapSection = nullptr;
for (const auto &Sec : unwrapOrError(Obj->sections())) {
@@ -2369,7 +2358,6 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
if (!StackMapSection)
return;
- StringRef StackMapContents;
ArrayRef<uint8_t> StackMapContentsArray =
unwrapOrError(Obj->getSectionContents(StackMapSection));
@@ -2441,34 +2429,91 @@ template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
printFields(OS, "Section header string table index:", Str);
}
-template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) {
- uint32_t SectionIndex = 0;
- bool HasGroups = false;
+namespace {
+struct GroupMember {
+ StringRef Name;
+ uint64_t Index;
+};
+
+struct GroupSection {
+ StringRef Name;
+ StringRef Signature;
+ uint64_t ShName;
+ uint64_t Index;
+ uint32_t Type;
+ std::vector<GroupMember> Members;
+};
+
+template <class ELFT>
+std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) {
+ using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr;
+ using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym;
+ using Elf_Word = typename ELFFile<ELFT>::Elf_Word;
+
+ std::vector<GroupSection> Ret;
+ uint64_t I = 0;
for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
- if (Sec.sh_type == ELF::SHT_GROUP) {
- HasGroups = true;
- const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link));
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab));
- const Elf_Sym *Signature =
- unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info));
- ArrayRef<Elf_Word> Data = unwrapOrError(
- Obj->template getSectionContentsAsArray<Elf_Word>(&Sec));
- StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
- OS << "\n" << getGroupType(Data[0]) << " group section ["
- << format_decimal(SectionIndex, 5) << "] `" << Name << "' ["
- << StrTable.data() + Signature->st_name << "] contains "
- << (Data.size() - 1) << " sections:\n"
- << " [Index] Name\n";
- for (auto &Ndx : Data.slice(1)) {
- auto Sec = unwrapOrError(Obj->getSection(Ndx));
- const StringRef Name = unwrapOrError(Obj->getSectionName(Sec));
- OS << " [" << format_decimal(Ndx, 5) << "] " << Name
- << "\n";
+ ++I;
+ if (Sec.sh_type != ELF::SHT_GROUP)
+ continue;
+
+ const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link));
+ StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab));
+ const Elf_Sym *Sym =
+ unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info));
+ auto Data =
+ unwrapOrError(Obj->template getSectionContentsAsArray<Elf_Word>(&Sec));
+
+ StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
+ StringRef Signature = StrTable.data() + Sym->st_name;
+ Ret.push_back({Name, Signature, Sec.sh_name, I - 1, Data[0], {}});
+
+ std::vector<GroupMember> &GM = Ret.back().Members;
+ for (uint32_t Ndx : Data.slice(1)) {
+ auto Sec = unwrapOrError(Obj->getSection(Ndx));
+ const StringRef Name = unwrapOrError(Obj->getSectionName(Sec));
+ GM.push_back({Name, Ndx});
+ }
+ }
+ return Ret;
+}
+
+DenseMap<uint64_t, const GroupSection *>
+mapSectionsToGroups(ArrayRef<GroupSection> Groups) {
+ DenseMap<uint64_t, const GroupSection *> Ret;
+ for (const GroupSection &G : Groups)
+ for (const GroupMember &GM : G.Members)
+ Ret.insert({GM.Index, &G});
+ return Ret;
+}
+
+} // namespace
+
+template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) {
+ std::vector<GroupSection> V = getGroups<ELFT>(Obj);
+ DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
+ for (const GroupSection &G : V) {
+ OS << "\n"
+ << getGroupType(G.Type) << " group section ["
+ << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature
+ << "] contains " << G.Members.size() << " sections:\n"
+ << " [Index] Name\n";
+ for (const GroupMember &GM : G.Members) {
+ const GroupSection *MainGroup = Map[GM.Index];
+ if (MainGroup != &G) {
+ OS.flush();
+ errs() << "Error: section [" << format_decimal(GM.Index, 5)
+ << "] in group section [" << format_decimal(G.Index, 5)
+ << "] already in group section ["
+ << format_decimal(MainGroup->Index, 5) << "]";
+ errs().flush();
+ continue;
}
+ OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n";
}
- ++SectionIndex;
}
- if (!HasGroups)
+
+ if (V.empty())
OS << "There are no section groups in this file.\n";
}
@@ -2539,7 +2584,9 @@ static inline void printRelocHeader(raw_ostream &OS, bool Is64, bool IsRela) {
template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
bool HasRelocSections = false;
for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
- if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA)
+ if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
+ Sec.sh_type != ELF::SHT_ANDROID_REL &&
+ Sec.sh_type != ELF::SHT_ANDROID_RELA)
continue;
HasRelocSections = true;
StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
@@ -2548,9 +2595,12 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
OS << "\nRelocation section '" << Name << "' at offset 0x"
<< to_hexString(Offset, false) << " contains " << Entries
<< " entries:\n";
- printRelocHeader(OS, ELFT::Is64Bits, (Sec.sh_type == ELF::SHT_RELA));
+ printRelocHeader(OS, ELFT::Is64Bits,
+ Sec.sh_type == ELF::SHT_RELA ||
+ Sec.sh_type == ELF::SHT_ANDROID_RELA);
const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link));
- if (Sec.sh_type == ELF::SHT_REL) {
+ switch (Sec.sh_type) {
+ case ELF::SHT_REL:
for (const auto &R : unwrapOrError(Obj->rels(&Sec))) {
Elf_Rela Rela;
Rela.r_offset = R.r_offset;
@@ -2558,9 +2608,16 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
Rela.r_addend = 0;
printRelocation(Obj, SymTab, Rela, false);
}
- } else {
+ break;
+ case ELF::SHT_RELA:
for (const auto &R : unwrapOrError(Obj->relas(&Sec)))
printRelocation(Obj, SymTab, R, true);
+ break;
+ case ELF::SHT_ANDROID_REL:
+ case ELF::SHT_ANDROID_RELA:
+ for (const auto &R : unwrapOrError(Obj->android_relas(&Sec)))
+ printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA);
+ break;
}
}
if (!HasRelocSections)
@@ -3310,7 +3367,7 @@ static std::string getGNUNoteTypeName(const uint32_t NT) {
std::string string;
raw_string_ostream OS(string);
OS << format("Unknown note type (0x%08x)", NT);
- return string;
+ return OS.str();
}
static std::string getFreeBSDNoteTypeName(const uint32_t NT) {
@@ -3338,7 +3395,30 @@ static std::string getFreeBSDNoteTypeName(const uint32_t NT) {
std::string string;
raw_string_ostream OS(string);
OS << format("Unknown note type (0x%08x)", NT);
- return string;
+ return OS.str();
+}
+
+static std::string getAMDGPUNoteTypeName(const uint32_t NT) {
+ static const struct {
+ uint32_t ID;
+ const char *Name;
+ } Notes[] = {
+ {ELF::NT_AMD_AMDGPU_HSA_METADATA,
+ "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"},
+ {ELF::NT_AMD_AMDGPU_ISA,
+ "NT_AMD_AMDGPU_ISA (ISA Version)"},
+ {ELF::NT_AMD_AMDGPU_PAL_METADATA,
+ "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)"}
+ };
+
+ for (const auto &Note : Notes)
+ if (Note.ID == NT)
+ return std::string(Note.Name);
+
+ std::string string;
+ raw_string_ostream OS(string);
+ OS << format("Unknown note type (0x%08x)", NT);
+ return OS.str();
}
template <typename ELFT>
@@ -3381,6 +3461,39 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
OS << '\n';
}
+template <typename ELFT>
+static void printAMDGPUNote(raw_ostream &OS, uint32_t NoteType,
+ ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words,
+ size_t Size) {
+ switch (NoteType) {
+ default:
+ return;
+ case ELF::NT_AMD_AMDGPU_HSA_METADATA:
+ OS << " HSA Metadata:\n"
+ << StringRef(reinterpret_cast<const char *>(Words.data()), Size);
+ break;
+ case ELF::NT_AMD_AMDGPU_ISA:
+ OS << " ISA Version:\n"
+ << " "
+ << StringRef(reinterpret_cast<const char *>(Words.data()), Size);
+ break;
+ case ELF::NT_AMD_AMDGPU_PAL_METADATA:
+ const uint32_t *PALMetadataBegin = reinterpret_cast<const uint32_t *>(Words.data());
+ const uint32_t *PALMetadataEnd = PALMetadataBegin + Size;
+ std::vector<uint32_t> PALMetadata(PALMetadataBegin, PALMetadataEnd);
+ std::string PALMetadataString;
+ auto Error = AMDGPU::PALMD::toString(PALMetadata, PALMetadataString);
+ OS << " PAL Metadata:\n";
+ if (Error) {
+ OS << " Invalid";
+ return;
+ }
+ OS << PALMetadataString;
+ break;
+ }
+ OS.flush();
+}
+
template <class ELFT>
void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
const Elf_Ehdr *e = Obj->getHeader();
@@ -3421,6 +3534,9 @@ void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
printGNUNote<ELFT>(OS, Type, Descriptor, DescriptorSize);
} else if (Name == "FreeBSD") {
OS << getFreeBSDNoteTypeName(Type) << '\n';
+ } else if (Name == "AMD") {
+ OS << getAMDGPUNoteTypeName(Type) << '\n';
+ printAMDGPUNote<ELFT>(OS, Type, Descriptor, DescriptorSize);
} else {
OS << "Unknown note type: (" << format_hex(Type, 10) << ')';
}
@@ -3442,6 +3558,119 @@ void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
}
}
+template <class ELFT>
+void GNUStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
+ size_t Bias = ELFT::Is64Bits ? 8 : 0;
+ auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
+ OS.PadToColumn(2);
+ OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias);
+ OS.PadToColumn(11 + Bias);
+ OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)";
+ OS.PadToColumn(22 + Bias);
+ OS << format_hex_no_prefix(*E, 8 + Bias);
+ OS.PadToColumn(31 + 2 * Bias);
+ OS << Purpose << "\n";
+ };
+
+ OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n");
+ OS << " Canonical gp value: "
+ << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n";
+
+ OS << " Reserved entries:\n";
+ OS << " Address Access Initial Purpose\n";
+ PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver");
+ if (Parser.getGotModulePointer())
+ PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)");
+
+ if (!Parser.getLocalEntries().empty()) {
+ OS << "\n";
+ OS << " Local entries:\n";
+ OS << " Address Access Initial\n";
+ for (auto &E : Parser.getLocalEntries())
+ PrintEntry(&E, "");
+ }
+
+ if (Parser.IsStatic)
+ return;
+
+ if (!Parser.getGlobalEntries().empty()) {
+ OS << "\n";
+ OS << " Global entries:\n";
+ OS << " Address Access Initial Sym.Val. Type Ndx Name\n";
+ for (auto &E : Parser.getGlobalEntries()) {
+ const Elf_Sym *Sym = Parser.getGotSym(&E);
+ std::string SymName = this->dumper()->getFullSymbolName(
+ Sym, this->dumper()->getDynamicStringTable(), false);
+
+ OS.PadToColumn(2);
+ OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));
+ OS.PadToColumn(11 + Bias);
+ OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)";
+ OS.PadToColumn(22 + Bias);
+ OS << to_string(format_hex_no_prefix(E, 8 + Bias));
+ OS.PadToColumn(31 + 2 * Bias);
+ OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias));
+ OS.PadToColumn(40 + 3 * Bias);
+ OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes));
+ OS.PadToColumn(48 + 3 * Bias);
+ OS << getSymbolSectionNdx(Parser.Obj, Sym,
+ this->dumper()->dynamic_symbols().begin());
+ OS.PadToColumn(52 + 3 * Bias);
+ OS << SymName << "\n";
+ }
+ }
+
+ if (!Parser.getOtherEntries().empty())
+ OS << "\n Number of TLS and multi-GOT entries "
+ << Parser.getOtherEntries().size() << "\n";
+}
+
+template <class ELFT>
+void GNUStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
+ size_t Bias = ELFT::Is64Bits ? 8 : 0;
+ auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
+ OS.PadToColumn(2);
+ OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias);
+ OS.PadToColumn(11 + Bias);
+ OS << format_hex_no_prefix(*E, 8 + Bias);
+ OS.PadToColumn(20 + 2 * Bias);
+ OS << Purpose << "\n";
+ };
+
+ OS << "PLT GOT:\n\n";
+
+ OS << " Reserved entries:\n";
+ OS << " Address Initial Purpose\n";
+ PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver");
+ if (Parser.getPltModulePointer())
+ PrintEntry(Parser.getGotModulePointer(), "Module pointer");
+
+ if (!Parser.getPltEntries().empty()) {
+ OS << "\n";
+ OS << " Entries:\n";
+ OS << " Address Initial Sym.Val. Type Ndx Name\n";
+ for (auto &E : Parser.getPltEntries()) {
+ const Elf_Sym *Sym = Parser.getPltSym(&E);
+ std::string SymName = this->dumper()->getFullSymbolName(
+ Sym, this->dumper()->getDynamicStringTable(), false);
+
+ OS.PadToColumn(2);
+ OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));
+ OS.PadToColumn(11 + Bias);
+ OS << to_string(format_hex_no_prefix(E, 8 + Bias));
+ OS.PadToColumn(20 + 2 * Bias);
+ OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias));
+ OS.PadToColumn(29 + 3 * Bias);
+ OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes));
+ OS.PadToColumn(37 + 3 * Bias);
+ OS << getSymbolSectionNdx(Parser.Obj, Sym,
+ this->dumper()->dynamic_symbols().begin());
+ OS.PadToColumn(41 + 3 * Bias);
+ OS << SymName << "\n";
+ }
+ }
+}
+
template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
const Elf_Ehdr *e = Obj->getHeader();
{
@@ -3454,13 +3683,22 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
makeArrayRef(ElfDataEncoding));
W.printNumber("FileVersion", e->e_ident[ELF::EI_VERSION]);
- // Handle architecture specific OS/ABI values.
- if (e->e_machine == ELF::EM_AMDGPU &&
- e->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA)
- W.printHex("OS/ABI", "AMDGPU_HSA", ELF::ELFOSABI_AMDGPU_HSA);
- else
- W.printEnum("OS/ABI", e->e_ident[ELF::EI_OSABI],
- makeArrayRef(ElfOSABI));
+ auto OSABI = makeArrayRef(ElfOSABI);
+ if (e->e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&
+ e->e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {
+ switch (e->e_machine) {
+ case ELF::EM_AMDGPU:
+ OSABI = makeArrayRef(AMDGPUElfOSABI);
+ break;
+ case ELF::EM_ARM:
+ OSABI = makeArrayRef(ARMElfOSABI);
+ break;
+ case ELF::EM_TI_C6000:
+ OSABI = makeArrayRef(C6000ElfOSABI);
+ break;
+ }
+ }
+ W.printEnum("OS/ABI", e->e_ident[ELF::EI_OSABI], OSABI);
W.printNumber("ABIVersion", e->e_ident[ELF::EI_ABIVERSION]);
W.printBinary("Unused", makeArrayRef(e->e_ident).slice(ELF::EI_PAD));
}
@@ -3475,6 +3713,11 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderMipsFlags),
unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
unsigned(ELF::EF_MIPS_MACH));
+ else if (e->e_machine == EM_AMDGPU)
+ W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderAMDGPUFlags),
+ unsigned(ELF::EF_AMDGPU_ARCH));
+ else if (e->e_machine == EM_RISCV)
+ W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderRISCVFlags));
else
W.printFlags("Flags", e->e_flags);
W.printNumber("HeaderSize", e->e_ehsize);
@@ -3489,36 +3732,32 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
template <class ELFT>
void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) {
DictScope Lists(W, "Groups");
- uint32_t SectionIndex = 0;
- bool HasGroups = false;
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
- if (Sec.sh_type == ELF::SHT_GROUP) {
- HasGroups = true;
- const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link));
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab));
- const Elf_Sym *Sym =
- unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info));
- auto Data = unwrapOrError(
- Obj->template getSectionContentsAsArray<Elf_Word>(&Sec));
- DictScope D(W, "Group");
- StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
- W.printNumber("Name", Name, Sec.sh_name);
- W.printNumber("Index", SectionIndex);
- W.printHex("Type", getGroupType(Data[0]), Data[0]);
- W.startLine() << "Signature: " << StrTable.data() + Sym->st_name << "\n";
- {
- ListScope L(W, "Section(s) in group");
- size_t Member = 1;
- while (Member < Data.size()) {
- auto Sec = unwrapOrError(Obj->getSection(Data[Member]));
- const StringRef Name = unwrapOrError(Obj->getSectionName(Sec));
- W.startLine() << Name << " (" << Data[Member++] << ")\n";
- }
+ std::vector<GroupSection> V = getGroups<ELFT>(Obj);
+ DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
+ for (const GroupSection &G : V) {
+ DictScope D(W, "Group");
+ W.printNumber("Name", G.Name, G.ShName);
+ W.printNumber("Index", G.Index);
+ W.printHex("Type", getGroupType(G.Type), G.Type);
+ W.startLine() << "Signature: " << G.Signature << "\n";
+
+ ListScope L(W, "Section(s) in group");
+ for (const GroupMember &GM : G.Members) {
+ const GroupSection *MainGroup = Map[GM.Index];
+ if (MainGroup != &G) {
+ W.flush();
+ errs() << "Error: " << GM.Name << " (" << GM.Index
+ << ") in a group " + G.Name + " (" << G.Index
+ << ") is already in a group " + MainGroup->Name + " ("
+ << MainGroup->Index << ")\n";
+ errs().flush();
+ continue;
}
+ W.startLine() << GM.Name << " (" << GM.Index << ")\n";
}
- ++SectionIndex;
}
- if (!HasGroups)
+
+ if (V.empty())
W.startLine() << "There are no group sections in the file.\n";
}
@@ -3529,7 +3768,9 @@ template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) {
for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
++SectionNumber;
- if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA)
+ if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
+ Sec.sh_type != ELF::SHT_ANDROID_REL &&
+ Sec.sh_type != ELF::SHT_ANDROID_RELA)
continue;
StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
@@ -3562,6 +3803,11 @@ void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) {
for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec)))
printRelocation(Obj, R, SymTab);
break;
+ case ELF::SHT_ANDROID_REL:
+ case ELF::SHT_ANDROID_RELA:
+ for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec)))
+ printRelocation(Obj, R, SymTab);
+ break;
}
}
@@ -3682,8 +3928,7 @@ void LLVMStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
bool IsDynamic) {
unsigned SectionIndex = 0;
StringRef SectionName;
- getSectionNameIndex(*Obj, Symbol, First, this->dumper()->getShndxTable(),
- SectionName, SectionIndex);
+ this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex);
std::string FullSymbolName =
this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic);
unsigned char SymbolType = Symbol->getType();
@@ -3820,3 +4065,114 @@ template <class ELFT>
void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
W.startLine() << "printNotes not implemented!\n";
}
+
+template <class ELFT>
+void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
+ auto PrintEntry = [&](const Elf_Addr *E) {
+ W.printHex("Address", Parser.getGotAddress(E));
+ W.printNumber("Access", Parser.getGotOffset(E));
+ W.printHex("Initial", *E);
+ };
+
+ DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT");
+
+ W.printHex("Canonical gp value", Parser.getGp());
+ {
+ ListScope RS(W, "Reserved entries");
+ {
+ DictScope D(W, "Entry");
+ PrintEntry(Parser.getGotLazyResolver());
+ W.printString("Purpose", StringRef("Lazy resolver"));
+ }
+
+ if (Parser.getGotModulePointer()) {
+ DictScope D(W, "Entry");
+ PrintEntry(Parser.getGotModulePointer());
+ W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
+ }
+ }
+ {
+ ListScope LS(W, "Local entries");
+ for (auto &E : Parser.getLocalEntries()) {
+ DictScope D(W, "Entry");
+ PrintEntry(&E);
+ }
+ }
+
+ if (Parser.IsStatic)
+ return;
+
+ {
+ ListScope GS(W, "Global entries");
+ for (auto &E : Parser.getGlobalEntries()) {
+ DictScope D(W, "Entry");
+
+ PrintEntry(&E);
+
+ const Elf_Sym *Sym = Parser.getGotSym(&E);
+ W.printHex("Value", Sym->st_value);
+ W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
+
+ unsigned SectionIndex = 0;
+ StringRef SectionName;
+ this->dumper()->getSectionNameIndex(
+ Sym, this->dumper()->dynamic_symbols().begin(), SectionName,
+ SectionIndex);
+ W.printHex("Section", SectionName, SectionIndex);
+
+ std::string SymName = this->dumper()->getFullSymbolName(
+ Sym, this->dumper()->getDynamicStringTable(), true);
+ W.printNumber("Name", SymName, Sym->st_name);
+ }
+ }
+
+ W.printNumber("Number of TLS and multi-GOT entries",
+ uint64_t(Parser.getOtherEntries().size()));
+}
+
+template <class ELFT>
+void LLVMStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
+ auto PrintEntry = [&](const Elf_Addr *E) {
+ W.printHex("Address", Parser.getPltAddress(E));
+ W.printHex("Initial", *E);
+ };
+
+ DictScope GS(W, "PLT GOT");
+
+ {
+ ListScope RS(W, "Reserved entries");
+ {
+ DictScope D(W, "Entry");
+ PrintEntry(Parser.getPltLazyResolver());
+ W.printString("Purpose", StringRef("PLT lazy resolver"));
+ }
+
+ if (auto E = Parser.getPltModulePointer()) {
+ DictScope D(W, "Entry");
+ PrintEntry(E);
+ W.printString("Purpose", StringRef("Module pointer"));
+ }
+ }
+ {
+ ListScope LS(W, "Entries");
+ for (auto &E : Parser.getPltEntries()) {
+ DictScope D(W, "Entry");
+ PrintEntry(&E);
+
+ const Elf_Sym *Sym = Parser.getPltSym(&E);
+ W.printHex("Value", Sym->st_value);
+ W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
+
+ unsigned SectionIndex = 0;
+ StringRef SectionName;
+ this->dumper()->getSectionNameIndex(
+ Sym, this->dumper()->dynamic_symbols().begin(), SectionName,
+ SectionIndex);
+ W.printHex("Section", SectionName, SectionIndex);
+
+ std::string SymName =
+ this->dumper()->getFullSymbolName(Sym, Parser.getPltStrTable(), true);
+ W.printNumber("Name", SymName, Sym->st_name);
+ }
+ }
+}