[Mips] Support writing .reginfo section into the linked file
authorSimon Atanasyan <simon@atanasyan.com>
Sat, 4 Apr 2015 19:13:32 +0000 (19:13 +0000)
committerSimon Atanasyan <simon@atanasyan.com>
Sat, 4 Apr 2015 19:13:32 +0000 (19:13 +0000)
In case of MIPS O32 ABI linker should merge registers usage masks stored
in the input .reginfo sections and save result into the output .reginfo
section.

The ABI states that the .reginfo section should be put into the separate
segment. This requirement is not implemented in this patch.

llvm-svn: 234103

19 files changed:
lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h
lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h
lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
lld/lib/ReaderWriter/ELF/Mips/MipsReginfo.h
lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
lld/test/CMakeLists.txt
lld/test/elf/Mips/base-address.test
lld/test/elf/Mips/dynlib-fileheader-micro.test
lld/test/elf/Mips/dynlib-fileheader.test
lld/test/elf/Mips/mips-options-gp0.test
lld/test/elf/Mips/reginfo-01.test [new file with mode: 0644]
lld/test/elf/Mips/reginfo-02.test [new file with mode: 0644]
lld/test/elf/Mips/reginfo-03.test [new file with mode: 0644]
lld/test/elf/Mips/reginfo-04.test [new file with mode: 0644]
lld/test/elf/Mips/reginfo-05.test [new file with mode: 0644]
lld/test/elf/Mips/rel-gprel16.test
lld/test/elf/Mips/rel-gprel32.test

index 034b57ca7c3eb1078ed67df138891d84396b3d71..a72a467b808735dc5f160eb6fbe298d86934b86d 100644 (file)
@@ -13,6 +13,7 @@
 #include "MipsDynamicTable.h"
 #include "MipsELFWriters.h"
 #include "MipsLinkingContext.h"
+#include "MipsSectionChunks.h"
 
 namespace lld {
 namespace elf {
@@ -32,6 +33,7 @@ protected:
   bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
 
   void finalizeDefaultAtomValues() override;
+  void createDefaultSections() override;
 
   std::error_code setELFHeader() override {
     DynamicLibraryWriter<ELFT>::setELFHeader();
@@ -46,6 +48,7 @@ protected:
 private:
   MipsELFWriter<ELFT> _writeHelper;
   MipsTargetLayout<ELFT> &_targetLayout;
+  unique_bump_ptr<Section<ELFT>> _reginfo;
 };
 
 template <class ELFT>
@@ -69,6 +72,19 @@ void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
   _writeHelper.finalizeMipsRuntimeAtomValues();
 }
 
+template <class ELFT>
+void MipsDynamicLibraryWriter<ELFT>::createDefaultSections() {
+  DynamicLibraryWriter<ELFT>::createDefaultSections();
+  const auto &mask =
+      static_cast<const MipsLinkingContext &>(this->_ctx).getMergeReginfoMask();
+  if (!ELFT::Is64Bits && mask.hasValue()) {
+    _reginfo = unique_bump_ptr<Section<ELFT>>(
+        new (this->_alloc)
+            MipsReginfoSection<ELFT>(this->_ctx, _targetLayout, *mask));
+    this->_layout.addSection(_reginfo.get());
+  }
+}
+
 template <class ELFT>
 unique_bump_ptr<SymbolTable<ELFT>>
     MipsDynamicLibraryWriter<ELFT>::createSymbolTable() {
index 7376fb5f2cf0966106a89b96c66a507dee024c57..92d1165595e4871ab87b6815958c132cd1c6b043 100644 (file)
@@ -161,6 +161,8 @@ private:
     typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
     typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
 
+    auto &ctx = static_cast<MipsLinkingContext &>(this->_ctx);
+
     if (const Elf_Shdr *sec = findSectionByType(SHT_MIPS_OPTIONS)) {
       auto contents = this->getSectionContents(sec);
       if (std::error_code ec = contents.getError())
@@ -172,9 +174,12 @@ private:
           return make_dynamic_error_code(
               StringRef("Invalid size of MIPS_OPTIONS section"));
 
-        const auto *opt = reinterpret_cast<const Elf_Mips_Options *>(raw.data());
+        const auto *opt =
+            reinterpret_cast<const Elf_Mips_Options *>(raw.data());
         if (opt->kind == ODK_REGINFO) {
-          _gp0 = reinterpret_cast<const Elf_RegInfo *>(opt + 1)->ri_gp_value;
+          const auto *regInfo = reinterpret_cast<const Elf_RegInfo *>(opt + 1);
+          ctx.mergeReginfoMask(*regInfo);
+          _gp0 = regInfo->ri_gp_value;
           break;
         }
         raw = raw.slice(opt->size);
@@ -189,7 +194,9 @@ private:
         return make_dynamic_error_code(
             StringRef("Invalid size of MIPS_REGINFO section"));
 
-      _gp0 = reinterpret_cast<const Elf_RegInfo *>(raw.data())->ri_gp_value;
+      const auto *regInfo = reinterpret_cast<const Elf_RegInfo *>(raw.data());
+      ctx.mergeReginfoMask(*regInfo);
+      _gp0 = regInfo->ri_gp_value;
     }
     return std::error_code();
   }
index 3927d69e6be68b4962f35c73e57197149bf4dad3..61e2eedc53929f95bf9d740587e0731ec29a11c4 100644 (file)
@@ -31,6 +31,7 @@ protected:
   bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
 
   void finalizeDefaultAtomValues() override;
+  void createDefaultSections() override;
   std::error_code setELFHeader() override;
 
   unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
@@ -40,6 +41,7 @@ protected:
 private:
   MipsELFWriter<ELFT> _writeHelper;
   MipsTargetLayout<ELFT> &_targetLayout;
+  unique_bump_ptr<Section<ELFT>> _reginfo;
 };
 
 template <class ELFT>
