[llvm] r178694 - Implement the "mips endian" for r_info.

Rafael Espindola rafael.espindola at gmail.com
Wed Apr 3 14:02:51 PDT 2013


Author: rafael
Date: Wed Apr  3 16:02:51 2013
New Revision: 178694

URL: http://llvm.org/viewvc/llvm-project?rev=178694&view=rev
Log:
Implement the "mips endian" for r_info.

Normally r_info is just a 32 of 64 bit number matching the endian of the rest
of the file. Unfortunately, mips 64 bit little endian is special: The top 32
bits are a little endian number and the following 32 are a big endian one.

Added:
    llvm/trunk/test/Object/Inputs/trivial-object-test.elf-mips64el
Modified:
    llvm/trunk/include/llvm/Object/ELF.h
    llvm/trunk/test/MC/Mips/eh-frame.s
    llvm/trunk/test/Object/objdump-relocations.test

Modified: llvm/trunk/include/llvm/Object/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=178694&r1=178693&r2=178694&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELF.h (original)
+++ llvm/trunk/include/llvm/Object/ELF.h Wed Apr  3 16:02:51 2013
@@ -330,6 +330,14 @@ struct Elf_Rel_Base<ELFT<TargetEndiannes
                              MaxAlign LLVM_ELF_COMMA false>)
   Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
   Elf_Word      r_info;  // Symbol table index and type of relocation to apply
+
+  uint32_t getRInfo(bool isMips64EL) const {
+    assert(!isMips64EL);
+    return r_info;
+  }
+  void setRInfo(uint32_t R) {
+    r_info = R;
+  }
 };
 
 template<template<endianness, std::size_t, bool> class ELFT,
@@ -339,6 +347,22 @@ struct Elf_Rel_Base<ELFT<TargetEndiannes
                              MaxAlign LLVM_ELF_COMMA true>)
   Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
   Elf_Xword     r_info;   // Symbol table index and type of relocation to apply
+
+  uint64_t getRInfo(bool isMips64EL) const {
+    uint64_t t = r_info;
+    if (!isMips64EL)
+      return t;
+    // Mip64 little endian has a "special" encoding of r_info. Instead of one
+    // 64 bit little endian number, it is a little ending 32 bit number followed
+    // by a 32 bit big endian number.
+    return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
+      ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
+    return r_info;
+  }
+  void setRInfo(uint64_t R) {
+    // FIXME: Add mips64el support.
+    r_info = R;
+  }
 };
 
 template<template<endianness, std::size_t, bool> class ELFT,
@@ -349,6 +373,14 @@ struct Elf_Rel_Base<ELFT<TargetEndiannes
   Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
   Elf_Word      r_info;   // Symbol table index and type of relocation to apply
   Elf_Sword     r_addend; // Compute value for relocatable field by adding this
+
+  uint32_t getRInfo(bool isMips64EL) const {
+    assert(!isMips64EL);
+    return r_info;
+  }
+  void setRInfo(uint32_t R) {
+    r_info = R;
+  }
 };
 
 template<template<endianness, std::size_t, bool> class ELFT,
@@ -359,6 +391,21 @@ struct Elf_Rel_Base<ELFT<TargetEndiannes
   Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
   Elf_Xword     r_info;   // Symbol table index and type of relocation to apply
   Elf_Sxword    r_addend; // Compute value for relocatable field by adding this.
+
+  uint64_t getRInfo(bool isMips64EL) const {
+    // Mip64 little endian has a "special" encoding of r_info. Instead of one
+    // 64 bit little endian number, it is a little ending 32 bit number followed
+    // by a 32 bit big endian number.
+    uint64_t t = r_info;
+    if (!isMips64EL)
+      return t;
+    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;
+  }
 };
 
 template<class ELFT, bool isRela>
@@ -368,20 +415,21 @@ template<template<endianness, std::size_
          endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
 struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, true>, isRela>
        : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela> {
-  using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela>::r_info;
   LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA
                              MaxAlign LLVM_ELF_COMMA true>)
 
   // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
   // and ELF64_R_INFO macros defined in the ELF specification:
-  uint32_t getSymbol() const { return (uint32_t) (r_info >> 32); }
-  uint32_t getType() const {
-    return (uint32_t) (r_info & 0xffffffffL);
+  uint32_t getSymbol(bool isMips64EL) const {
+    return (uint32_t) (this->getRInfo(isMips64EL) >> 32);
+  }
+  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) {
-    r_info = ((uint64_t)s << 32) + (t&0xffffffffL);
+    this->setRInfo(((uint64_t)s << 32) + (t&0xffffffffL));
   }
 };
 
@@ -389,18 +437,21 @@ template<template<endianness, std::size_
          endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
 struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, false>, isRela>
        : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela> {
-  using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela>::r_info;
   LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA
                              MaxAlign LLVM_ELF_COMMA false>)
 
   // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
   // and ELF32_R_INFO macros defined in the ELF specification:
-  uint32_t getSymbol() const { return (r_info >> 8); }
-  unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); }
+  uint32_t getSymbol(bool isMips64EL) const {
+    return this->getRInfo(isMips64EL) >> 8;
+  }
+  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) {
-    r_info = (s << 8) + t;
+    this->setRInfo((s << 8) + t);
   }
 };
 
@@ -703,6 +754,13 @@ protected:
 
 public:
   ELFObjectFile(MemoryBuffer *Object, error_code &ec);
