diff options
| author | 2018-04-06 14:26:03 +0000 | |
|---|---|---|
| committer | 2018-04-06 14:26:03 +0000 | |
| commit | bdabc2f19ffb9e20600dad6e8a300842a7bda50e (patch) | |
| tree | c50e7b2e5449b074651bb82a58517a8ebc4a8cf7 /gnu/llvm/tools/llvm-readobj/ELFDumper.cpp | |
| parent | Print a 'p' flag for file descriptors that were opened after pledge(2). (diff) | |
| download | wireguard-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.cpp | 1054 |
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); + } + } +} |
