summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/llvm-readobj/ELFDumper.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
committerpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
commitb773203fb58f3ef282fb69c832d8710cab5bc82d (patch)
treee75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/llvm-readobj/ELFDumper.cpp
parenttweak errno in previous (diff)
downloadwireguard-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.cpp734
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));