+
+  bool isMips64EL() const {
+    return Header->e_machine == ELF::EM_MIPS &&
+      Header->getFileClass() == ELF::ELFCLASS64 &&
+      Header->getDataEncoding() == ELF::ELFDATA2LSB;
+  }
+
   virtual symbol_iterator begin_symbols() const;
   virtual symbol_iterator end_symbols() const;
 
@@ -1467,11 +1525,11 @@ error_code ELFObjectFile<ELFT>::getReloc
     default :
       report_fatal_error("Invalid section type in Rel!");
     case ELF::SHT_REL : {
-      symbolIdx = getRel(Rel)->getSymbol();
+      symbolIdx = getRel(Rel)->getSymbol(isMips64EL());
       break;
     }
     case ELF::SHT_RELA : {
-      symbolIdx = getRela(Rel)->getSymbol();
+      symbolIdx = getRela(Rel)->getSymbol(isMips64EL());
       break;
     }
   }
@@ -1537,11 +1595,11 @@ error_code ELFObjectFile<ELFT>::getReloc
     default :
       report_fatal_error("Invalid section type in Rel!");
     case ELF::SHT_REL : {
-      Result = getRel(Rel)->getType();
+      Result = getRel(Rel)->getType(isMips64EL());
       break;
     }
     case ELF::SHT_RELA : {
-      Result = getRela(Rel)->getType();
+      Result = getRela(Rel)->getType(isMips64EL());
       break;
     }
   }
@@ -1561,11 +1619,11 @@ error_code ELFObjectFile<ELFT>::getReloc
     default :
       return object_error::parse_failed;
     case ELF::SHT_REL : {
-      type = getRel(Rel)->getType();
+      type = getRel(Rel)->getType(isMips64EL());
       break;
     }
     case ELF::SHT_RELA : {
-      type = getRela(Rel)->getType();
+      type = getRela(Rel)->getType(isMips64EL());
       break;
     }
   }
@@ -2059,14 +2117,14 @@ error_code ELFObjectFile<ELFT>::getReloc
     default:
       return object_error::parse_failed;
     case ELF::SHT_REL: {
-      type = getRel(Rel)->getType();
-      symbol_index = getRel(Rel)->getSymbol();
+      type = getRel(Rel)->getType(isMips64EL());
+      symbol_index = getRel(Rel)->getSymbol(isMips64EL());
       // TODO: Read implicit addend from section data.
       break;
     }
     case ELF::SHT_RELA: {
-      type = getRela(Rel)->getType();
-      symbol_index = getRela(Rel)->getSymbol();
+      type = getRela(Rel)->getType(isMips64EL());
+      symbol_index = getRela(Rel)->getSymbol(isMips64EL());
       addend = getRela(Rel)->r_addend;
       break;
     }

Modified: llvm/trunk/test/MC/Mips/eh-frame.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/eh-frame.s?rev=178694&r1=178693&r2=178694&view=diff
==============================================================================
--- llvm/trunk/test/MC/Mips/eh-frame.s (original)
+++ llvm/trunk/test/MC/Mips/eh-frame.s Wed Apr  3 16:02:51 2013
@@ -130,7 +130,7 @@ func:
 
 
 // MIPS64EL: RELOCATION RECORDS FOR [.eh_frame]:
-// FIXME: llvm-objdump currently misprints the relocations for mips64el
+// MIPS64EL-NEXT: R_MIPS_64
 // MIPS64EL: Contents of section .eh_frame:
 // MIPS64EL-NEXT: 0000
 

Added: llvm/trunk/test/Object/Inputs/trivial-object-test.elf-mips64el
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/trivial-object-test.elf-mips64el?rev=178694&view=auto
==============================================================================
Binary files llvm/trunk/test/Object/Inputs/trivial-object-test.elf-mips64el (added) and llvm/trunk/test/Object/Inputs/trivial-object-test.elf-mips64el Wed Apr  3 16:02:51 2013 differ

Modified: llvm/trunk/test/Object/objdump-relocations.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/objdump-relocations.test?rev=178694&r1=178693&r2=178694&view=diff
==============================================================================
--- llvm/trunk/test/Object/objdump-relocations.test (original)
+++ llvm/trunk/test/Object/objdump-relocations.test Wed Apr  3 16:02:51 2013
@@ -8,6 +8,8 @@ RUN: llvm-objdump -r %p/Inputs/trivial-o
 RUN:              | FileCheck %s -check-prefix ELF-x86-64
 RUN: llvm-objdump -r %p/Inputs/trivial-object-test.elf-hexagon \
 RUN:              | FileCheck %s -check-prefix ELF-hexagon
+RUN: llvm-objdump -r %p/Inputs/trivial-object-test.elf-mips64el \
+RUN:              | FileCheck %s -check-prefix ELF-MIPS64EL
 
 RUN: llvm-objdump -r %p/Inputs/relocations.elf-x86-64 \
 RUN:              | FileCheck %s -check-prefix ELF-complex-x86-64
@@ -40,6 +42,11 @@ ELF-hexagon: R_HEX_LO16 puts
 ELF-hexagon: R_HEX_B15_PCREL testf
 ELF-hexagon: R_HEX_B22_PCREL puts
 
+// Note: this file was produced with gas to make sure we don't end up in a
+// situation where LLVM produces and accepts a broken file.
+ELF-MIPS64EL: .data
+ELF-MIPS64EL: R_MIPS_64
+
 ELF-complex-x86-64: .text
 ELF-complex-x86-64-NEXT: R_X86_64_8 .data-4
 ELF-complex-x86-64-NEXT: R_X86_64_16 .data-4





More information about the llvm-commits mailing list