@@ -122,6 +124,18 @@ void MipsExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
   _writeHelper.finalizeMipsRuntimeAtomValues();
 }
 
+template <class ELFT> void MipsExecutableWriter<ELFT>::createDefaultSections() {
+  ExecutableWriter<ELFT>::createDefaultSections();
+  const auto &mask =
+      static_cast<const MipsLinkingContext &>(this->_ctx).getMergeReginfoMask();
+  if (!ELFT::Is64Bits && mask.hasValue()) {
+    _reginfo = unique_bump_ptr<Section<ELFT>>(
+        new (this->_alloc)
+            MipsReginfoSection<ELFT>(this->_ctx, _targetLayout, *mask));
+    this->_layout.addSection(_reginfo.get());
+  }
+}
+
 template <class ELFT>
 unique_bump_ptr<SymbolTable<ELFT>>
     MipsExecutableWriter<ELFT>::createSymbolTable() {
index ea91fcfd6de667ae9141a9093560068c7188c5bb..fcbd72471ee3ec66caed4224cad632d4eab57536 100644 (file)
@@ -47,10 +47,22 @@ std::error_code MipsLinkingContext::mergeHeaderFlags(uint8_t fileClass,
   return _flagsMerger.mergeHeaderFlags(fileClass, flags);
 }
 
+void MipsLinkingContext::mergeReginfoMask(const MipsReginfo &info) {
+  if (_reginfoMask.hasValue())
+    _reginfoMask->merge(info);
+  else
+    _reginfoMask = info;
+}
+
 uint32_t MipsLinkingContext::getMergedELFFlags() const {
   return _flagsMerger.getMergedELFFlags();
 }
 
+const llvm::Optional<MipsReginfo> &
+MipsLinkingContext::getMergeReginfoMask() const {
+  return _reginfoMask;
+}
+
 uint64_t MipsLinkingContext::getBaseAddress() const {
   if (_baseAddress == 0 && getOutputELFType() == llvm::ELF::ET_EXEC)
     return getTriple().isArch64Bit() ? 0x120000000 : 0x400000;
index f6679706866870d9b1b9150ebc6a744bf761c811..d77ba25c9659b27f2c753f7592e2c2fef0e6c01e 100644 (file)
@@ -10,6 +10,7 @@
 #define LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
 
 #include "MipsELFFlagsMerger.h"
+#include "MipsReginfo.h"
 #include "lld/ReaderWriter/ELFLinkingContext.h"
 
 namespace lld {
@@ -46,7 +47,11 @@ public:
   MipsLinkingContext(llvm::Triple triple);
 
   std::error_code mergeHeaderFlags(uint8_t fileClass, uint64_t flags) override;
+  void mergeReginfoMask(const MipsReginfo &info);
+
   uint32_t getMergedELFFlags() const;
+  const llvm::Optional<MipsReginfo> &getMergeReginfoMask() const;
+
   void registerRelocationNames(Registry &r) override;
 
   // ELFLinkingContext
@@ -62,6 +67,7 @@ public:
 
 private:
   MipsELFFlagsMerger _flagsMerger;
+  llvm::Optional<MipsReginfo> _reginfoMask;
 };
 
 } // elf
index 01552a293de42da209615d283fe1fe12baf39997..83ccaa5e1a6acc16b19f5517bf1cd70351c30d4c 100644 (file)
@@ -47,4 +47,33 @@ template <class ELFT> struct Elf_Mips_Options {
 } // end namespace object.
 } // end namespace llvm.
 
