[llvm-readobj] Print .MIPS.abiflags section content

This change adds new flag -mips-abi-flags to the llvm-readobj. This flag
forces printing of .MIPS.abiflags section content.

https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.2.1._.MIPS.abiflags

llvm-svn: 236737
This commit is contained in:
Simon Atanasyan 2015-05-07 15:40:35 +00:00
parent 2920c56bce
commit a3aa1d15da
7 changed files with 188 additions and 1 deletions

View File

@ -489,6 +489,22 @@ struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > {
Elf_Xword p_align; // Segment alignment constraint
};
// .MIPS.abiflags section content
template <class ELFT> struct Elf_Mips_ABIFlags {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Half version; // Version of the structure
uint8_t isa_level; // ISA level: 1-5, 32, and 64
uint8_t isa_rev; // ISA revision (0 for MIPS I - MIPS V)
uint8_t gpr_size; // General purpose registers size
uint8_t cpr1_size; // Co-processor 1 registers size
uint8_t cpr2_size; // Co-processor 2 registers size
uint8_t fp_abi; // Floating-point ABI flag
Elf_Word isa_ext; // Processor-specific extension
Elf_Word ases; // ASEs flags
Elf_Word flags1; // General flags
Elf_Word flags2; // General flags
};
} // end namespace object.
} // end namespace llvm.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,42 @@
RUN: llvm-readobj -mips-abi-flags %p/Inputs/abiflags.obj.elf-mipsel | \
RUN: FileCheck -check-prefix=EL64 %s
RUN: llvm-readobj -mips-abi-flags %p/Inputs/abiflags.obj.elf-mips | \
RUN: FileCheck -check-prefix=BE32 %s
EL64: MIPS ABI Flags {
EL64-NEXT: Version: 0
EL64-NEXT: ISA: MIPS64r5
EL64-NEXT: ISA Extension: Cavium Networks Octeon3 (0x13)
EL64-NEXT: ASEs [ (0x103)
EL64-NEXT: DSP (0x1)
EL64-NEXT: DSPR2 (0x2)
EL64-NEXT: VZ (0x100)
EL64-NEXT: ]
EL64-NEXT: FP ABI: Hard float (double precision) (0x1)
EL64-NEXT: GPR size: 64
EL64-NEXT: CPR1 size: 64
EL64-NEXT: CPR2 size: 0
EL64-NEXT: Flags 1 [ (0x1)
EL64-NEXT: ODDSPREG (0x1)
EL64-NEXT: ]
EL64-NEXT: Flags 2: 0x0
EL64-NEXT: }
BE32: MIPS ABI Flags {
BE32-NEXT: Version: 0
BE32-NEXT: ISA: MIPS32r2
BE32-NEXT: ISA Extension: None (0x0)
BE32-NEXT: ASEs [ (0x803)
BE32-NEXT: DSP (0x1)
BE32-NEXT: DSPR2 (0x2)
BE32-NEXT: microMIPS (0x800)
BE32-NEXT: ]
BE32-NEXT: FP ABI: Soft float (0x3)
BE32-NEXT: GPR size: 32
BE32-NEXT: CPR1 size: 0
BE32-NEXT: CPR2 size: 0
BE32-NEXT: Flags 1 [ (0x1)
BE32-NEXT: ODDSPREG (0x1)
BE32-NEXT: ]
BE32-NEXT: Flags 2: 0x0
BE32-NEXT: }

View File

@ -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;
@ -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 },
@ -1249,3 +1261,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);
}

View File

@ -42,6 +42,7 @@ public:
// Only implemented for MIPS ELF at this time.
virtual void printMipsPLTGOT() { }
virtual void printMipsABIFlags() { }
// Only implemented for PE/COFF.
virtual void printCOFFImports() { }

View File

@ -148,6 +148,10 @@ namespace opts {
MipsPLTGOT("mips-plt-got",
cl::desc("Display the MIPS GOT and PLT GOT sections"));
// -mips-abi-flags
cl::opt<bool> MipsABIFlags("mips-abi-flags",
cl::desc("Display the MIPS.abiflags section"));
// -coff-imports
cl::opt<bool>
COFFImports("coff-imports", cl::desc("Display the PE/COFF import table"));
@ -287,9 +291,12 @@ static void dumpObject(const ObjectFile *Obj) {
if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
if (opts::ARMAttributes)
Dumper->printAttributes();
if (isMipsArch(Obj->getArch()) && Obj->isELF())
if (isMipsArch(Obj->getArch()) && Obj->isELF()) {
if (opts::MipsPLTGOT)
Dumper->printMipsPLTGOT();
if (opts::MipsABIFlags)
Dumper->printMipsABIFlags();
}
if (opts::COFFImports)
Dumper->printCOFFImports();
if (opts::COFFExports)