mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-02 08:26:29 +00:00
[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:
parent
2920c56bce
commit
a3aa1d15da
@ -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.
|
||||
|
||||
|
BIN
test/tools/llvm-readobj/Inputs/abiflags.obj.elf-mips
Normal file
BIN
test/tools/llvm-readobj/Inputs/abiflags.obj.elf-mips
Normal file
Binary file not shown.
BIN
test/tools/llvm-readobj/Inputs/abiflags.obj.elf-mipsel
Normal file
BIN
test/tools/llvm-readobj/Inputs/abiflags.obj.elf-mipsel
Normal file
Binary file not shown.
42
test/tools/llvm-readobj/mips-abiflags.test
Normal file
42
test/tools/llvm-readobj/mips-abiflags.test
Normal 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: }
|
@ -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);
|
||||
}
|
||||
|
@ -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() { }
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user