+namespace lld {
+namespace elf {
+
+struct MipsReginfo {
+  uint32_t _gpRegMask = 0;
+  uint32_t _cpRegMask[4] = {0};
+
+  MipsReginfo() = default;
+
+  template <class ElfReginfo> MipsReginfo(const ElfReginfo &elf) {
+    _gpRegMask = elf.ri_gprmask;
+    _cpRegMask[0] = elf.ri_cprmask[0];
+    _cpRegMask[1] = elf.ri_cprmask[1];
+    _cpRegMask[2] = elf.ri_cprmask[2];
+    _cpRegMask[3] = elf.ri_cprmask[3];
+  }
+
+  void merge(const MipsReginfo &info) {
+    _gpRegMask |= info._gpRegMask;
+    _cpRegMask[0] |= info._cpRegMask[0];
+    _cpRegMask[1] |= info._cpRegMask[1];
+    _cpRegMask[2] |= info._cpRegMask[2];
+    _cpRegMask[3] |= info._cpRegMask[3];
+  }
+};
+
+} // end namespace elf
+} // end namespace lld
+
 #endif
index 06142fd4c2a74fd8860cba2c10f8b109e4ea29c1..67ec6f3d756b8c4c05d9df98441b80331d607826 100644 (file)
@@ -9,12 +9,59 @@
 #ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H
 #define LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H
 
