diff options
| author | 2019-01-27 16:42:12 +0000 | |
|---|---|---|
| committer | 2019-01-27 16:42:12 +0000 | |
| commit | b773203fb58f3ef282fb69c832d8710cab5bc82d (patch) | |
| tree | e75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/llvm-readobj/ELFDumper.cpp | |
| parent | tweak errno in previous (diff) | |
| download | wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip | |
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/llvm-readobj/ELFDumper.cpp')
| -rw-r--r-- | gnu/llvm/tools/llvm-readobj/ELFDumper.cpp | 734 |
1 files changed, 541 insertions, 193 deletions
diff --git a/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp b/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp index 5605eaea755..645ec2d7e04 100644 --- a/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -8,11 +8,12 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file implements the ELF-specific dumper for llvm-readobj. +/// This file implements the ELF-specific dumper for llvm-readobj. /// //===----------------------------------------------------------------------===// #include "ARMEHABIPrinter.h" +#include "DwarfCFIEHPrinter.h" #include "Error.h" #include "ObjDumper.h" #include "StackMapPrinter.h" @@ -43,6 +44,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MipsABIFlags.h" #include "llvm/Support/ScopedPrinter.h" @@ -77,28 +79,32 @@ 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; \ - using Elf_Dyn_Range = typename ELFO::Elf_Dyn_Range; \ - using Elf_Rel = typename ELFO::Elf_Rel; \ - using Elf_Rela = typename ELFO::Elf_Rela; \ - using Elf_Rel_Range = typename ELFO::Elf_Rel_Range; \ - using Elf_Rela_Range = typename ELFO::Elf_Rela_Range; \ - using Elf_Phdr = typename ELFO::Elf_Phdr; \ - using Elf_Half = typename ELFO::Elf_Half; \ - using Elf_Ehdr = typename ELFO::Elf_Ehdr; \ - using Elf_Word = typename ELFO::Elf_Word; \ - using Elf_Hash = typename ELFO::Elf_Hash; \ - using Elf_GnuHash = typename ELFO::Elf_GnuHash; \ - using Elf_Sym_Range = typename ELFO::Elf_Sym_Range; \ - using Elf_Versym = typename ELFO::Elf_Versym; \ - using Elf_Verneed = typename ELFO::Elf_Verneed; \ - using Elf_Vernaux = typename ELFO::Elf_Vernaux; \ - using Elf_Verdef = typename ELFO::Elf_Verdef; \ - using Elf_Verdaux = typename ELFO::Elf_Verdaux; \ - using uintX_t = typename ELFO::uintX_t; + using Elf_Addr = typename ELFT::Addr; \ + using Elf_Shdr = typename ELFT::Shdr; \ + using Elf_Sym = typename ELFT::Sym; \ + using Elf_Dyn = typename ELFT::Dyn; \ + using Elf_Dyn_Range = typename ELFT::DynRange; \ + using Elf_Rel = typename ELFT::Rel; \ + using Elf_Rela = typename ELFT::Rela; \ + using Elf_Relr = typename ELFT::Relr; \ + using Elf_Rel_Range = typename ELFT::RelRange; \ + using Elf_Rela_Range = typename ELFT::RelaRange; \ + using Elf_Relr_Range = typename ELFT::RelrRange; \ + using Elf_Phdr = typename ELFT::Phdr; \ + using Elf_Half = typename ELFT::Half; \ + using Elf_Ehdr = typename ELFT::Ehdr; \ + using Elf_Word = typename ELFT::Word; \ + using Elf_Hash = typename ELFT::Hash; \ + using Elf_GnuHash = typename ELFT::GnuHash; \ + using Elf_Note = typename ELFT::Note; \ + using Elf_Sym_Range = typename ELFT::SymRange; \ + using Elf_Versym = typename ELFT::Versym; \ + using Elf_Verneed = typename ELFT::Verneed; \ + using Elf_Vernaux = typename ELFT::Vernaux; \ + using Elf_Verdef = typename ELFT::Verdef; \ + using Elf_Verdaux = typename ELFT::Verdaux; \ + using Elf_CGProfile = typename ELFT::CGProfile; \ + using uintX_t = typename ELFT::uint; namespace { @@ -113,11 +119,11 @@ struct DynRegionInfo { DynRegionInfo(const void *A, uint64_t S, uint64_t ES) : Addr(A), Size(S), EntSize(ES) {} - /// \brief Address in current address space. + /// Address in current address space. const void *Addr = nullptr; - /// \brief Size in bytes of the region. + /// Size in bytes of the region. uint64_t Size = 0; - /// \brief Size of each entity in the region. + /// Size of each entity in the region. uint64_t EntSize = 0; template <typename Type> ArrayRef<Type> getAsArrayRef() const { @@ -162,8 +168,13 @@ public: void printHashHistogram() override; + void printCGProfile() override; + void printAddrsig() override; + void printNotes() override; + void printELFLinkerOptions() override; + private: std::unique_ptr<DumpStyle<ELFT>> ELFDumperStyle; @@ -198,6 +209,7 @@ private: const ELFO *Obj; DynRegionInfo DynRelRegion; DynRegionInfo DynRelaRegion; + DynRegionInfo DynRelrRegion; DynRegionInfo DynPLTRelRegion; DynRegionInfo DynSymRegion; DynRegionInfo DynamicTable; @@ -206,6 +218,8 @@ private: const Elf_Hash *HashTable = nullptr; const Elf_GnuHash *GnuHashTable = nullptr; const Elf_Shdr *DotSymtabSec = nullptr; + const Elf_Shdr *DotCGProfileSec = nullptr; + const Elf_Shdr *DotAddrsigSec = nullptr; StringRef DynSymtabName; ArrayRef<Elf_Word> ShndxTable; @@ -248,18 +262,23 @@ public: Elf_Rel_Range dyn_rels() const; Elf_Rela_Range dyn_relas() const; + Elf_Relr_Range dyn_relrs() 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; + StringRef getStaticSymbolName(uint32_t Index) const; void printSymbolsHelper(bool IsDynamic) const; const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } + const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; } + const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; } ArrayRef<Elf_Word> getShndxTable() const { return ShndxTable; } StringRef getDynamicStringTable() const { return DynamicStringTable; } const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; } const DynRegionInfo &getDynRelaRegion() const { return DynRelaRegion; } + const DynRegionInfo &getDynRelrRegion() const { return DynRelrRegion; } const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; } const Elf_Hash *getHashTable() const { return HashTable; } const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; } @@ -295,8 +314,8 @@ template <class ELFT> class MipsGOTParser; template <typename ELFT> class DumpStyle { public: - using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr; - using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym; + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Sym = typename ELFT::Sym; DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {} virtual ~DumpStyle() = default; @@ -315,7 +334,10 @@ public: bool IsDynamic) = 0; virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0; virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0; + virtual void printCGProfile(const ELFFile<ELFT> *Obj) = 0; + virtual void printAddrsig(const ELFFile<ELFT> *Obj) = 0; virtual void printNotes(const ELFFile<ELFT> *Obj) = 0; + virtual void printELFLinkerOptions(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; } @@ -344,7 +366,10 @@ public: size_t Offset) override; void printProgramHeaders(const ELFO *Obj) override; void printHashHistogram(const ELFFile<ELFT> *Obj) override; + void printCGProfile(const ELFFile<ELFT> *Obj) override; + void printAddrsig(const ELFFile<ELFT> *Obj) override; void printNotes(const ELFFile<ELFT> *Obj) override; + void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override; void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; @@ -374,6 +399,7 @@ private: } void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym, StringRef StrTable, uint32_t Bucket); + void printRelocHeader(unsigned SType); void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, const Elf_Rela &R, bool IsRela); void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, @@ -404,7 +430,10 @@ public: void printDynamicRelocations(const ELFO *Obj) override; void printProgramHeaders(const ELFO *Obj) override; void printHashHistogram(const ELFFile<ELFT> *Obj) override; + void printCGProfile(const ELFFile<ELFT> *Obj) override; + void printAddrsig(const ELFFile<ELFT> *Obj) override; void printNotes(const ELFFile<ELFT> *Obj) override; + void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override; void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; @@ -730,6 +759,16 @@ StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab, } template <typename ELFT> +StringRef ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const { + StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); + Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); + if (Index >= Syms.size()) + reportError("Invalid symbol index"); + const Elf_Sym *Sym = &Syms[Index]; + return unwrapOrError(Sym->getName(StrTable)); +} + +template <typename ELFT> std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic) const { @@ -1007,7 +1046,6 @@ static const EnumEntry<unsigned> ElfMachineType[] = { ENUM_ENT(EM_56800EX, "EM_56800EX"), ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"), ENUM_ENT(EM_RISCV, "RISC-V"), - ENUM_ENT(EM_WEBASSEMBLY, "EM_WEBASSEMBLY"), ENUM_ENT(EM_LANAI, "EM_LANAI"), ENUM_ENT(EM_BPF, "EM_BPF"), }; @@ -1255,9 +1293,39 @@ static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { }; 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) + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906), + LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_XNACK) }; static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = { @@ -1353,6 +1421,16 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer) reportError("Multiple SHT_GNU_verneed"); dot_gnu_version_r_sec = &Sec; break; + case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: + if (DotCGProfileSec != nullptr) + reportError("Multiple .note.llvm.cgprofile"); + DotCGProfileSec = &Sec; + break; + case ELF::SHT_LLVM_ADDRSIG: + if (DotAddrsigSec != nullptr) + reportError("Multiple .llvm_addrsig"); + DotAddrsigSec = &Sec; + break; } } @@ -1427,6 +1505,18 @@ void ELFDumper<ELFT>::parseDynamicTable( case ELF::DT_RELENT: DynRelRegion.EntSize = Dyn.getVal(); break; + case ELF::DT_RELR: + case ELF::DT_ANDROID_RELR: + DynRelrRegion.Addr = toMappedAddr(Dyn.getPtr()); + break; + case ELF::DT_RELRSZ: + case ELF::DT_ANDROID_RELRSZ: + DynRelrRegion.Size = Dyn.getVal(); + break; + case ELF::DT_RELRENT: + case ELF::DT_ANDROID_RELRENT: + DynRelrRegion.EntSize = Dyn.getVal(); + break; case ELF::DT_PLTREL: if (Dyn.getVal() == DT_REL) DynPLTRelRegion.EntSize = sizeof(Elf_Rel); @@ -1460,6 +1550,11 @@ typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const { return DynRelaRegion.getAsArrayRef<Elf_Rela>(); } +template <typename ELFT> +typename ELFDumper<ELFT>::Elf_Relr_Range ELFDumper<ELFT>::dyn_relrs() const { + return DynRelrRegion.getAsArrayRef<Elf_Relr>(); +} + template<class ELFT> void ELFDumper<ELFT>::printFileHeaders() { ELFDumperStyle->printFileHeaders(Obj); @@ -1497,93 +1592,69 @@ template <class ELFT> void ELFDumper<ELFT>::printHashHistogram() { ELFDumperStyle->printHashHistogram(Obj); } +template <class ELFT> void ELFDumper<ELFT>::printCGProfile() { + ELFDumperStyle->printCGProfile(Obj); +} + template <class ELFT> void ELFDumper<ELFT>::printNotes() { ELFDumperStyle->printNotes(Obj); } -#define LLVM_READOBJ_TYPE_CASE(name) \ - case DT_##name: return #name +template <class ELFT> void ELFDumper<ELFT>::printELFLinkerOptions() { + ELFDumperStyle->printELFLinkerOptions(Obj); +} static const char *getTypeString(unsigned Arch, uint64_t Type) { +#define DYNAMIC_TAG(n, v) switch (Arch) { case EM_HEXAGON: switch (Type) { - LLVM_READOBJ_TYPE_CASE(HEXAGON_SYMSZ); - LLVM_READOBJ_TYPE_CASE(HEXAGON_VER); - LLVM_READOBJ_TYPE_CASE(HEXAGON_PLT); +#define HEXAGON_DYNAMIC_TAG(name, value) \ + case DT_##name: \ + return #name; +#include "llvm/BinaryFormat/DynamicTags.def" +#undef HEXAGON_DYNAMIC_TAG } + case EM_MIPS: switch (Type) { - LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP_REL); - LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION); - LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS); - LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS); - LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO); - LLVM_READOBJ_TYPE_CASE(MIPS_SYMTABNO); - LLVM_READOBJ_TYPE_CASE(MIPS_UNREFEXTNO); - LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM); - LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP); - LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT); - LLVM_READOBJ_TYPE_CASE(MIPS_OPTIONS); +#define MIPS_DYNAMIC_TAG(name, value) \ + case DT_##name: \ + return #name; +#include "llvm/BinaryFormat/DynamicTags.def" +#undef MIPS_DYNAMIC_TAG + } + + case EM_PPC64: + switch(Type) { +#define PPC64_DYNAMIC_TAG(name, value) \ + case DT_##name: \ + return #name; +#include "llvm/BinaryFormat/DynamicTags.def" +#undef PPC64_DYNAMIC_TAG } } +#undef DYNAMIC_TAG 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); - LLVM_READOBJ_TYPE_CASE(FINI_ARRAY); - LLVM_READOBJ_TYPE_CASE(FINI_ARRAYSZ); - LLVM_READOBJ_TYPE_CASE(FLAGS); - LLVM_READOBJ_TYPE_CASE(FLAGS_1); - LLVM_READOBJ_TYPE_CASE(HASH); - LLVM_READOBJ_TYPE_CASE(INIT); - LLVM_READOBJ_TYPE_CASE(INIT_ARRAY); - LLVM_READOBJ_TYPE_CASE(INIT_ARRAYSZ); - LLVM_READOBJ_TYPE_CASE(PREINIT_ARRAY); - LLVM_READOBJ_TYPE_CASE(PREINIT_ARRAYSZ); - LLVM_READOBJ_TYPE_CASE(JMPREL); - LLVM_READOBJ_TYPE_CASE(NEEDED); - LLVM_READOBJ_TYPE_CASE(NULL); - LLVM_READOBJ_TYPE_CASE(PLTGOT); - LLVM_READOBJ_TYPE_CASE(PLTREL); - LLVM_READOBJ_TYPE_CASE(PLTRELSZ); - LLVM_READOBJ_TYPE_CASE(REL); - LLVM_READOBJ_TYPE_CASE(RELA); - LLVM_READOBJ_TYPE_CASE(RELENT); - LLVM_READOBJ_TYPE_CASE(RELSZ); - LLVM_READOBJ_TYPE_CASE(RELAENT); - LLVM_READOBJ_TYPE_CASE(RELASZ); - LLVM_READOBJ_TYPE_CASE(RPATH); - LLVM_READOBJ_TYPE_CASE(RUNPATH); - LLVM_READOBJ_TYPE_CASE(SONAME); - LLVM_READOBJ_TYPE_CASE(STRSZ); - LLVM_READOBJ_TYPE_CASE(STRTAB); - LLVM_READOBJ_TYPE_CASE(SYMBOLIC); - LLVM_READOBJ_TYPE_CASE(SYMENT); - LLVM_READOBJ_TYPE_CASE(SYMTAB); - LLVM_READOBJ_TYPE_CASE(TEXTREL); - LLVM_READOBJ_TYPE_CASE(VERDEF); - LLVM_READOBJ_TYPE_CASE(VERDEFNUM); - LLVM_READOBJ_TYPE_CASE(VERNEED); - LLVM_READOBJ_TYPE_CASE(VERNEEDNUM); - LLVM_READOBJ_TYPE_CASE(VERSYM); - LLVM_READOBJ_TYPE_CASE(RELACOUNT); - LLVM_READOBJ_TYPE_CASE(RELCOUNT); - LLVM_READOBJ_TYPE_CASE(GNU_HASH); - LLVM_READOBJ_TYPE_CASE(TLSDESC_PLT); - LLVM_READOBJ_TYPE_CASE(TLSDESC_GOT); - LLVM_READOBJ_TYPE_CASE(AUXILIARY); - LLVM_READOBJ_TYPE_CASE(FILTER); +// Now handle all dynamic tags except the architecture specific ones +#define MIPS_DYNAMIC_TAG(name, value) +#define HEXAGON_DYNAMIC_TAG(name, value) +#define PPC64_DYNAMIC_TAG(name, value) +// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. +#define DYNAMIC_TAG_MARKER(name, value) +#define DYNAMIC_TAG(name, value) \ + case DT_##name: \ + return #name; +#include "llvm/BinaryFormat/DynamicTags.def" +#undef DYNAMIC_TAG +#undef MIPS_DYNAMIC_TAG +#undef HEXAGON_DYNAMIC_TAG +#undef PPC64_DYNAMIC_TAG +#undef DYNAMIC_TAG_MARKER default: return "unknown"; } } -#undef LLVM_READOBJ_TYPE_CASE - #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ { #enum, prefix##_##enum } @@ -1771,16 +1842,20 @@ void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) { template<class ELFT> void ELFDumper<ELFT>::printUnwindInfo() { + const unsigned Machine = Obj->getHeader()->e_machine; + if (Machine == EM_386 || Machine == EM_X86_64) { + DwarfCFIEH::PrinterContext<ELFT> Ctx(W, Obj); + return Ctx.printUnwindInformation(); + } W.startLine() << "UnwindInfo not implemented.\n"; } namespace { -template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() { +template <> void ELFDumper<ELF32LE>::printUnwindInfo() { const unsigned Machine = Obj->getHeader()->e_machine; if (Machine == EM_ARM) { - ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx( - W, Obj, DotSymtabSec); + ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, DotSymtabSec); return Ctx.PrintUnwindInformation(); } W.startLine() << "UnwindInfo not implemented.\n"; @@ -1841,9 +1916,8 @@ void ELFDumper<ELFT>::printNeededLibraries() { std::stable_sort(Libs.begin(), Libs.end()); - for (const auto &L : Libs) { - outs() << " " << L << "\n"; - } + for (const auto &L : Libs) + W.startLine() << L << "\n"; } @@ -1877,7 +1951,7 @@ void ELFDumper<ELFT>::printGnuHashTable() { } template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { - outs() << "LoadName: " << SOName << '\n'; + W.printString("LoadName", SOName); } template <class ELFT> @@ -1887,7 +1961,7 @@ void ELFDumper<ELFT>::printAttributes() { namespace { -template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() { +template <> void ELFDumper<ELF32LE>::printAttributes() { if (Obj->getHeader()->e_machine != EM_ARM) { W.startLine() << "Attributes not implemented.\n"; return; @@ -2219,7 +2293,9 @@ static const EnumEntry<unsigned> ElfMipsASEFlags[] = { {"MSA", Mips::AFL_ASE_MSA}, {"MIPS16", Mips::AFL_ASE_MIPS16}, {"microMIPS", Mips::AFL_ASE_MICROMIPS}, - {"XPA", Mips::AFL_ASE_XPA} + {"XPA", Mips::AFL_ASE_XPA}, + {"CRC", Mips::AFL_ASE_CRC}, + {"GINV", Mips::AFL_ASE_GINV}, }; static const EnumEntry<unsigned> ElfMipsFpABIType[] = { @@ -2361,14 +2437,18 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { ArrayRef<uint8_t> StackMapContentsArray = unwrapOrError(Obj->getSectionContents(StackMapSection)); - prettyPrintStackMap(outs(), StackMapV2Parser<ELFT::TargetEndianness>( - StackMapContentsArray)); + prettyPrintStackMap( + W, StackMapV2Parser<ELFT::TargetEndianness>(StackMapContentsArray)); } template <class ELFT> void ELFDumper<ELFT>::printGroupSections() { ELFDumperStyle->printGroupSections(Obj); } +template <class ELFT> void ELFDumper<ELFT>::printAddrsig() { + ELFDumperStyle->printAddrsig(Obj); +} + static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, StringRef Str2) { OS.PadToColumn(2u); @@ -2378,6 +2458,30 @@ static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, OS.flush(); } +template <class ELFT> +static std::string getSectionHeadersNumString(const ELFFile<ELFT> *Obj) { + const typename ELFT::Ehdr *ElfHeader = Obj->getHeader(); + if (ElfHeader->e_shnum != 0) + return to_string(ElfHeader->e_shnum); + + ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections()); + if (Arr.empty()) + return "0"; + return "0 (" + to_string(Arr[0].sh_size) + ")"; +} + +template <class ELFT> +static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> *Obj) { + const typename ELFT::Ehdr *ElfHeader = Obj->getHeader(); + if (ElfHeader->e_shstrndx != SHN_XINDEX) + return to_string(ElfHeader->e_shstrndx); + + ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections()); + if (Arr.empty()) + return "65535 (corrupt: out of range)"; + return to_string(ElfHeader->e_shstrndx) + " (" + to_string(Arr[0].sh_link) + ")"; +} + template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) { const Elf_Ehdr *e = Obj->getHeader(); OS << "ELF Header:\n"; @@ -2423,9 +2527,9 @@ template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) { printFields(OS, "Number of program headers:", Str); Str = to_string(e->e_shentsize) + " (bytes)"; printFields(OS, "Size of section headers:", Str); - Str = to_string(e->e_shnum); + Str = getSectionHeadersNumString(Obj); printFields(OS, "Number of section headers:", Str); - Str = to_string(e->e_shstrndx); + Str = getSectionHeaderTableIndexString(Obj); printFields(OS, "Section header string table index:", Str); } @@ -2440,15 +2544,17 @@ struct GroupSection { StringRef Signature; uint64_t ShName; uint64_t Index; + uint32_t Link; + uint32_t Info; 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; + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Sym = typename ELFT::Sym; + using Elf_Word = typename ELFT::Word; std::vector<GroupSection> Ret; uint64_t I = 0; @@ -2466,7 +2572,14 @@ std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) { 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], {}}); + Ret.push_back({Name, + Signature, + Sec.sh_name, + I - 1, + Sec.sh_link, + Sec.sh_info, + Data[0], + {}}); std::vector<GroupMember> &GM = Ret.back().Members; for (uint32_t Ndx : Data.slice(1)) { @@ -2522,7 +2635,6 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, const Elf_Rela &R, bool IsRela) { std::string Offset, Info, Addend, Value; SmallString<32> RelocName; - StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); StringRef TargetName; const Elf_Sym *Sym = nullptr; unsigned Width = ELFT::Is64Bits ? 16 : 8; @@ -2538,6 +2650,7 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); TargetName = unwrapOrError(Obj->getSectionName(Sec)); } else if (Sym) { + StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); TargetName = unwrapOrError(Sym->getName(StrTable)); } @@ -2569,35 +2682,62 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, OS << "\n"; } -static inline void printRelocHeader(raw_ostream &OS, bool Is64, bool IsRela) { - if (Is64) - OS << " Offset Info Type" +template <class ELFT> void GNUStyle<ELFT>::printRelocHeader(unsigned SType) { + bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; + bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; + if (ELFT::Is64Bits) + OS << " "; + else + OS << " "; + if (IsRelr && opts::RawRelr) + OS << "Data "; + else + OS << "Offset"; + if (ELFT::Is64Bits) + OS << " Info Type" << " Symbol's Value Symbol's Name"; else - OS << " Offset Info Type Sym. Value " - << "Symbol's Name"; + OS << " Info Type Sym. Value Symbol's Name"; if (IsRela) - OS << (IsRela ? " + Addend" : ""); + OS << " + Addend"; OS << "\n"; } 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_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL && - Sec.sh_type != ELF::SHT_ANDROID_RELA) + Sec.sh_type != ELF::SHT_ANDROID_RELA && + Sec.sh_type != ELF::SHT_ANDROID_RELR) continue; HasRelocSections = true; StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); unsigned Entries = Sec.getEntityCount(); + std::vector<Elf_Rela> AndroidRelas; + if (Sec.sh_type == ELF::SHT_ANDROID_REL || + Sec.sh_type == ELF::SHT_ANDROID_RELA) { + // Android's packed relocation section needs to be unpacked first + // to get the actual number of entries. + AndroidRelas = unwrapOrError(Obj->android_relas(&Sec)); + Entries = AndroidRelas.size(); + } + std::vector<Elf_Rela> RelrRelas; + if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || + Sec.sh_type == ELF::SHT_ANDROID_RELR)) { + // .relr.dyn relative relocation section needs to be unpacked first + // to get the actual number of entries. + Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(&Sec)); + RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + Entries = RelrRelas.size(); + } uintX_t Offset = Sec.sh_offset; 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 || - Sec.sh_type == ELF::SHT_ANDROID_RELA); + printRelocHeader(Sec.sh_type); const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link)); switch (Sec.sh_type) { case ELF::SHT_REL: @@ -2613,9 +2753,19 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) { for (const auto &R : unwrapOrError(Obj->relas(&Sec))) printRelocation(Obj, SymTab, R, true); break; + case ELF::SHT_RELR: + case ELF::SHT_ANDROID_RELR: + if (opts::RawRelr) + for (const auto &R : unwrapOrError(Obj->relrs(&Sec))) + OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8)) + << "\n"; + else + for (const auto &R : RelrRelas) + printRelocation(Obj, SymTab, R, false); + break; case ELF::SHT_ANDROID_REL: case ELF::SHT_ANDROID_RELA: - for (const auto &R : unwrapOrError(Obj->android_relas(&Sec))) + for (const auto &R : AndroidRelas) printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA); break; } @@ -2694,8 +2844,17 @@ std::string getSectionTypeString(unsigned Arch, unsigned Type) { return "GROUP"; case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICES"; + case SHT_RELR: + case SHT_ANDROID_RELR: + return "RELR"; case SHT_LLVM_ODRTAB: return "LLVM_ODRTAB"; + case SHT_LLVM_LINKER_OPTIONS: + return "LLVM_LINKER_OPTIONS"; + case SHT_LLVM_CALL_GRAPH_PROFILE: + return "LLVM_CALL_GRAPH_PROFILE"; + case SHT_LLVM_ADDRSIG: + return "LLVM_ADDRSIG"; // FIXME: Parse processor specific GNU attributes case SHT_GNU_ATTRIBUTES: return "ATTRIBUTES"; @@ -2727,7 +2886,9 @@ template <class ELFT> void GNUStyle<ELFT>::printSections(const ELFO *Obj) { Bias = 8; Width = 8; } - OS << "There are " << to_string(Obj->getHeader()->e_shnum) + + ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections()); + OS << "There are " << to_string(Sections.size()) << " section headers, starting at offset " << "0x" << to_hexString(Obj->getHeader()->e_shoff, false) << ":\n\n"; OS << "Section Headers:\n"; @@ -2746,7 +2907,7 @@ template <class ELFT> void GNUStyle<ELFT>::printSections(const ELFO *Obj) { printField(f); OS << "\n"; - for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { + for (const Elf_Shdr &Sec : Sections) { Number = to_string(SectionIndex); Fields[0].Str = Number; Fields[1].Str = unwrapOrError(Obj->getSectionName(&Sec)); @@ -3198,13 +3359,14 @@ template <class ELFT> void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); + const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); if (DynRelaRegion.Size > 0) { OS << "\n'RELA' relocation section at offset " << format_hex(reinterpret_cast<const uint8_t *>(DynRelaRegion.Addr) - Obj->base(), 1) << " contains " << DynRelaRegion.Size << " bytes:\n"; - printRelocHeader(OS, ELFT::Is64Bits, true); + printRelocHeader(ELF::SHT_RELA); for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) printDynamicRelocation(Obj, Rela, true); } @@ -3213,7 +3375,7 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { << format_hex(reinterpret_cast<const uint8_t *>(DynRelRegion.Addr) - Obj->base(), 1) << " contains " << DynRelRegion.Size << " bytes:\n"; - printRelocHeader(OS, ELFT::Is64Bits, false); + printRelocHeader(ELF::SHT_REL); for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { Elf_Rela Rela; Rela.r_offset = Rel.r_offset; @@ -3222,6 +3384,18 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { printDynamicRelocation(Obj, Rela, false); } } + if (DynRelrRegion.Size > 0) { + OS << "\n'RELR' relocation section at offset " + << format_hex(reinterpret_cast<const uint8_t *>(DynRelrRegion.Addr) - + Obj->base(), + 1) << " contains " << DynRelrRegion.Size << " bytes:\n"; + printRelocHeader(ELF::SHT_REL); + Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); + std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &Rela : RelrRelas) { + printDynamicRelocation(Obj, Rela, false); + } + } if (DynPLTRelRegion.Size) { OS << "\n'PLT' relocation section at offset " << format_hex(reinterpret_cast<const uint8_t *>(DynPLTRelRegion.Addr) - @@ -3229,11 +3403,11 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { 1) << " contains " << DynPLTRelRegion.Size << " bytes:\n"; } if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) { - printRelocHeader(OS, ELFT::Is64Bits, true); + printRelocHeader(ELF::SHT_RELA); for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>()) printDynamicRelocation(Obj, Rela, true); } else { - printRelocHeader(OS, ELFT::Is64Bits, false); + printRelocHeader(ELF::SHT_REL); for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) { Elf_Rela Rela; Rela.r_offset = Rel.r_offset; @@ -3349,6 +3523,16 @@ void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { } } +template <class ELFT> +void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) { + OS << "GNUStyle::printCGProfile not implemented\n"; +} + +template <class ELFT> +void GNUStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) { + OS << "GNUStyle::printAddrsig not implemented\n"; +} + static std::string getGNUNoteTypeName(const uint32_t NT) { static const struct { uint32_t ID; @@ -3358,6 +3542,7 @@ static std::string getGNUNoteTypeName(const uint32_t NT) { {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"}, {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"}, + {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"}, }; for (const auto &Note : Notes) @@ -3422,9 +3607,65 @@ static std::string getAMDGPUNoteTypeName(const uint32_t NT) { } template <typename ELFT> +static void printGNUProperty(raw_ostream &OS, uint32_t Type, uint32_t DataSize, + ArrayRef<uint8_t> Data) { + switch (Type) { + default: + OS << format(" <application-specific type 0x%x>\n", Type); + return; + case GNU_PROPERTY_STACK_SIZE: { + OS << " stack size: "; + if (DataSize == sizeof(typename ELFT::uint)) + OS << format("0x%llx\n", + (uint64_t)(*(const typename ELFT::Addr *)Data.data())); + else + OS << format("<corrupt length: 0x%x>\n", DataSize); + break; + } + case GNU_PROPERTY_NO_COPY_ON_PROTECTED: + OS << " no copy on protected"; + if (DataSize) + OS << format(" <corrupt length: 0x%x>", DataSize); + OS << "\n"; + break; + case GNU_PROPERTY_X86_FEATURE_1_AND: + OS << " X86 features: "; + if (DataSize != 4 && DataSize != 8) { + OS << format("<corrupt length: 0x%x>\n", DataSize); + break; + } + uint64_t CFProtection = + (DataSize == 4) + ? support::endian::read32<ELFT::TargetEndianness>(Data.data()) + : support::endian::read64<ELFT::TargetEndianness>(Data.data()); + if (CFProtection == 0) { + OS << "none\n"; + break; + } + if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_IBT) { + OS << "IBT"; + CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_IBT; + if (CFProtection) + OS << ", "; + } + if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_SHSTK) { + OS << "SHSTK"; + CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK; + if (CFProtection) + OS << ", "; + } + if (CFProtection) + OS << format("<unknown flags: 0x%llx>", CFProtection); + OS << "\n"; + break; + } +} + +template <typename ELFT> static void printGNUNote(raw_ostream &OS, uint32_t NoteType, - ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words, - size_t Size) { + ArrayRef<typename ELFT::Word> Words, size_t Size) { + using Elf_Word = typename ELFT::Word; + switch (NoteType) { default: return; @@ -3456,15 +3697,37 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType, OS << " Version: " << StringRef(reinterpret_cast<const char *>(Words.data()), Size); break; - } + case ELF::NT_GNU_PROPERTY_TYPE_0: + OS << " Properties:"; + + ArrayRef<uint8_t> Arr(reinterpret_cast<const uint8_t *>(Words.data()), + Size); + while (Arr.size() >= 8) { + uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data()); + uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4); + Arr = Arr.drop_front(8); + + // Take padding size into account if present. + uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint)); + if (Arr.size() < PaddedSize) { + OS << format(" <corrupt type (0x%x) datasz: 0x%x>\n", Type, + DataSize); + break; + } + printGNUProperty<ELFT>(OS, Type, DataSize, Arr.take_front(PaddedSize)); + Arr = Arr.drop_front(PaddedSize); + } + if (!Arr.empty()) + OS << " <corrupted GNU_PROPERTY_TYPE_0>"; + break; + } OS << '\n'; } template <typename ELFT> static void printAMDGPUNote(raw_ostream &OS, uint32_t NoteType, - ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words, - size_t Size) { + ArrayRef<typename ELFT::Word> Words, size_t Size) { switch (NoteType) { default: return; @@ -3499,66 +3762,66 @@ void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { const Elf_Ehdr *e = Obj->getHeader(); bool IsCore = e->e_type == ELF::ET_CORE; - auto process = [&](const typename ELFFile<ELFT>::Elf_Off Offset, - const typename ELFFile<ELFT>::Elf_Addr Size) { - if (Size <= 0) - return; - - const auto *P = static_cast<const uint8_t *>(Obj->base() + Offset); - const auto *E = P + Size; - + auto PrintHeader = [&](const typename ELFT::Off Offset, + const typename ELFT::Addr Size) { OS << "Displaying notes found at file offset " << format_hex(Offset, 10) << " with length " << format_hex(Size, 10) << ":\n" << " Owner Data size\tDescription\n"; + }; - while (P < E) { - const Elf_Word *Words = reinterpret_cast<const Elf_Word *>(&P[0]); - - uint32_t NameSize = Words[0]; - uint32_t DescriptorSize = Words[1]; - uint32_t Type = Words[2]; - - ArrayRef<Elf_Word> Descriptor(&Words[3 + (alignTo<4>(NameSize) / 4)], - alignTo<4>(DescriptorSize) / 4); - - StringRef Name; - if (NameSize) - Name = - StringRef(reinterpret_cast<const char *>(&Words[3]), NameSize - 1); - - OS << " " << Name << std::string(22 - NameSize, ' ') - << format_hex(DescriptorSize, 10) << '\t'; - - if (Name == "GNU") { - OS << getGNUNoteTypeName(Type) << '\n'; - 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) << ')'; - } - OS << '\n'; - - P = P + 3 * sizeof(Elf_Word) + alignTo<4>(NameSize) + - alignTo<4>(DescriptorSize); + auto ProcessNote = [&](const Elf_Note &Note) { + StringRef Name = Note.getName(); + ArrayRef<Elf_Word> Descriptor = Note.getDesc(); + Elf_Word Type = Note.getType(); + + OS << " " << Name << std::string(22 - Name.size(), ' ') + << format_hex(Descriptor.size(), 10) << '\t'; + + if (Name == "GNU") { + OS << getGNUNoteTypeName(Type) << '\n'; + printGNUNote<ELFT>(OS, Type, Descriptor, Descriptor.size()); + } else if (Name == "FreeBSD") { + OS << getFreeBSDNoteTypeName(Type) << '\n'; + } else if (Name == "AMD") { + OS << getAMDGPUNoteTypeName(Type) << '\n'; + printAMDGPUNote<ELFT>(OS, Type, Descriptor, Descriptor.size()); + } else { + OS << "Unknown note type: (" << format_hex(Type, 10) << ')'; } + OS << '\n'; }; if (IsCore) { - for (const auto &P : unwrapOrError(Obj->program_headers())) - if (P.p_type == PT_NOTE) - process(P.p_offset, P.p_filesz); + for (const auto &P : unwrapOrError(Obj->program_headers())) { + if (P.p_type != PT_NOTE) + continue; + PrintHeader(P.p_offset, P.p_filesz); + Error Err = Error::success(); + for (const auto &Note : Obj->notes(P, Err)) + ProcessNote(Note); + if (Err) + error(std::move(Err)); + } } else { - for (const auto &S : unwrapOrError(Obj->sections())) - if (S.sh_type == SHT_NOTE) - process(S.sh_offset, S.sh_size); + for (const auto &S : unwrapOrError(Obj->sections())) { + if (S.sh_type != SHT_NOTE) + continue; + PrintHeader(S.sh_offset, S.sh_size); + Error Err = Error::success(); + for (const auto &Note : Obj->notes(S, Err)) + ProcessNote(Note); + if (Err) + error(std::move(Err)); + } } } template <class ELFT> +void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) { + OS << "printELFLinkerOptions not implemented!\n"; +} + +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) { @@ -3715,7 +3978,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) { 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)); + unsigned(ELF::EF_AMDGPU_MACH)); else if (e->e_machine == EM_RISCV) W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderRISCVFlags)); else @@ -3724,8 +3987,8 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) { W.printNumber("ProgramHeaderEntrySize", e->e_phentsize); W.printNumber("ProgramHeaderCount", e->e_phnum); W.printNumber("SectionHeaderEntrySize", e->e_shentsize); - W.printNumber("SectionHeaderCount", e->e_shnum); - W.printNumber("StringTableSectionIndex", e->e_shstrndx); + W.printString("SectionHeaderCount", getSectionHeadersNumString(Obj)); + W.printString("StringTableSectionIndex", getSectionHeaderTableIndexString(Obj)); } } @@ -3738,6 +4001,8 @@ void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) { DictScope D(W, "Group"); W.printNumber("Name", G.Name, G.ShName); W.printNumber("Index", G.Index); + W.printNumber("Link", G.Link); + W.printNumber("Info", G.Info); W.printHex("Type", getGroupType(G.Type), G.Type); W.startLine() << "Signature: " << G.Signature << "\n"; @@ -3768,9 +4033,12 @@ 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_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL && - Sec.sh_type != ELF::SHT_ANDROID_RELA) + Sec.sh_type != ELF::SHT_ANDROID_RELA && + Sec.sh_type != ELF::SHT_ANDROID_RELR) continue; StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); @@ -3803,6 +4071,19 @@ 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_RELR: + case ELF::SHT_ANDROID_RELR: { + Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec)); + if (opts::RawRelr) { + for (const Elf_Relr &R : Relrs) + W.startLine() << W.hex(R) << "\n"; + } else { + std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &R : RelrRelas) + 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))) @@ -3983,6 +4264,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); + const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); if (DynRelRegion.Size && DynRelaRegion.Size) report_fatal_error("There are both REL and RELA dynamic relocations"); @@ -3999,6 +4281,12 @@ void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { Rela.r_addend = 0; printDynamicRelocation(Obj, Rela); } + if (DynRelrRegion.Size > 0) { + Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); + std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &Rela : RelrRelas) + printDynamicRelocation(Obj, Rela); + } if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>()) printDynamicRelocation(Obj, Rela); @@ -4062,11 +4350,71 @@ void LLVMStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { } template <class ELFT> +void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) { + ListScope L(W, "CGProfile"); + if (!this->dumper()->getDotCGProfileSec()) + return; + auto CGProfile = + unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>( + this->dumper()->getDotCGProfileSec())); + for (const Elf_CGProfile &CGPE : CGProfile) { + DictScope D(W, "CGProfileEntry"); + W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from), + CGPE.cgp_from); + W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to), + CGPE.cgp_to); + W.printNumber("Weight", CGPE.cgp_weight); + } +} + +template <class ELFT> +void LLVMStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) { + ListScope L(W, "Addrsig"); + if (!this->dumper()->getDotAddrsigSec()) + return; + ArrayRef<uint8_t> Contents = unwrapOrError( + Obj->getSectionContents(this->dumper()->getDotAddrsigSec())); + const uint8_t *Cur = Contents.begin(); + const uint8_t *End = Contents.end(); + while (Cur != End) { + unsigned Size; + const char *Err; + uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err); + if (Err) + reportError(Err); + W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex), + SymIndex); + Cur += Size; + } +} + +template <class ELFT> void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { W.startLine() << "printNotes not implemented!\n"; } template <class ELFT> +void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) { + ListScope L(W, "LinkerOptions"); + + for (const Elf_Shdr &Shdr : unwrapOrError(Obj->sections())) { + if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS) + continue; + + ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Shdr)); + for (const uint8_t *P = Contents.begin(), *E = Contents.end(); P < E; ) { + StringRef Key = StringRef(reinterpret_cast<const char *>(P)); + StringRef Value = + StringRef(reinterpret_cast<const char *>(P) + Key.size() + 1); + + W.printString(Key, Value); + + P = P + Key.size() + Value.size() + 2; + } + } +} + +template <class ELFT> void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { auto PrintEntry = [&](const Elf_Addr *E) { W.printHex("Address", Parser.getGotAddress(E)); |
