From bd58bdb7a61afeadd7c71d4b5351695a43d17d44 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Thu, 7 May 2015 15:40:48 +0000 Subject: [PATCH] [obj2yaml/yaml2obj] Add SHT_MIPS_ABIFLAGS section support This change adds support for the SHT_MIPS_ABIFLAGS section reading/writing to the obj2yaml and yaml2obj tools. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236738 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELFYAML.h | 59 +++++++++++++++- lib/Object/ELFYAML.cpp | 119 ++++++++++++++++++++++++++++++++ test/Object/Mips/abi-flags.yaml | 63 +++++++++++++++++ test/Object/obj2yaml.test | 7 +- tools/obj2yaml/elf2yaml.cpp | 37 ++++++++++ tools/yaml2obj/yaml2elf.cpp | 37 ++++++++++ 6 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 test/Object/Mips/abi-flags.yaml diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index 45cbdbd2da3..b45507920a9 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -48,6 +48,13 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA) + // For now, hardcode 64 bits everywhere that 32 or 64 would be needed // since 64-bit can hold 32-bit values too. struct FileHeader { @@ -78,7 +85,7 @@ struct SectionOrType { }; struct Section { - enum class SectionKind { Group, RawContent, Relocation }; + enum class SectionKind { Group, RawContent, Relocation, MipsABIFlags }; SectionKind Kind; StringRef Name; ELF_SHT Type; @@ -122,6 +129,26 @@ struct RelocationSection : Section { return S->Kind == SectionKind::Relocation; } }; + +// Represents .MIPS.abiflags section +struct MipsABIFlags : Section { + llvm::yaml::Hex16 Version; + MIPS_ISA ISALevel; + llvm::yaml::Hex8 ISARevision; + MIPS_AFL_REG GPRSize; + MIPS_AFL_REG CPR1Size; + MIPS_AFL_REG CPR2Size; + MIPS_ABI_FP FpABI; + MIPS_AFL_EXT ISAExtension; + MIPS_AFL_ASE ASEs; + MIPS_AFL_FLAGS1 Flags1; + llvm::yaml::Hex32 Flags2; + MipsABIFlags() : Section(SectionKind::MipsABIFlags) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::MipsABIFlags; + } +}; + struct Object { FileHeader Header; std::vector> Sections; @@ -208,6 +235,36 @@ struct ScalarEnumerationTraits { static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); }; +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::MIPS_AFL_REG &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::MIPS_ABI_FP &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::MIPS_AFL_EXT &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::MIPS_ISA &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, ELFYAML::MIPS_AFL_ASE &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value); +}; + template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); diff --git a/lib/Object/ELFYAML.cpp b/lib/Object/ELFYAML.cpp index d63571e6646..69a9f12e303 100644 --- a/lib/Object/ELFYAML.cpp +++ b/lib/Object/ELFYAML.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/ELFYAML.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/MipsABIFlags.h" namespace llvm { @@ -461,6 +462,93 @@ void ScalarEnumerationTraits::enumeration( #undef ELF_RELOC } +void ScalarEnumerationTraits::enumeration( + IO &IO, ELFYAML::MIPS_AFL_REG &Value) { +#define ECase(X) IO.enumCase(Value, #X, Mips::AFL_##X); + ECase(REG_NONE) + ECase(REG_32) + ECase(REG_64) + ECase(REG_128) +#undef ECase +} + +void ScalarEnumerationTraits::enumeration( + IO &IO, ELFYAML::MIPS_ABI_FP &Value) { +#define ECase(X) IO.enumCase(Value, #X, Mips::Val_GNU_MIPS_ABI_##X); + ECase(FP_ANY) + ECase(FP_DOUBLE) + ECase(FP_SINGLE) + ECase(FP_SOFT) + ECase(FP_OLD_64) + ECase(FP_XX) + ECase(FP_64) + ECase(FP_64A) +#undef ECase +} + +void ScalarEnumerationTraits::enumeration( + IO &IO, ELFYAML::MIPS_AFL_EXT &Value) { +#define ECase(X) IO.enumCase(Value, #X, Mips::AFL_##X); + ECase(EXT_NONE) + ECase(EXT_XLR) + ECase(EXT_OCTEON2) + ECase(EXT_OCTEONP) + ECase(EXT_LOONGSON_3A) + ECase(EXT_OCTEON) + ECase(EXT_5900) + ECase(EXT_4650) + ECase(EXT_4010) + ECase(EXT_4100) + ECase(EXT_3900) + ECase(EXT_10000) + ECase(EXT_SB1) + ECase(EXT_4111) + ECase(EXT_4120) + ECase(EXT_5400) + ECase(EXT_5500) + ECase(EXT_LOONGSON_2E) + ECase(EXT_LOONGSON_2F) + ECase(EXT_OCTEON3) +#undef ECase +} + +void ScalarEnumerationTraits::enumeration( + IO &IO, ELFYAML::MIPS_ISA &Value) { + IO.enumCase(Value, "MIPS1", 1); + IO.enumCase(Value, "MIPS2", 2); + IO.enumCase(Value, "MIPS3", 3); + IO.enumCase(Value, "MIPS4", 4); + IO.enumCase(Value, "MIPS5", 5); + IO.enumCase(Value, "MIPS32", 32); + IO.enumCase(Value, "MIPS64", 64); +} + +void ScalarBitSetTraits::bitset( + IO &IO, ELFYAML::MIPS_AFL_ASE &Value) { +#define BCase(X) IO.bitSetCase(Value, #X, Mips::AFL_ASE_##X); + BCase(DSP) + BCase(DSPR2) + BCase(EVA) + BCase(MCU) + BCase(MDMX) + BCase(MIPS3D) + BCase(MT) + BCase(SMARTMIPS) + BCase(VIRT) + BCase(MSA) + BCase(MIPS16) + BCase(MICROMIPS) + BCase(XPA) +#undef BCase +} + +void ScalarBitSetTraits::bitset( + IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value) { +#define BCase(X) IO.bitSetCase(Value, #X, Mips::AFL_FLAGS1_##X); + BCase(ODDSPREG) +#undef BCase +} + void MappingTraits::mapping(IO &IO, ELFYAML::FileHeader &FileHdr) { IO.mapRequired("Class", FileHdr.Class); @@ -536,6 +624,26 @@ void MappingTraits::mapping( IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); } +static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Version", Section.Version, Hex16(0)); + IO.mapRequired("ISA", Section.ISALevel); + IO.mapOptional("ISARevision", Section.ISARevision, Hex8(0)); + IO.mapOptional("ISAExtension", Section.ISAExtension, + ELFYAML::MIPS_AFL_EXT(Mips::AFL_EXT_NONE)); + IO.mapOptional("ASEs", Section.ASEs, ELFYAML::MIPS_AFL_ASE(0)); + IO.mapOptional("FpABI", Section.FpABI, + ELFYAML::MIPS_ABI_FP(Mips::Val_GNU_MIPS_ABI_FP_ANY)); + IO.mapOptional("GPRSize", Section.GPRSize, + ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); + IO.mapOptional("CPR1Size", Section.CPR1Size, + ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); + IO.mapOptional("CPR2Size", Section.CPR2Size, + ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); + IO.mapOptional("Flags1", Section.Flags1, ELFYAML::MIPS_AFL_FLAGS1(0)); + IO.mapOptional("Flags2", Section.Flags2, Hex32(0)); +} + void MappingTraits>::mapping( IO &IO, std::unique_ptr &Section) { ELFYAML::ELF_SHT sectionType; @@ -556,6 +664,11 @@ void MappingTraits>::mapping( Section.reset(new ELFYAML::Group()); groupSectionMapping(IO, *cast(Section.get())); break; + case ELF::SHT_MIPS_ABIFLAGS: + if (!IO.outputting()) + Section.reset(new ELFYAML::MipsABIFlags()); + sectionMapping(IO, *cast(Section.get())); + break; default: if (!IO.outputting()) Section.reset(new ELFYAML::RawContentSection()); @@ -625,5 +738,11 @@ void MappingTraits::mapping(IO &IO, ELFYAML::Object &Object) { IO.setContext(nullptr); } +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1) + } // end namespace yaml } // end namespace llvm diff --git a/test/Object/Mips/abi-flags.yaml b/test/Object/Mips/abi-flags.yaml new file mode 100644 index 00000000000..8a11fc4124c --- /dev/null +++ b/test/Object/Mips/abi-flags.yaml @@ -0,0 +1,63 @@ +# RUN: yaml2obj -format=elf %s > %t +# RUN: llvm-readobj -mips-abi-flags %t | FileCheck -check-prefix=OBJ %s +# RUN: obj2yaml %t | FileCheck -check-prefix=YAML %s + +# OBJ: MIPS ABI Flags { +# OBJ-NEXT: Version: 0 +# OBJ-NEXT: ISA: MIPS64r5 +# OBJ-NEXT: ISA Extension: Cavium Networks Octeon3 (0x13) +# OBJ-NEXT: ASEs [ (0x103) +# OBJ-NEXT: DSP (0x1) +# OBJ-NEXT: DSPR2 (0x2) +# OBJ-NEXT: VZ (0x100) +# OBJ-NEXT: ] +# OBJ-NEXT: FP ABI: Hard float (double precision) (0x1) +# OBJ-NEXT: GPR size: 64 +# OBJ-NEXT: CPR1 size: 64 +# OBJ-NEXT: CPR2 size: 0 +# OBJ-NEXT: Flags 1 [ (0x1) +# OBJ-NEXT: ODDSPREG (0x1) +# OBJ-NEXT: ] +# OBJ-NEXT: Flags 2: 0x0 +# OBJ-NEXT: } + +# YAML: Sections: +# YAML-NEXT: - Name: .MIPS.abiflags +# YAML-NEXT: Type: SHT_MIPS_ABIFLAGS +# YAML-NEXT: AddressAlign: 0x0000000000000008 +# YAML-NEXT: ISA: MIPS64 +# YAML-NEXT: ISARevision: 0x05 +# YAML-NEXT: ISAExtension: EXT_OCTEON3 +# YAML-NEXT: ASEs: [ DSP, DSPR2, VIRT ] +# YAML-NEXT: FpABI: FP_DOUBLE +# YAML-NEXT: GPRSize: REG_64 +# YAML-NEXT: CPR1Size: REG_64 +# YAML-NEXT: Flags1: [ ODDSPREG ] + +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2MSB + Type: ET_REL + Machine: EM_MIPS + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + Version: 0 + ISA: MIPS64 + ISARevision: 5 + ISAExtension: EXT_OCTEON3 + ASEs: [ DSP, DSPR2, VIRT ] + FpABI: FP_DOUBLE + GPRSize: REG_64 + CPR1Size: REG_64 + CPR2Size: REG_NONE + Flags1: [ ODDSPREG ] + Flags2: 0x0 + +Symbols: + Local: + - Name: .MIPS.abiflags + Type: STT_SECTION + Section: .MIPS.abiflags diff --git a/test/Object/obj2yaml.test b/test/Object/obj2yaml.test index e654dcdccf5..2a3f7c841dd 100644 --- a/test/Object/obj2yaml.test +++ b/test/Object/obj2yaml.test @@ -253,7 +253,12 @@ ELF-MIPSEL-NEXT: - Name: .MIPS.abiflags ELF-MIPSEL-NEXT: Type: SHT_MIPS_ABIFLAGS ELF-MIPSEL-NEXT: Flags: [ SHF_ALLOC ] ELF-MIPSEL-NEXT: AddressAlign: 0x0000000000000008 -ELF-MIPSEL-NEXT: Content: '000020010101000100000000000000000100000000000000' +ELF-MIPSEL-NEXT: ISA: MIPS32 +ELF-MIPSEL-NEXT: ISARevision: 0x01 +ELF-MIPSEL-NEXT: FpABI: FP_DOUBLE +ELF-MIPSEL-NEXT: GPRSize: REG_32 +ELF-MIPSEL-NEXT: CPR1Size: REG_32 +ELF-MIPSEL-NEXT: Flags1: [ ODDSPREG ] ELF-MIPSEL-NEXT: Symbols: ELF-MIPSEL-NEXT: Local: ELF-MIPSEL-NEXT: - Name: trivial.ll diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp index e606df2a084..8ce70bc3652 100644 --- a/tools/obj2yaml/elf2yaml.cpp +++ b/tools/obj2yaml/elf2yaml.cpp @@ -41,6 +41,7 @@ class ELFDumper { ErrorOr dumpContentSection(const Elf_Shdr *Shdr); ErrorOr dumpGroup(const Elf_Shdr *Shdr); + ErrorOr dumpMipsABIFlags(const Elf_Shdr *Shdr); public: ELFDumper(const object::ELFFile &O); @@ -96,6 +97,13 @@ ErrorOr ELFDumper::dump() { Y->Sections.push_back(std::unique_ptr(G.get())); break; } + case ELF::SHT_MIPS_ABIFLAGS: { + ErrorOr G = dumpMipsABIFlags(&Sec); + if (std::error_code EC = G.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr(G.get())); + break; + } default: { ErrorOr S = dumpContentSection(&Sec); if (std::error_code EC = S.getError()) @@ -318,6 +326,35 @@ ErrorOr ELFDumper::dumpGroup(const Elf_Shdr *Shdr) { return S.release(); } +template +ErrorOr +ELFDumper::dumpMipsABIFlags(const Elf_Shdr *Shdr) { + assert(Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS && + "Section type is not SHT_MIPS_ABIFLAGS"); + auto S = make_unique(); + if (std::error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + + ErrorOr> ContentOrErr = Obj.getSectionContents(Shdr); + if (std::error_code EC = ContentOrErr.getError()) + return EC; + + auto *Flags = reinterpret_cast *>( + ContentOrErr.get().data()); + S->Version = Flags->version; + S->ISALevel = Flags->isa_level; + S->ISARevision = Flags->isa_rev; + S->GPRSize = Flags->gpr_size; + S->CPR1Size = Flags->cpr1_size; + S->CPR2Size = Flags->cpr2_size; + S->FpABI = Flags->fp_abi; + S->ISAExtension = Flags->isa_ext; + S->ASEs = Flags->ases; + S->Flags1 = Flags->flags1; + S->Flags2 = Flags->flags2; + return S.release(); +} + template static std::error_code elf2yaml(raw_ostream &Out, const object::ELFFile &Obj) { diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index 17dbe8b03da..1226506f624 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -133,6 +133,9 @@ class ELFState { ContiguousBlobAccumulator &CBA); bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group, ContiguousBlobAccumulator &CBA); + bool writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::MipsABIFlags &Section, + ContiguousBlobAccumulator &CBA); // - SHT_NULL entry (placed first, i.e. 0'th entry) // - symbol table (.symtab) (placed third to last) @@ -235,6 +238,9 @@ bool ELFState::initSectionHeaders(std::vector &SHeaders, SHeader.sh_info = SymIdx; if (!writeSectionContent(SHeader, *S, CBA)) return false; + } else if (auto S = dyn_cast(Sec.get())) { + if (!writeSectionContent(SHeader, *S, CBA)) + return false; } else llvm_unreachable("Unknown section type"); @@ -413,6 +419,37 @@ bool ELFState::writeSectionContent(Elf_Shdr &SHeader, return true; } +template +bool ELFState::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::MipsABIFlags &Section, + ContiguousBlobAccumulator &CBA) { + if (Section.Type != llvm::ELF::SHT_MIPS_ABIFLAGS) { + errs() << "error: Invalid section type.\n"; + return false; + } + + object::Elf_Mips_ABIFlags Flags; + zero(Flags); + SHeader.sh_entsize = sizeof(Flags); + SHeader.sh_size = SHeader.sh_entsize; + + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset); + Flags.version = Section.Version; + Flags.isa_level = Section.ISALevel; + Flags.isa_rev = Section.ISARevision; + Flags.gpr_size = Section.GPRSize; + Flags.cpr1_size = Section.CPR1Size; + Flags.cpr2_size = Section.CPR2Size; + Flags.fp_abi = Section.FpABI; + Flags.isa_ext = Section.ISAExtension; + Flags.ases = Section.ASEs; + Flags.flags1 = Section.Flags1; + Flags.flags2 = Section.Flags2; + OS.write((const char *)&Flags, sizeof(Flags)); + + return true; +} + template bool ELFState::buildSectionIndex() { SN2I.addName(".symtab", getDotSymTabSecNo()); SN2I.addName(".strtab", getDotStrTabSecNo()); -- 2.34.1