+#include "MipsReginfo.h"
+
 namespace lld {
 namespace elf {
 
 template <typename ELFT> class MipsTargetLayout;
 class MipsLinkingContext;
 
+/// \brief Handle Mips .reginfo section
+template <class ELFT> class MipsReginfoSection : public Section<ELFT> {
+public:
+  MipsReginfoSection(const ELFLinkingContext &ctx,
+                     MipsTargetLayout<ELFT> &targetLayout,
+                     const MipsReginfo &reginfo)
+      : Section<ELFT>(ctx, ".reginfo", "MipsReginfo"),
+        _targetLayout(targetLayout) {
+    this->setOrder(MipsTargetLayout<ELFT>::ORDER_RO_NOTE);
+    this->_entSize = sizeof(Elf_RegInfo);
+    this->_fsize = sizeof(Elf_RegInfo);
+    this->_msize = sizeof(Elf_RegInfo);
+    this->_alignment = 4;
+    this->_type = SHT_MIPS_REGINFO;
+    this->_flags = SHF_ALLOC;
+
+    memset(&_reginfo, 0, sizeof(_reginfo));
+    _reginfo.ri_gprmask = reginfo._gpRegMask;
+    _reginfo.ri_cprmask[0] = reginfo._cpRegMask[0];
+    _reginfo.ri_cprmask[1] = reginfo._cpRegMask[1];
+    _reginfo.ri_cprmask[2] = reginfo._cpRegMask[2];
+    _reginfo.ri_cprmask[3] = reginfo._cpRegMask[3];
+  }
+
+  void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
+             llvm::FileOutputBuffer &buffer) override {
+    uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
+    std::memcpy(dest, &_reginfo, this->_fsize);
+  }
+
+  void finalize() override {
+    const AtomLayout *gpAtom = _targetLayout.getGP();
+    _reginfo.ri_gp_value = gpAtom ? gpAtom->_virtualAddr : 0;;
+
+    if (this->_outputSection)
+      this->_outputSection->setType(this->_type);
+  }
+
+private:
+  typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
+
+  Elf_RegInfo _reginfo;
+  MipsTargetLayout<ELFT> &_targetLayout;
+};
+
 /// \brief Handle Mips GOT section
 template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> {
 public:
index e29f5f4c5a90bdac300e8226afd0599f95f92983..dff9903f9256ad19b116ad22e7c399dc2911fb77 100644 (file)
@@ -20,7 +20,7 @@ configure_lit_site_cfg(
   )
 
 set(LLD_TEST_DEPS
-  FileCheck not llvm-nm
+  FileCheck not llvm-ar llvm-nm
   lld llvm-config llvm-objdump llvm-readobj yaml2obj obj2yaml
   linker-script-test macho-dump llvm-mc llvm-nm
   )
index f55091f84c33db7b044d2324eb84abd451f14181..5f629a4b434f5a1c7179f3f2c04eec3ac07bc7cd 100644 (file)
@@ -77,16 +77,6 @@ Sections:
     Flags:           [ SHF_WRITE, SHF_ALLOC ]
     AddressAlign:    0x04
     Size:            0x00
-  - Name:            .reginfo
-    Type:            SHT_MIPS_REGINFO
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x01
-    Size:            0x18
-  - Name:            .MIPS.abiflags
-    Type:            SHT_MIPS_ABIFLAGS
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x08
-    Content:         '000020010101000100000000000000000000000000000000'
 Symbols:
   Local:
     - Name:            .text
@@ -98,12 +88,6 @@ Symbols:
     - Name:            .bss
       Type:            STT_SECTION
       Section:         .bss
-    - Name:            .reginfo
-      Type:            STT_SECTION
-      Section:         .reginfo
-    - Name:            .MIPS.abiflags
-      Type:            STT_SECTION
-      Section:         .MIPS.abiflags
   Global:
     - Name:            main
       Section:         .text
index 139b3aa626c90ecf5fa37a9391186fe383fa2da8..5572160b5aaff57405c7abe7f4cb342d851f0302 100644 (file)
@@ -64,11 +64,6 @@ Sections:
     Flags:           [ SHF_WRITE, SHF_ALLOC ]
     AddressAlign:    0x04
     Size:            0x00
-  - Name:            .reginfo
-    Type:            SHT_MIPS_REGINFO
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x01
-    Size:            0x18
   - Name:            .MIPS.abiflags
     Type:            SHT_MIPS_ABIFLAGS
     Flags:           [ SHF_ALLOC ]
index 5dd9d6a64a7138963f444b26c68e940f2483d39a..426e07d05c7d7c7f853796a1f904cadb202f1cab 100644 (file)
@@ -63,11 +63,6 @@ Sections:
     Flags:           [ SHF_WRITE, SHF_ALLOC ]
     AddressAlign:    0x04
     Size:            0x00
-  - Name:            .reginfo
-    Type:            SHT_MIPS_REGINFO
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x01
-    Size:            0x18
   - Name:            .MIPS.abiflags
     Type:            SHT_MIPS_ABIFLAGS
     Flags:           [ SHF_ALLOC ]
index 339ab97253b63ca9f2edc627624c828838e6c8fb..6f4649121f867ce37cd82c7a5f3cf1bae287714d 100644 (file)
@@ -1,12 +1,12 @@
 # Check reading GP0 value from .MIPS.options section
 #
 # RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor gnu -target mipsel -e G1 -shared -o %t.so %t.o
+# RUN: lld -flavor gnu -target mips64el -e G1 -shared -o %t.so %t.o
 # RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=SYM %s
 # RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=SEC %s
 
 # SYM:      Name: L1 (1)
-# SYM-NEXT: Value: 0xCC
+# SYM-NEXT: Value: 0x134
 # SYM-NEXT: Size: 4
 # SYM-NEXT: Binding: Local (0x0)
 # SYM-NEXT: Type: Function (0x2)
 # SYM-NEXT: Other: 0
 # SYM-NEXT: Section: Absolute (0xFFF1)
 
-# 0xffff80dc == 0x0 (addend) + 0x00cc (L1) + 0x1000 (GP0) - 0x8ff0 (_gp)
+# 0xffff8144 == 0x0 (addend) + 0x0134 (L1) + 0x1000 (GP0) - 0x8ff0 (_gp)
 # SEC:      Contents of section .rodata:
-# SEC-NEXT:  00d4 dc80ffff 00000000 00000000 00000000  ................
+# SEC-NEXT:  013c 4481ffff 00000000 00000000 00000000
 
 !ELF
 FileHeader:
-  Class:    ELFCLASS32
+  Class:    ELFCLASS64
   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 ]
+  Flags:    [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64R2 ]
 Sections:
 - Name:         .text
   Type:         SHT_PROGBITS
@@ -47,7 +46,7 @@ Sections:
   Size:         16
 
 - Name:         .rel.rodata
-  Type:         SHT_REL
+  Type:         SHT_RELA
   Link:         .symtab
   Info:         .rodata
   AddressAlign: 0x04
@@ -60,7 +59,7 @@ Sections:
   Type:         SHT_MIPS_OPTIONS
   Flags:        [ SHF_ALLOC ]
   AddressAlign: 0x01
-  Content:      "0128000000000000000000000000000000000000000000000000000000100000"
+  Content:      "012800000000000000000000000000000000000000000000000000000000000000100000"
 
 Symbols:
   Local:
diff --git a/lld/test/elf/Mips/reginfo-01.test b/lld/test/elf/Mips/reginfo-01.test
new file mode 100644 (file)
index 0000000..5076ef8
--- /dev/null
@@ -0,0 +1,30 @@
+# Check that LLD does not write a .reginfo section if input
+# object file does not contain such section.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.o
+# RUN: llvm-readobj -s %t.so | FileCheck %s
+
+# CHECK-NOT: Name: .reginfo
+
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
diff --git a/lld/test/elf/Mips/reginfo-02.test b/lld/test/elf/Mips/reginfo-02.test
new file mode 100644 (file)
index 0000000..1ab9391
--- /dev/null
@@ -0,0 +1,74 @@
+# Check merging input .reginfo sections.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t1.o %t2.o
+# RUN: llvm-objdump -s -t %t.so | FileCheck %s
+
+# CHECK:      Contents of section .reginfo:
+# CHECK-NEXT:  00b4 f0000001 e0000002 d0000003 c0000004
+# CHECK-NEXT:  00c4 b0000005 f08f0000
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00008ff0 g *ABS* 00000000 _gp
+
+# t1.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      "F0000000E0000000D0000000C0000000B000000000100000"
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+
+# t2.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      "000000010000000200000003000000040000000500000100"
+
+Symbols:
+  Global:
+    - Name:    T1
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+...
diff --git a/lld/test/elf/Mips/reginfo-03.test b/lld/test/elf/Mips/reginfo-03.test
new file mode 100644 (file)
index 0000000..0f5ea0e
--- /dev/null
@@ -0,0 +1,40 @@
+# Check handling a zero-filled input .reginfo section.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.o
+# RUN: llvm-objdump -s -t %t.so | FileCheck %s
+
+# CHECK:      Contents of section .reginfo:
+# CHECK-NEXT:  00b4 00000000 00000000 00000000 00000000
+# CHECK-NEXT:  00c4 00000000 f08f0000
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00008ff0 g *ABS* 00000000 _gp
+
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      "000000000000000000000000000000000000000000000000"
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
diff --git a/lld/test/elf/Mips/reginfo-04.test b/lld/test/elf/Mips/reginfo-04.test
new file mode 100644 (file)
index 0000000..e3bd5f2
--- /dev/null
@@ -0,0 +1,76 @@
+# Check that .reginfo sections from shared libraries do not affect
+# output .reginfo section content.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.so.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t.exe.o
+# RUN: lld -flavor gnu -target mipsel -e T0 -o %t.exe %t.so %t.exe.o
+# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
+
+# CHECK:      Contents of section .reginfo:
+# CHECK-NEXT:  400104 44444444 44444444 44444444 44444444
+# CHECK-NEXT:  400114 44444444 f08f4000
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00408ff0 g *ABS* 00000000 _gp
+
+# t.so.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      "111111111111111111111111111111111111111100100000"
+
+Symbols:
+  Global:
+    - Name:    T1
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+
+# t.exe.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      "444444444444444444444444444444444444444400000000"
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+...
diff --git a/lld/test/elf/Mips/reginfo-05.test b/lld/test/elf/Mips/reginfo-05.test
new file mode 100644 (file)
index 0000000..f421270
--- /dev/null
@@ -0,0 +1,118 @@
+# Check that .reginfo section gets register usage mask from "used" files only.
+# In this test case we take only t2.o from libreginfo.a and should not add
+# register usage masks from t1.o to the output .reginfo section.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
+# RUN: llvm-ar q %T/libreginfo.a %t1.o %t2.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t3.o
+# RUN: lld -flavor gnu -target mipsel -e T0 -o %t.exe %t3.o -L%T -lreginfo
+# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
+
+# CHECK:      Contents of section .reginfo:
+# CHECK-NEXT:  400104 66666666 66666666 66666666 66666666
+# CHECK-NEXT:  400114 66666666 f08f4000
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00408ff0 g *ABS* 00000000 _gp
+
+# t1.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      "111111111111111111111111111111111111111100000000"
+
+Symbols:
+  Global:
+    - Name:    T1
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+
+# t2.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      "222222222222222222222222222222222222222200000000"
+
+Symbols:
+  Global:
+    - Name:    T2
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+
+# t3.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Size:         4
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .rel.text
+  Type:         SHT_REL
+  Info:         .text
+  AddressAlign: 4
+  Relocations:
+    - Offset: 0
+      Symbol: T2
+      Type:   R_MIPS_32
+
+- Name:         .reginfo
+  Type:         SHT_MIPS_REGINFO
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      "444444444444444444444444444444444444444400000000"
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+    - Name:    T2
+...
index dc188ea6825a78a809be04d8a33378c7bbb909ea..84fc3ec5e97df1f20e0d2ee721841a1f65583f93 100644 (file)
@@ -6,20 +6,20 @@
 # RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=SEC %s
 
 # SYM:      Name: L1 (1)
-# SYM-NEXT: Value: 0xCC
+# SYM-NEXT: Value: 0x104
 # SYM-NEXT: Size: 4
 # SYM-NEXT: Binding: Local (0x0)
 # SYM-NEXT: Type: Function (0x2)
 # SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x4)
+# SYM-NEXT: Section: .text (0x5)
 
 # SYM:      Name: G1 (4)
-# SYM-NEXT: Value: 0xD0
+# SYM-NEXT: Value: 0x108
 # SYM-NEXT: Size: 4
 # SYM-NEXT: Binding: Global (0x1)
 # SYM-NEXT: Type: Function (0x2)
 # SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x4)
+# SYM-NEXT: Section: .text (0x5)
 
 # SYM:      Name: _gp (34)
 # SYM-NEXT: Value: 0x8FF0
@@ -29,9 +29,9 @@
 # SYM-NEXT: Other: 0
 # SYM-NEXT: Section: Absolute (0xFFF1)
 
-# 0x160db == 0xffff (addend) + 0x00cc (L1) + 0x01f000 (GP0) - 0x8ff0 (_gp)
+# 0x6113 == 0xffff (addend) + 0x0104 (L1) + 0x01f000 (GP0) - 0x8ff0 (_gp)
 # SEC:      Contents of section .rodata:
-# SEC-NEXT:  00d4 db600008 00000000 00000000 00000000  .`..............
+# SEC-NEXT:  010c 13610008 00000000 00000000 00000000
 
 !ELF
 FileHeader:
index 73ae6f161979caccda2aedff86a132f2fcc267aa..ced53f5f83ecaf3817eb1904862eb9944c9f0cea 100644 (file)
@@ -6,12 +6,12 @@
 # RUN: llvm-objdump -s %t-exe | FileCheck -check-prefix=SEC %s
 
 # SYM:      Name: $L1 (1)
-# SYM-NEXT: Value: 0x400108
+# SYM-NEXT: Value: 0x400140
 # SYM-NEXT: Size: 4
 # SYM-NEXT: Binding: Local (0x0)
 # SYM-NEXT: Type: Function (0x2)
 # SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x5)
+# SYM-NEXT: Section: .text (0x6)
 #
 # SYM:      Name: _gp (212)
 # SYM-NEXT: Value: 0x408FF0
 # SYM-NEXT: Other: 0
 # SYM-NEXT: Section: Absolute (0xFFF1)
 
-# 0x08FF711B == 0x8000001 (addend) + 0x400108 ($L1) +
+# 0x08ff7153 == 0x8000001 (addend) + 0x400140 ($L1) +
 #               0x1000002 (GP0) - 0x408FF0 (_gp)
 # SEC:      Contents of section .rodata:
-# SEC-NEXT:  400118 1b71ff08 00000000 00000000 00000000  .q..............
+# SEC-NEXT:  400150 5371ff08 00000000 00000000 00000000
 
 !ELF
 FileHeader: