diff options
| author | Simon Atanasyan <simon@atanasyan.com> | 2015-01-25 13:29:25 +0000 |
|---|---|---|
| committer | Simon Atanasyan <simon@atanasyan.com> | 2015-01-25 13:29:25 +0000 |
| commit | 5d19c67a68533d716fd791ea5a4cdb6b13a26ab1 (patch) | |
| tree | 44a69f5e7273e2994174c1ae21f78505e8a35e7d | |
| parent | 1a603b3f13e10a378602a1ed164e59b61e2fa485 (diff) | |
| download | llvm-5d19c67a68533d716fd791ea5a4cdb6b13a26ab1.zip llvm-5d19c67a68533d716fd791ea5a4cdb6b13a26ab1.tar.gz llvm-5d19c67a68533d716fd791ea5a4cdb6b13a26ab1.tar.bz2 | |
[ELFYAML] Support mips64 relocation record format in yaml2obj/obj2yaml
MIPS64 ELF file has a very specific relocation record format. Each
record might specify up to three relocation operations. So the `r_info`
field in fact consists of three relocation type sub-fields and optional
code of "special" symbols.
http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
page 40
The patch implements support of the MIPS64 relocation record format in
yaml2obj/obj2yaml tools by introducing new optional Relocation fields:
Type2, Type3, and SpecSym. These fields are recognized only if the
object/YAML file relates to the MIPS64 target.
Differential Revision: http://reviews.llvm.org/D7136
llvm-svn: 227044
| -rw-r--r-- | llvm/include/llvm/Object/ELFTypes.h | 52 | ||||
| -rw-r--r-- | llvm/include/llvm/Object/ELFYAML.h | 6 | ||||
| -rw-r--r-- | llvm/include/llvm/Support/ELF.h | 8 | ||||
| -rw-r--r-- | llvm/lib/Object/ELFYAML.cpp | 49 | ||||
| -rw-r--r-- | llvm/test/Object/Mips/elf-mips64-rel.yaml | 113 | ||||
| -rw-r--r-- | llvm/tools/yaml2obj/yaml2elf.cpp | 10 |
6 files changed, 219 insertions, 19 deletions
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h index 4bc0c7c..9a97f7b3 100644 --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -302,7 +302,10 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { assert(!isMips64EL); return r_info; } - void setRInfo(uint32_t R) { r_info = R; } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } }; template <endianness TargetEndianness, std::size_t MaxAlign> @@ -321,9 +324,12 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; } }; @@ -338,7 +344,10 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { assert(!isMips64EL); return r_info; } - void setRInfo(uint32_t R) { r_info = R; } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } }; template <endianness TargetEndianness, std::size_t MaxAlign> @@ -358,9 +367,12 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> { return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; } }; @@ -380,10 +392,14 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>, uint32_t getType(bool isMips64EL) const { return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, uint32_t t) { - this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL)); + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(uint32_t t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) { + this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL); } }; @@ -401,10 +417,14 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>, unsigned char getType(bool isMips64EL) const { return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, unsigned char t) { - this->setRInfo((s << 8) + t); + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(unsigned char t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { + this->setRInfo((s << 8) + t, IsMips64EL); } }; diff --git a/llvm/include/llvm/Object/ELFYAML.h b/llvm/include/llvm/Object/ELFYAML.h index b71946d..1bfce10 100644 --- a/llvm/include/llvm/Object/ELFYAML.h +++ b/llvm/include/llvm/Object/ELFYAML.h @@ -41,6 +41,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) @@ -186,6 +187,11 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_REL> { }; template <> +struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> { + static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); +}; + +template <> struct MappingTraits<ELFYAML::FileHeader> { static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); }; diff --git a/llvm/include/llvm/Support/ELF.h b/llvm/include/llvm/Support/ELF.h index ef7db394..590df51 100644 --- a/llvm/include/llvm/Support/ELF.h +++ b/llvm/include/llvm/Support/ELF.h @@ -796,6 +796,14 @@ enum { STN_UNDEF = 0 }; +// Special relocation symbols used in the MIPS64 ELF relocation entries +enum { + RSS_UNDEF = 0, // None + RSS_GP = 1, // Value of gp + RSS_GP0 = 2, // Value of gp used to create object being relocated + RSS_LOC = 3 // Address of location being relocated +}; + // Relocation entry, without explicit addend. struct Elf32_Rel { Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) diff --git a/llvm/lib/Object/ELFYAML.cpp b/llvm/lib/Object/ELFYAML.cpp index 14aa831..f44b937 100644 --- a/llvm/lib/Object/ELFYAML.cpp +++ b/llvm/lib/Object/ELFYAML.cpp @@ -415,6 +415,16 @@ void ScalarBitSetTraits<ELFYAML::ELF_STO>::bitset(IO &IO, #undef BCaseMask } +void ScalarEnumerationTraits<ELFYAML::ELF_RSS>::enumeration( + IO &IO, ELFYAML::ELF_RSS &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + ECase(RSS_UNDEF) + ECase(RSS_GP) + ECase(RSS_GP0) + ECase(RSS_LOC) +#undef ECase +} + void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration( IO &IO, ELFYAML::ELF_REL &Value) { const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); @@ -540,11 +550,48 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return "Section size must be greater or equal to the content size"; } +namespace { +struct NormalizedMips64RelType { + NormalizedMips64RelType(IO &) + : Type(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), + Type2(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), + Type3(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), + SpecSym(ELFYAML::ELF_REL(ELF::RSS_UNDEF)) {} + NormalizedMips64RelType(IO &, ELFYAML::ELF_REL Original) + : Type(Original & 0xFF), Type2(Original >> 8 & 0xFF), + Type3(Original >> 16 & 0xFF), SpecSym(Original >> 24 & 0xFF) {} + + ELFYAML::ELF_REL denormalize(IO &) { + ELFYAML::ELF_REL Res = Type | Type2 << 8 | Type3 << 16 | SpecSym << 24; + return Res; + } + + ELFYAML::ELF_REL Type; + ELFYAML::ELF_REL Type2; + ELFYAML::ELF_REL Type3; + ELFYAML::ELF_RSS SpecSym; +}; +} + void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO, ELFYAML::Relocation &Rel) { + const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); + assert(Object && "The IO context is not initialized"); + IO.mapRequired("Offset", Rel.Offset); IO.mapRequired("Symbol", Rel.Symbol); - IO.mapRequired("Type", Rel.Type); + + if (Object->Header.Machine == ELFYAML::ELF_EM(ELF::EM_MIPS) && + Object->Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64)) { + MappingNormalization<NormalizedMips64RelType, ELFYAML::ELF_REL> Key( + IO, Rel.Type); + IO.mapRequired("Type", Key->Type); + IO.mapOptional("Type2", Key->Type2, ELFYAML::ELF_REL(ELF::R_MIPS_NONE)); + IO.mapOptional("Type3", Key->Type3, ELFYAML::ELF_REL(ELF::R_MIPS_NONE)); + IO.mapOptional("SpecSym", Key->SpecSym, ELFYAML::ELF_RSS(ELF::RSS_UNDEF)); + } else + IO.mapRequired("Type", Rel.Type); + IO.mapOptional("Addend", Rel.Addend); } diff --git a/llvm/test/Object/Mips/elf-mips64-rel.yaml b/llvm/test/Object/Mips/elf-mips64-rel.yaml new file mode 100644 index 0000000..1f56540 --- /dev/null +++ b/llvm/test/Object/Mips/elf-mips64-rel.yaml @@ -0,0 +1,113 @@ +# RUN: yaml2obj -format=elf %s > %t +# RUN: llvm-readobj -r %t | FileCheck -check-prefix=OBJ %s +# RUN: obj2yaml %t | FileCheck -check-prefix=YAML %s + +# OBJ: Relocations [ +# OBJ-NEXT: Section (2) .rela.text { +# OBJ-NEXT: 0x14 R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 main 0x4 +# OBJ-NEXT: 0x1C R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 main 0x8 +# OBJ-NEXT: 0x20 R_MIPS_GOT_PAGE/R_MIPS_NONE/R_MIPS_NONE .rodata 0x0 +# OBJ-NEXT: 0x24 R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE .rodata 0x0 +# OBJ-NEXT: 0x28 R_MIPS_CALL16/R_MIPS_NONE/R_MIPS_NONE printf 0x0 +# OBJ-NEXT: 0x30 R_MIPS_GPREL16/R_MIPS_LO16/R_MIPS_NONE printf 0x0 +# OBJ-NEXT: } +# OBJ-NEXT: ] + +# YAML: Relocations: +# YAML-NEXT: - Offset: 0x0000000000000014 +# YAML-NEXT: Symbol: main +# YAML-NEXT: Type: R_MIPS_GPREL16 +# YAML-NEXT: Type2: R_MIPS_SUB +# YAML-NEXT: Type3: R_MIPS_HI16 +# YAML-NEXT: Addend: 4 +# YAML-NEXT: - Offset: 0x000000000000001C +# YAML-NEXT: Symbol: main +# YAML-NEXT: Type: R_MIPS_GPREL16 +# YAML-NEXT: Type2: R_MIPS_SUB +# YAML-NEXT: Type3: R_MIPS_LO16 +# YAML-NEXT: Addend: 8 +# YAML-NEXT: - Offset: 0x0000000000000020 +# YAML-NEXT: Symbol: .rodata +# YAML-NEXT: Type: R_MIPS_GOT_PAGE +# YAML-NEXT: Addend: 0 +# YAML-NEXT: - Offset: 0x0000000000000024 +# YAML-NEXT: Symbol: .rodata +# YAML-NEXT: Type: R_MIPS_GOT_OFST +# YAML-NEXT: Addend: 0 +# YAML-NEXT: - Offset: 0x0000000000000028 +# YAML-NEXT: Symbol: printf +# YAML-NEXT: Type: R_MIPS_CALL16 +# YAML-NEXT: Addend: 0 +# YAML-NEXT: - Offset: 0x0000000000000030 +# YAML-NEXT: Symbol: printf +# YAML-NEXT: Type: R_MIPS_GPREL16 +# YAML-NEXT: Type2: R_MIPS_LO16 +# YAML-NEXT: SpecSym: RSS_GP0 +# YAML-NEXT: Addend: 0 + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, + EF_MIPS_NOREORDER, EF_MIPS_ARCH_64R2 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x10 + Size: 0x60 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Info: .text + Relocations: + - Offset: 0x14 + Symbol: main + Type: R_MIPS_GPREL16 + Type2: R_MIPS_SUB + Type3: R_MIPS_HI16 + Addend: 4 + - Offset: 0x1C + Symbol: main + Type: R_MIPS_GPREL16 + Type2: R_MIPS_SUB + Type3: R_MIPS_LO16 + Addend: 8 + - Offset: 0x20 + Symbol: .rodata + Type: R_MIPS_GOT_PAGE + - Offset: 0x24 + Symbol: .rodata + Type: R_MIPS_GOT_OFST + - Offset: 0x28 + Symbol: printf + Type: R_MIPS_CALL16 + - Offset: 0x30 + Symbol: printf + Type: R_MIPS_GPREL16 + Type2: R_MIPS_LO16 + SpecSym: RSS_GP0 + - Name: .rodata + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 0x10 + Size: 0x0F + +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .rodata + Type: STT_SECTION + Section: .rodata + Global: + - Name: main + Type: STT_FUNC + Section: .text + Size: 0x58 + - Name: printf +... diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index 44c8c12..c8d4b88 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -321,6 +321,12 @@ ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, SHeader.sh_size = Section.Size; } +static bool isMips64EL(const ELFYAML::Object &Doc) { + return Doc.Header.Machine == ELFYAML::ELF_EM(llvm::ELF::EM_MIPS) && + Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) && + Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); +} + template <class ELFT> bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, @@ -351,13 +357,13 @@ ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, zero(REntry); REntry.r_offset = Rel.Offset; REntry.r_addend = Rel.Addend; - REntry.setSymbolAndType(SymIdx, Rel.Type); + REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc)); OS.write((const char *)&REntry, sizeof(REntry)); } else { Elf_Rel REntry; zero(REntry); REntry.r_offset = Rel.Offset; - REntry.setSymbolAndType(SymIdx, Rel.Type); + REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc)); OS.write((const char *)&REntry, sizeof(REntry)); } } |
