diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-readobj/ELFDumper.cpp')
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/ELFDumper.cpp | 234 |
1 files changed, 209 insertions, 25 deletions
diff --git a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp index d68c786..0931cb7 100644 --- a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/MipsABIFlags.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -56,6 +57,7 @@ public: void printAttributes() override; void printMipsPLTGOT() override; + void printMipsABIFlags() override; private: typedef ELFFile<ELFT> ELFO; @@ -139,19 +141,19 @@ static void getSectionNameIndex(const ELFO &Obj, typename ELFO::Elf_Sym_Iter Symbol, StringRef &SectionName, unsigned &SectionIndex) { SectionIndex = Symbol->st_shndx; - if (SectionIndex == SHN_UNDEF) { + if (Symbol->isUndefined()) SectionName = "Undefined"; - } else if (SectionIndex >= SHN_LOPROC && SectionIndex <= SHN_HIPROC) { + else if (Symbol->isProcessorSpecific()) SectionName = "Processor Specific"; - } else if (SectionIndex >= SHN_LOOS && SectionIndex <= SHN_HIOS) { + else if (Symbol->isOSSpecific()) SectionName = "Operating System Specific"; - } else if (SectionIndex > SHN_HIOS && SectionIndex < SHN_ABS) { + else if (Symbol->isReserved()) SectionName = "Reserved"; - } else if (SectionIndex == SHN_ABS) { + else if (Symbol->isAbsolute()) SectionName = "Absolute"; - } else if (SectionIndex == SHN_COMMON) { + else if (Symbol->isCommon()) SectionName = "Common"; - } else { + else { if (SectionIndex == SHN_XINDEX) SectionIndex = Obj.getSymbolTableIndex(&*Symbol); assert(SectionIndex != SHN_XINDEX && @@ -170,6 +172,16 @@ findSectionByAddress(const ELFFile<ELFT> *Obj, uint64_t Addr) { return nullptr; } +template <class ELFT> +static const typename ELFFile<ELFT>::Elf_Shdr * +findSectionByName(const ELFFile<ELFT> &Obj, StringRef Name) { + for (const auto &Shdr : Obj.sections()) { + if (Name == errorOrDefault(Obj.getSectionName(&Shdr))) + return &Shdr; + } + return nullptr; +} + static const EnumEntry<unsigned> ElfClass[] = { { "None", ELF::ELFCLASSNONE }, { "32-bit", ELF::ELFCLASS32 }, @@ -207,6 +219,7 @@ static const EnumEntry<unsigned> ElfOSABI[] = { { "NSK", ELF::ELFOSABI_NSK }, { "AROS", ELF::ELFOSABI_AROS }, { "FenixOS", ELF::ELFOSABI_FENIXOS }, + { "CloudABI", ELF::ELFOSABI_CLOUDABI }, { "C6000_ELFABI", ELF::ELFOSABI_C6000_ELFABI }, { "C6000_LINUX" , ELF::ELFOSABI_C6000_LINUX }, { "ARM", ELF::ELFOSABI_ARM }, @@ -372,9 +385,10 @@ static const EnumEntry<unsigned> ElfMachineType[] = { }; static const EnumEntry<unsigned> ElfSymbolBindings[] = { - { "Local", ELF::STB_LOCAL }, - { "Global", ELF::STB_GLOBAL }, - { "Weak", ELF::STB_WEAK } + { "Local", ELF::STB_LOCAL }, + { "Global", ELF::STB_GLOBAL }, + { "Weak", ELF::STB_WEAK }, + { "Unique", ELF::STB_GNU_UNIQUE } }; static const EnumEntry<unsigned> ElfSymbolTypes[] = { @@ -469,6 +483,7 @@ static const char *getElfSegmentType(unsigned Arch, unsigned Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO); LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC); LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS); + LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS); } } @@ -503,10 +518,33 @@ static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_FP64), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O64), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_EABI32), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_EABI64), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_3900), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4010), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4100), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4650), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4120), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4111), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_SB1), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_XLR), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON3), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5400), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5900), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5500), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_9000), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS2E), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS2F), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS3A), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_MDMX), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2), LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3), @@ -549,7 +587,8 @@ void ELFDumper<ELFT>::printFileHeaders() { W.printHex ("SectionHeaderOffset", Header->e_shoff); if (Header->e_machine == EM_MIPS) W.printFlags("Flags", Header->e_flags, makeArrayRef(ElfHeaderMipsFlags), - unsigned(ELF::EF_MIPS_ARCH)); + unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), + unsigned(ELF::EF_MIPS_MACH)); else W.printFlags("Flags", Header->e_flags); W.printNumber("HeaderSize", Header->e_ehsize); @@ -666,26 +705,30 @@ void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel) { SmallString<32> RelocName; Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); - StringRef SymbolName; + StringRef TargetName; std::pair<const Elf_Shdr *, const Elf_Sym *> Sym = Obj->getRelocationSymbol(Sec, &Rel); - if (Sym.first) - SymbolName = errorOrDefault(Obj->getSymbolName(Sym.first, Sym.second)); + if (Sym.second && Sym.second->getType() == ELF::STT_SECTION) { + const Elf_Shdr *Sec = Obj->getSection(Sym.second); + ErrorOr<StringRef> SecName = Obj->getSectionName(Sec); + if (SecName) + TargetName = SecName.get(); + } else if (Sym.first) { + TargetName = errorOrDefault(Obj->getSymbolName(Sym.first, Sym.second)); + } if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset); W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printNumber("Symbol", SymbolName.size() > 0 ? SymbolName : "-", + W.printNumber("Symbol", TargetName.size() > 0 ? TargetName : "-", Rel.getSymbol(Obj->isMips64EL())); W.printHex("Addend", Rel.r_addend); } else { raw_ostream& OS = W.startLine(); - OS << W.hex(Rel.r_offset) - << " " << RelocName - << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Rel.r_addend) - << "\n"; + OS << W.hex(Rel.r_offset) << " " << RelocName << " " + << (TargetName.size() > 0 ? TargetName : "-") << " " + << W.hex(Rel.r_addend) << "\n"; } } @@ -739,6 +782,7 @@ static const char *getTypeString(uint64_t Type) { 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); @@ -780,6 +824,7 @@ static const char *getTypeString(uint64_t Type) { 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); default: return "unknown"; } } @@ -797,6 +842,34 @@ static const EnumEntry<unsigned> ElfDynamicDTFlags[] = { LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) }; +static const EnumEntry<unsigned> ElfDynamicDTFlags1[] = { + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT), + LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON) +}; + static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), @@ -871,6 +944,7 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value, case DT_MIPS_GOTSYM: case DT_MIPS_RLD_MAP: case DT_MIPS_PLTGOT: + case DT_MIPS_OPTIONS: OS << format("0x%" PRIX64, Value); break; case DT_RELCOUNT: @@ -909,6 +983,9 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value, case DT_FLAGS: printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS); break; + case DT_FLAGS_1: + printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS); + break; } } @@ -918,11 +995,10 @@ void ELFDumper<ELFT>::printUnwindInfo() { } namespace { -template <> -void ELFDumper<ELFType<support::little, 2, false> >::printUnwindInfo() { +template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() { const unsigned Machine = Obj->getHeader()->e_machine; if (Machine == EM_ARM) { - ARM::EHABI::PrinterContext<ELFType<support::little, 2, false> > Ctx(W, Obj); + ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx(W, Obj); return Ctx.PrintUnwindInformation(); } W.startLine() << "UnwindInfo not implemented.\n"; @@ -1002,8 +1078,7 @@ void ELFDumper<ELFT>::printAttributes() { } namespace { -template <> -void ELFDumper<ELFType<support::little, 2, false> >::printAttributes() { +template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() { if (Obj->getHeader()->e_machine != EM_ARM) { W.startLine() << "Attributes not implemented.\n"; return; @@ -1240,3 +1315,112 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { MipsGOTParser<ELFT>(Obj, W).parseGOT(*GotShdr); } + +static const EnumEntry<unsigned> ElfMipsISAExtType[] = { + {"None", Mips::AFL_EXT_NONE}, + {"Broadcom SB-1", Mips::AFL_EXT_SB1}, + {"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON}, + {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2}, + {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP}, + {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3}, + {"LSI R4010", Mips::AFL_EXT_4010}, + {"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E}, + {"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F}, + {"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A}, + {"MIPS R4650", Mips::AFL_EXT_4650}, + {"MIPS R5900", Mips::AFL_EXT_5900}, + {"MIPS R10000", Mips::AFL_EXT_10000}, + {"NEC VR4100", Mips::AFL_EXT_4100}, + {"NEC VR4111/VR4181", Mips::AFL_EXT_4111}, + {"NEC VR4120", Mips::AFL_EXT_4120}, + {"NEC VR5400", Mips::AFL_EXT_5400}, + {"NEC VR5500", Mips::AFL_EXT_5500}, + {"RMI Xlr", Mips::AFL_EXT_XLR}, + {"Toshiba R3900", Mips::AFL_EXT_3900} +}; + +static const EnumEntry<unsigned> ElfMipsASEFlags[] = { + {"DSP", Mips::AFL_ASE_DSP}, + {"DSPR2", Mips::AFL_ASE_DSPR2}, + {"Enhanced VA Scheme", Mips::AFL_ASE_EVA}, + {"MCU", Mips::AFL_ASE_MCU}, + {"MDMX", Mips::AFL_ASE_MDMX}, + {"MIPS-3D", Mips::AFL_ASE_MIPS3D}, + {"MT", Mips::AFL_ASE_MT}, + {"SmartMIPS", Mips::AFL_ASE_SMARTMIPS}, + {"VZ", Mips::AFL_ASE_VIRT}, + {"MSA", Mips::AFL_ASE_MSA}, + {"MIPS16", Mips::AFL_ASE_MIPS16}, + {"microMIPS", Mips::AFL_ASE_MICROMIPS}, + {"XPA", Mips::AFL_ASE_XPA} +}; + +static const EnumEntry<unsigned> ElfMipsFpABIType[] = { + {"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY}, + {"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE}, + {"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE}, + {"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT}, + {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)", + Mips::Val_GNU_MIPS_ABI_FP_OLD_64}, + {"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX}, + {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64}, + {"Hard float compat (32-bit CPU, 64-bit FPU)", + Mips::Val_GNU_MIPS_ABI_FP_64A} +}; + +static const EnumEntry<unsigned> ElfMipsFlags1[] { + {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG}, +}; + +static int getMipsRegisterSize(uint8_t Flag) { + switch (Flag) { + case Mips::AFL_REG_NONE: + return 0; + case Mips::AFL_REG_32: + return 32; + case Mips::AFL_REG_64: + return 64; + case Mips::AFL_REG_128: + return 128; + default: + return -1; + } +} + +template <class ELFT> void ELFDumper<ELFT>::printMipsABIFlags() { + const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.abiflags"); + if (!Shdr) { + W.startLine() << "There is no .MIPS.abiflags section in the file.\n"; + return; + } + ErrorOr<ArrayRef<uint8_t>> Sec = Obj->getSectionContents(Shdr); + if (!Sec) { + W.startLine() << "The .MIPS.abiflags section is empty.\n"; + return; + } + if (Sec->size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) { + W.startLine() << "The .MIPS.abiflags section has a wrong size.\n"; + return; + } + + auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec->data()); + + raw_ostream &OS = W.getOStream(); + DictScope GS(W, "MIPS ABI Flags"); + + W.printNumber("Version", Flags->version); + W.startLine() << "ISA: "; + if (Flags->isa_rev <= 1) + OS << format("MIPS%u", Flags->isa_level); + else + OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev); + OS << "\n"; + W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType)); + W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags)); + W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType)); + W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size)); + W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size)); + W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size)); + W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1)); + W.printHex("Flags 2", Flags->flags2); +} |