[lld] r207949 - [Mips] R_MIPS_GPREL32 relocation support.

Simon Atanasyan simon at atanasyan.com
Sun May 4 22:56:06 PDT 2014


Author: atanasyan
Date: Mon May  5 00:56:06 2014
New Revision: 207949

URL: http://llvm.org/viewvc/llvm-project?rev=207949&view=rev
Log:
[Mips] R_MIPS_GPREL32 relocation support.

Added:
    lld/trunk/test/elf/Mips/rel-gprel32.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h?rev=207949&r1=207948&r2=207949&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h Mon May  5 00:56:06 2014
@@ -12,6 +12,31 @@
 #include "ELFReader.h"
 #include "MipsLinkingContext.h"
 
+namespace llvm {
+namespace object {
+
+template <class ELFT>
+struct Elf_RegInfo;
+
+template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
+struct Elf_RegInfo<ELFType<TargetEndianness, MaxAlign, false>> {
+  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
+  Elf_Word ri_gprmask;     // bit-mask of used general registers
+  Elf_Word ri_cprmask[4];  // bit-mask of used co-processor registers
+  Elf_Sword ri_gp_value;   // gp register value
+};
+
+template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
+struct Elf_RegInfo<ELFType<TargetEndianness, MaxAlign, true>> {
+  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
+  Elf_Word ri_gprmask;     // bit-mask of used general registers
+  Elf_Word ri_cprmask[4];  // bit-mask of used co-processor registers
+  Elf_Sword ri_gp_value;   // gp register value
+};
+
+} // end namespace object.
+} // end namespace llvm.
+
 namespace lld {
 namespace elf {
 
@@ -44,7 +69,7 @@ public:
 
   MipsELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings,
               error_code &ec)
-      : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec) {}
+      : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec), _gp0(0) {}
 
   static ErrorOr<std::unique_ptr<MipsELFFile>>
   create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
@@ -76,6 +101,10 @@ public:
     if ((ec = file->createAtoms()))
       return ec;
 
+    // Retrieve registry usage descriptor and GP value.
+    if ((ec = file->readRegInfo()))
+      return ec;
+
     return std::move(file);
   }
 
@@ -83,12 +112,17 @@ public:
     return this->_objFile->getHeader()->e_flags & llvm::ELF::EF_MIPS_PIC;
   }
 
+  /// \brief gp register value stored in the .reginfo section.
+  int64_t getGP0() const { return _gp0; }
+
 private:
   typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
   typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
   typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter Elf_Rel_Iter;
 
+  int64_t _gp0;
+
   ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(
       StringRef symName, StringRef sectionName, const Elf_Sym *sym,
       const Elf_Shdr *sectionHdr, ArrayRef<uint8_t> contentData,
@@ -99,6 +133,30 @@ private:
         referenceStart, referenceEnd, referenceList);
   }
 
