[llvm] r227044 - [ELFYAML] Support mips64 relocation record format in yaml2obj/obj2yaml

Simon Atanasyan simon at atanasyan.com
Sun Jan 25 05:29:25 PST 2015


Author: atanasyan
Date: Sun Jan 25 07:29:25 2015
New Revision: 227044

URL: http://llvm.org/viewvc/llvm-project?rev=227044&view=rev
Log:
[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

Added:
    llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml
Modified:
    llvm/trunk/include/llvm/Object/ELFTypes.h
    llvm/trunk/include/llvm/Object/ELFYAML.h
    llvm/trunk/include/llvm/Support/ELF.h
    llvm/trunk/lib/Object/ELFYAML.cpp
    llvm/trunk/tools/yaml2obj/yaml2elf.cpp

Modified: llvm/trunk/include/llvm/Object/ELFTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFTypes.h?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFTypes.h (original)
+++ llvm/trunk/include/llvm/Object/ELFTypes.h Sun Jan 25 07:29:25 2015
@@ -302,7 +302,10 @@ struct Elf_Rel_Base<ELFType<TargetEndian
     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<TargetEndian
     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<TargetEndian
     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<TargetEndian
     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<TargetEndian
   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<TargetEndian
   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);
   }
 };
 

Modified: llvm/trunk/include/llvm/Object/ELFYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFYAML.h?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFYAML.h (original)
+++ llvm/trunk/include/llvm/Object/ELFYAML.h Sun Jan 25 07:29:25 2015
@@ -41,6 +41,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_EL
 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::
 };
 
 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);
 };

Modified: llvm/trunk/include/llvm/Support/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ELF.h?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ELF.h (original)
+++ llvm/trunk/include/llvm/Support/ELF.h Sun Jan 25 07:29:25 2015
@@ -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)

Modified: llvm/trunk/lib/Object/ELFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ELFYAML.cpp?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ELFYAML.cpp (original)
+++ llvm/trunk/lib/Object/ELFYAML.cpp Sun Jan 25 07:29:25 2015
@@ -415,6 +415,16 @@ void ScalarBitSetTraits<ELFYAML::ELF_STO
 #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<
   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);
 }
 

Added: llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml?rev=227044&view=auto
==============================================================================
--- llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml (added)
+++ llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml Sun Jan 25 07:29:25 2015
@@ -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
+...

Modified: llvm/trunk/tools/yaml2obj/yaml2elf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2elf.cpp?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2elf.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2elf.cpp Sun Jan 25 07:29:25 2015
@@ -321,6 +321,12 @@ ELFState<ELFT>::writeSectionContent(Elf_
   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_
       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));
     }
   }





More information about the llvm-commits mailing list