+  error_code readRegInfo() {
+    typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
+
+    for (auto sit = this->_objFile->begin_sections(),
+              sie = this->_objFile->end_sections();
+         sit != sie; ++sit) {
+      if (sit->sh_type != llvm::ELF::SHT_MIPS_REGINFO)
+        continue;
+
+      auto contents = this->getSectionContents(&*sit);
+      if (error_code ec = contents.getError())
+        return ec;
+
+      // FIXME (simon): Show error in case of invalid section size.
+      if (contents.get().size() == sizeof(Elf_RegInfo)) {
+        const auto *regInfo =
+            reinterpret_cast<const Elf_RegInfo *>(contents.get().data());
+        _gp0 = regInfo->ri_gp_value;
+      }
+      break;
+    }
+    return error_code::success();
+  }
+
   void createRelocationReferences(const Elf_Sym &symbol,
                                   ArrayRef<uint8_t> symContent,
                                   ArrayRef<uint8_t> secContent,
@@ -129,6 +187,7 @@ private:
     const uint8_t *ap = content.data() + ri.r_offset;
     switch (ri.getType(isMips64EL())) {
     case llvm::ELF::R_MIPS_32:
+    case llvm::ELF::R_MIPS_GPREL32:
     case llvm::ELF::R_MIPS_PC32:
       return *(int32_t *)ap;
     case llvm::ELF::R_MIPS_26:

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp?rev=207949&r1=207948&r2=207949&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp Mon May  5 00:56:06 2014
@@ -101,6 +101,14 @@ static void relocCall16(uint8_t *locatio
   applyReloc(location, G, 0xffff);
 }
 
+/// \brief R_MIPS_GPREL32
+/// local: rel32 A + S + GP0 – GP (truncate)
+static void relocGPRel32(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
+                         uint64_t GP) {
+  int32_t result = A + S + 0 - GP;
+  applyReloc(location, result, 0xffffffff);
+}
+
 /// \brief LLD_R_MIPS_32_HI16
 static void reloc32hi16(uint8_t *location, uint64_t S, int64_t A) {
   applyReloc(location, (S + A) & 0xffff0000, 0xffffffff);
@@ -154,6 +162,9 @@ error_code MipsTargetRelocationHandler::
   case R_MIPS_CALL16:
     relocCall16(location, relocVAddress, targetVAddress, ref.addend(), gpAddr);
     break;
+  case R_MIPS_GPREL32:
+    relocGPRel32(location, relocVAddress, targetVAddress, ref.addend(), gpAddr);
+    break;
   case R_MIPS_JALR:
     // We do not do JALR optimization now.
     break;

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp?rev=207949&r1=207948&r2=207949&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Mon May  5 00:56:06 2014
@@ -194,7 +194,7 @@ private:
   std::vector<LA25Atom *> _la25Vector;
 
   /// \brief Handle a specific reference.
-  void handleReference(Reference &ref);
+  void handleReference(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
 
   /// \brief Collect information about the reference to use it
   /// later in the handleReference() routine.
@@ -204,6 +204,7 @@ private:
   void handlePlain(Reference &ref);
   void handle26(Reference &ref);
   void handleGOT(Reference &ref);
+  void handleGPRel(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
 
   const GOTAtom *getLocalGOTEntry(const Reference &ref);
   const GOTAtom *getGlobalGOTEntry(const Atom *a);
@@ -243,7 +244,8 @@ void RelocationPass<ELFT>::perform(std::
   // Process all references.
   for (const auto &atom : mf->defined())
     for (const auto &ref : *atom)
-      handleReference(const_cast<Reference &>(*ref));
+      handleReference(*cast<MipsELFDefinedAtom<ELFT>>(atom),
+                      const_cast<Reference &>(*ref));
 
   // Create R_MIPS_REL32 relocations.
   for (auto *ref : _rel32Candidates) {
@@ -298,7 +300,8 @@ void RelocationPass<ELFT>::perform(std::
 }
 
 template <typename ELFT>
-void RelocationPass<ELFT>::handleReference(Reference &ref) {
+void RelocationPass<ELFT>::handleReference(const MipsELFDefinedAtom<ELFT> &atom,
+                                           Reference &ref) {
   if (!ref.target())
     return;
   if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
@@ -319,6 +322,23 @@ void RelocationPass<ELFT>::handleReferen
   case R_MIPS_CALL16:
     handleGOT(ref);
     break;
+  case R_MIPS_GPREL32:
+    handleGPRel(atom, ref);
+    break;
+  }
+}
+
+template <typename ELFT>
+static bool isConstrainSym(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref) {
+  if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
+    return false;
+  switch (ref.kindValue()) {
+  case R_MIPS_NONE:
+  case R_MIPS_JALR:
+  case R_MIPS_GPREL32:
+    return false;
+  default:
+    return true;
   }
 }
 
@@ -330,7 +350,7 @@ RelocationPass<ELFT>::collectReferenceIn
     return;
   if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
     return;
-  if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
+  if (!isConstrainSym(atom, ref))
     return;
 
   if (mightBeDynamic(atom, ref))
@@ -481,6 +501,13 @@ template <typename ELFT> void Relocation
 }
 
 template <typename ELFT>
+void RelocationPass<ELFT>::handleGPRel(const MipsELFDefinedAtom<ELFT> &atom,
+                                       Reference &ref) {
+  assert(ref.kindValue() == R_MIPS_GPREL32);
+  ref.setAddend(ref.addend() + atom.file().getGP0());
+}
+
+template <typename ELFT>
 bool RelocationPass<ELFT>::isLocalCall(const Atom *a) const {
   Atom::Scope scope;
   if (auto *da = dyn_cast<DefinedAtom>(a))

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp?rev=207949&r1=207948&r2=207949&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp Mon May  5 00:56:06 2014
@@ -55,6 +55,7 @@ const Registry::KindStrings MipsTargetHa
   LLD_KIND_STRING_ENTRY(R_MIPS_LO16),
   LLD_KIND_STRING_ENTRY(R_MIPS_GOT16),
   LLD_KIND_STRING_ENTRY(R_MIPS_CALL16),
+  LLD_KIND_STRING_ENTRY(R_MIPS_GPREL32),
   LLD_KIND_STRING_ENTRY(R_MIPS_JALR),
   LLD_KIND_STRING_ENTRY(R_MIPS_COPY),
   LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT),

Added: lld/trunk/test/elf/Mips/rel-gprel32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/rel-gprel32.test?rev=207949&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/rel-gprel32.test (added)
+++ lld/trunk/test/elf/Mips/rel-gprel32.test Mon May  5 00:56:06 2014
@@ -0,0 +1,84 @@
+# Check R_MIPS_GPREL32 relocation handling.
+#
+# RUN: yaml2obj -format=elf %s > %t-obj
+# RUN: lld -flavor gnu -target mipsel -o %t-exe %t-obj
+# RUN: llvm-readobj -symbols %t-exe | FileCheck -check-prefix=SYM %s
+# RUN: llvm-objdump -s %t-exe | FileCheck -check-prefix=SEC %s
+
+# SYM:      Name: $L1 (1)
+# SYM-NEXT: Value: 0x400108
+# SYM-NEXT: Size: 4
+# SYM-NEXT: Binding: Local (0x0)
+# SYM-NEXT: Type: Function (0x2)
+# SYM-NEXT: Other: 0
+# SYM-NEXT: Section: .text (0x5)
+#
+# SYM:      Name: _gp (212)
+# SYM-NEXT: Value: 0x408FF0
+# SYM-NEXT: Size: 0
+# SYM-NEXT: Binding: Global (0x1)
+# SYM-NEXT: Type: Object (0x1)
+# SYM-NEXT: Other: 0
+# SYM-NEXT: Section: Absolute (0xFFF1)
+
+# 0x08FF711B == 0x8000001 (addend) + 0x400108 ($L1) +
+#               0x1000002 (GP0) - 0x408FF0 (_gp)
+# SEC:      Contents of section .rodata:
+# SEC-NEXT:  400118 1b71ff08 00000000 00000000 00000000  .q..............
+
+!ELF
+FileHeader:
+  Class:    ELFCLASS32
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_MIPS
+  Flags:    [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+              EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
+Sections:
+- Type:         SHT_PROGBITS
+  Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  AddressAlign: 0x04
+  Content:      00000000000000000000000000000000
+
+- Type:         SHT_PROGBITS
+  Name:         .rodata
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 0x04
+  Content:      01000008000000000000000000000000
+
+- Type:         SHT_REL
+  Name:         .rel.rodata
+  Type:         SHT_REL
+  Link:         .symtab
+  Info:         .rodata
+  AddressAlign: 0x04
+  Relocations:
+    - Offset:      0
+      Symbol:      $L1
+      Type:        R_MIPS_GPREL32
+
+- Type:         SHT_MIPS_REGINFO
+  Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 0x01
+  Content:      000000000000000000000000000000000000000002000001
+
+Symbols:
+  Local:
+    - Name:     $L1
+      Section:  .text
+      Value:    0x00
+    - Name:     .rodata
+      Type:     STT_SECTION
+      Section:  .rodata
+  Global:
+    - Name:     __start
+      Section:  .text
+      Type:     STT_FUNC
+      Value:    0x04
+      Size:     12
+    - Name:     _gp_disp





More information about the llvm-commits mailing list