[lld] r246334 - [Mips] Initial support of the MIPS N32 ABI

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 28 14:39:00 PDT 2015


Author: atanasyan
Date: Fri Aug 28 16:39:00 2015
New Revision: 246334

URL: http://llvm.org/viewvc/llvm-project?rev=246334&view=rev
Log:
[Mips] Initial support of the MIPS N32 ABI

Added:
    lld/trunk/test/elf/Mips/e-flags-merge-12.test
    lld/trunk/test/elf/Mips/exe-fileheader-n32.test
    lld/trunk/test/elf/Mips/interpreter-n32.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp Fri Aug 28 16:39:00 2015
@@ -489,6 +489,21 @@ MipsAbiInfoHandler<ELFT>::getAbiFlags()
   return sec;
 }
 
+template <class ELFT> MipsAbi MipsAbiInfoHandler<ELFT>::getAbi() const {
+  if (!_abiFlags.hasValue())
+    return ELFT::Is64Bits ? MipsAbi::N64 : MipsAbi::O32;
+  switch (_abiFlags->_abi & (EF_MIPS_ABI_O32 | EF_MIPS_ABI2)) {
+  case EF_MIPS_ABI_O32:
+    return MipsAbi::O32;
+  case EF_MIPS_ABI2:
+    return MipsAbi::N32;
+  case 0:
+    return MipsAbi::N64;
+  default:
+    llvm_unreachable("Unknown ABI flag");
+  }
+}
+
 template <class ELFT>
 std::error_code
 MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags,
@@ -499,11 +514,15 @@ MipsAbiInfoHandler<ELFT>::mergeFlags(uin
   if (auto ec = abiFlags.getError())
     return ec;
 
-  // We support two ABI: O32 and N64. The last one does not have
+  // We support three ABI: O32, N32, and N64. The last one does not have
   // the corresponding ELF flag.
-  uint32_t supportedAbi = ELFT::Is64Bits ? 0 : uint32_t(EF_MIPS_ABI_O32);
-  if (abiFlags->_abi != supportedAbi)
-    return make_dynamic_error_code("Unsupported ABI");
+  if (ELFT::Is64Bits) {
+    if (abiFlags->_abi)
+      return make_dynamic_error_code("Unsupported ABI");
+  } else {
+    if (!(abiFlags->_abi & (EF_MIPS_ABI_O32 | EF_MIPS_ABI2)))
+      return make_dynamic_error_code("Unsupported ABI");
+  }
 
   // ... and still do not support MIPS-16 extension.
   if (abiFlags->_ases & AFL_ASE_MIPS16)
@@ -520,6 +539,10 @@ MipsAbiInfoHandler<ELFT>::mergeFlags(uin
     return std::error_code();
   }
 
+  // Check ABI compatibility.
+  if (abiFlags->_abi != _abiFlags->_abi)
+    return make_dynamic_error_code("Linking modules with incompatible ABI");
+
   // Check PIC / CPIC flags compatibility.
   if (abiFlags->_isCPic != _abiFlags->_isCPic)
     llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
@@ -614,7 +637,7 @@ MipsAbiInfoHandler<ELFT>::createAbiFromH
     return ec;
   abi._ases = *ases;
   abi._flags1 = 0;
-  abi._abi = flags & EF_MIPS_ABI;
+  abi._abi = flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
   abi._isPic = flags & EF_MIPS_PIC;
   abi._isCPic = flags & EF_MIPS_CPIC;
   abi._isNoReorder = flags & EF_MIPS_NOREORDER;

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h Fri Aug 28 16:39:00 2015
@@ -18,6 +18,8 @@
 namespace lld {
 namespace elf {
 
+enum class MipsAbi { O32, N32, N64 };
+
 struct MipsAbiFlags {
   unsigned _isa = 0;
   unsigned _fpAbi = 0;
@@ -53,6 +55,8 @@ public:
   llvm::Optional<Elf_Mips_RegInfo> getRegistersMask() const;
   llvm::Optional<Elf_Mips_ABIFlags> getAbiFlags() const;
 
+  MipsAbi getAbi() const;
+
   /// \brief Merge saved ELF header flags and the new set of flags.
   std::error_code mergeFlags(uint32_t newFlags,
                              const Elf_Mips_ABIFlags *newAbi);

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp Fri Aug 28 16:39:00 2015
@@ -46,9 +46,16 @@ MipsLinkingContext::MipsLinkingContext(l
     : ELFLinkingContext(triple, createTarget(triple, *this)) {}
 
 uint64_t MipsLinkingContext::getBaseAddress() const {
-  if (_baseAddress == 0 && getOutputELFType() == llvm::ELF::ET_EXEC)
-    return getTriple().isArch64Bit() ? 0x120000000 : 0x400000;
-  return _baseAddress;
+  if (_baseAddress != 0 || getOutputELFType() != llvm::ELF::ET_EXEC)
+    return _baseAddress;
+  switch (getAbi()) {
+    case MipsAbi::O32:
+      return 0x0400000;
+    case MipsAbi::N32:
+      return 0x10000000;
+    case MipsAbi::N64:
+      return 0x120000000;
+  }
 }
 
 StringRef MipsLinkingContext::entrySymbolName() const {
@@ -58,7 +65,14 @@ StringRef MipsLinkingContext::entrySymbo
 }
 
 StringRef MipsLinkingContext::getDefaultInterpreter() const {
-  return getTriple().isArch64Bit() ? "/lib64/ld.so.1" : "/lib/ld.so.1";
+  switch (getAbi()) {
+    case MipsAbi::O32:
+      return "/lib/ld.so.1";
+    case MipsAbi::N32:
+      return "/lib32/ld.so.1";
+    case MipsAbi::N64:
+      return "/lib64/ld.so.1";
+  }
 }
 
 void MipsLinkingContext::addPasses(PassManager &pm) {
@@ -124,6 +138,11 @@ bool MipsLinkingContext::isRelativeReloc
   }
 }
 
+MipsAbi MipsLinkingContext::getAbi() const {
+  auto &handler = static_cast<MipsBaseTargetHandler &>(getTargetHandler());
+  return handler.getAbi();
+}
+
 const Registry::KindStrings kindStrings[] = {
 #define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
 #include "llvm/Support/ELFRelocs/Mips.def"

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h Fri Aug 28 16:39:00 2015
@@ -9,6 +9,7 @@
 #ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
 #define LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
 
+#include "MipsAbiInfoHandler.h"
 #include "lld/ReaderWriter/ELFLinkingContext.h"
 
 namespace lld {
@@ -45,6 +46,8 @@ public:
   bool isCopyRelocation(const Reference &r) const override;
   bool isPLTRelocation(const Reference &r) const override;
   bool isRelativeReloc(const Reference &r) const override;
+
+  MipsAbi getAbi() const;
 };
 
 } // elf

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=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Fri Aug 28 16:39:00 2015
@@ -61,6 +61,30 @@ static const uint8_t mipsLePlt0AtomConte
   0xfe, 0xff, 0x18, 0x27  // subu  $24, $24, 2
 };
 
+// N32 big-endian PLT0 entry
+static const uint8_t mipsN32BePlt0AtomContent[] = {
+  0x3c, 0x0e, 0x00, 0x00, // lui   $14, %hi(&GOTPLT[0])
+  0x8d, 0xd9, 0x00, 0x00, // lw    $25, %lo(&GOTPLT[0])($14)
+  0x25, 0xce, 0x00, 0x00, // addiu $14, $14, %lo(&GOTPLT[0])
+  0x03, 0x0e, 0xc0, 0x23, // subu  $24, $24, $14
+  0x03, 0xe0, 0x78, 0x25, // move  $15, $31
+  0x00, 0x18, 0xc0, 0x82, // srl   $24, $24, 2
+  0x03, 0x20, 0xf8, 0x09, // jalr  $25
+  0x27, 0x18, 0xff, 0xfe  // subu  $24, $24, 2
+};
+
+// N32 little-endian PLT0 entry
+static const uint8_t mipsN32LePlt0AtomContent[] = {
+  0x00, 0x00, 0x0e, 0x3c, // lui   $14, %hi(&GOTPLT[0])
+  0x00, 0x00, 0xd9, 0x8d, // lw    $25, %lo(&GOTPLT[0])($14)
+  0x00, 0x00, 0xce, 0x25, // addiu $14, $14, %lo(&GOTPLT[0])
+  0x23, 0xc0, 0x0e, 0x03, // subu  $24, $24, $14
+  0x25, 0x78, 0xe0, 0x03, // move  $15, $31
+  0x82, 0xc0, 0x18, 0x00, // srl   $24, $24, 2
+  0x09, 0xf8, 0x20, 0x03, // jalr  $25
+  0xfe, 0xff, 0x18, 0x27  // subu  $24, $24, 2
+};
+
 // microMIPS big-endian PLT0 entry
 static const uint8_t microMipsBePlt0AtomContent[] = {
   0x79, 0x80, 0x00, 0x00, // addiupc $3,  (&GOTPLT[0]) - .
@@ -285,6 +309,27 @@ template <> ArrayRef<uint8_t> PLT0Atom<E
   return llvm::makeArrayRef(mipsLePlt0AtomContent);
 }
 
+template <class ELFT> class PLT0N32Atom : public PLTAtom {
+public:
+  PLT0N32Atom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
+    // Setup reference to fixup the PLT0 entry.
+    addReferenceELF_Mips(R_MIPS_HI16, 0, got, 0);
+    addReferenceELF_Mips(R_MIPS_LO16, 4, got, 0);
+    addReferenceELF_Mips(R_MIPS_LO16, 8, got, 0);
+  }
+
+  ArrayRef<uint8_t> rawContent() const override {
+    llvm_unreachable("PLT0 is not applicable for this target");
+  }
+};
+
+template <> ArrayRef<uint8_t> PLT0N32Atom<ELF32BE>::rawContent() const {
+  return llvm::makeArrayRef(mipsN32BePlt0AtomContent);
+}
+template <> ArrayRef<uint8_t> PLT0N32Atom<ELF32LE>::rawContent() const {
+  return llvm::makeArrayRef(mipsN32LePlt0AtomContent);
+}
+
 template <class ELFT> class PLT0MicroAtom : public PLTAtom {
 public:
   PLT0MicroAtom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
@@ -1253,6 +1298,8 @@ PLTAtom *RelocationPass<ELFT>::createPLT
 
   if (isMicroMips)
     return new (_file._alloc) PLT0MicroAtom<ELFT>(ga0, _file);
+  if (_ctx.getAbi() == MipsAbi::N32)
+    return new (_file._alloc) PLT0N32Atom<ELFT>(ga0, _file);
   return new (_file._alloc) PLT0Atom<ELFT>(ga0, _file);
 }
 

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=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp Fri Aug 28 16:39:00 2015
@@ -53,6 +53,10 @@ std::unique_ptr<Writer> MipsTargetHandle
   }
 }
 
+template <class ELFT> MipsAbi MipsTargetHandler<ELFT>::getAbi() const {
+  return _abiInfoHandler.getAbi();
+}
+
 template class MipsTargetHandler<ELF32BE>;
 template class MipsTargetHandler<ELF32LE>;
 template class MipsTargetHandler<ELF64BE>;

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h Fri Aug 28 16:39:00 2015
@@ -17,8 +17,14 @@
 namespace lld {
 namespace elf {
 
+class MipsBaseTargetHandler : public TargetHandler {
+public:
+  virtual MipsAbi getAbi() const = 0;
+};
+
 /// \brief TargetHandler for Mips
-template <class ELFT> class MipsTargetHandler final : public TargetHandler {
+template <class ELFT>
+class MipsTargetHandler final : public MipsBaseTargetHandler {
 public:
   MipsTargetHandler(MipsLinkingContext &ctx);
 
@@ -28,6 +34,7 @@ public:
   std::unique_ptr<Reader> getDSOReader() override;
   const TargetRelocationHandler &getRelocationHandler() const override;
   std::unique_ptr<Writer> getWriter() override;
+  MipsAbi getAbi() const override;
 
 private:
   MipsLinkingContext &_ctx;

Added: lld/trunk/test/elf/Mips/e-flags-merge-12.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/e-flags-merge-12.test?rev=246334&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/e-flags-merge-12.test (added)
+++ lld/trunk/test/elf/Mips/e-flags-merge-12.test Fri Aug 28 16:39:00 2015
@@ -0,0 +1,44 @@
+# Check that LLD shows an error and does not link files with O32 and N32 ABIs.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o32.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-n32.o
+
+# RUN: not lld -flavor gnu -target mipsel -shared -o %t.so \
+# RUN:         %t-o32.o %t-n32.o 2>&1 | FileCheck %s
+
+# CHECK: Linking modules with incompatible ABI
+
+# o32.o
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+                    EF_MIPS_32BITMODE, EF_MIPS_ARCH_64]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x04
+    Size:          0x04
+
+# n32.o
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI2,
+                    EF_MIPS_ARCH_64]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x04
+    Size:          0x04
+...

Added: lld/trunk/test/elf/Mips/exe-fileheader-n32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/exe-fileheader-n32.test?rev=246334&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/exe-fileheader-n32.test (added)
+++ lld/trunk/test/elf/Mips/exe-fileheader-n32.test Fri Aug 28 16:39:00 2015
@@ -0,0 +1,65 @@
+# Check ELF Header for N32 ABI executable file.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mipsel -o %t.exe %t.o
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK:      Format: ELF32-mips
+# CHECK-NEXT: Arch: mipsel
+# CHECK-NEXT: AddressSize: 32bit
+# CHECK-NEXT: LoadName:
+# CHECK-NEXT: ElfHeader {
+# CHECK-NEXT:   Ident {
+# CHECK-NEXT:     Magic: (7F 45 4C 46)
+# CHECK-NEXT:     Class: 32-bit
+# CHECK-NEXT:     DataEncoding: LittleEndian
+# CHECK-NEXT:     FileVersion: 1
+# CHECK-NEXT:     OS/ABI: SystemV
+# CHECK-NEXT:     ABIVersion: 0
+# CHECK-NEXT:     Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Type: Executable
+# CHECK-NEXT:   Machine: EM_MIPS
+# CHECK-NEXT:   Version: 1
+# CHECK-NEXT:   Entry: 0x10000130
+# CHECK-NEXT:   ProgramHeaderOffset: 0x34
+# CHECK-NEXT:   SectionHeaderOffset: 0x22C0
+# CHECK-NEXT:   Flags [ (0x60000027)
+# CHECK-NEXT:     EF_MIPS_ABI2
+# CHECK-NEXT:     EF_MIPS_ARCH_64
+# CHECK-NEXT:     EF_MIPS_CPIC
+# CHECK-NEXT:     EF_MIPS_NOREORDER
+# CHECK-NEXT:     EF_MIPS_PIC
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   HeaderSize: 52
+# CHECK-NEXT:   ProgramHeaderEntrySize: 32
+# CHECK-NEXT:   ProgramHeaderCount: {{[0-9]+}}
+# CHECK-NEXT:   SectionHeaderEntrySize: 40
+# CHECK-NEXT:   SectionHeaderCount: {{[0-9]+}}
+# CHECK-NEXT:   StringTableSectionIndex: {{[0-9]+}}
+# CHECK-NEXT: }
+
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+                     EF_MIPS_ABI2, EF_MIPS_ARCH_64 ]
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  16
+    Size:          8
+
+Symbols:
+  Local:
+    - Name:        .text
+      Type:        STT_SECTION
+      Section:     .text
+  Global:
+    - Name:        __start
+      Section:     .text
+...

Added: lld/trunk/test/elf/Mips/interpreter-n32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/interpreter-n32.test?rev=246334&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/interpreter-n32.test (added)
+++ lld/trunk/test/elf/Mips/interpreter-n32.test Fri Aug 28 16:39:00 2015
@@ -0,0 +1,27 @@
+# Check program interpreter setup in case of N32 ABI.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mipsel -o %t.exe %t.o
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: Contents of section .interp:
+# CHECK-NEXT: {{[0-9a-f ]+}} /lib32/ld.so.1.
+
+FileHeader:
+  Class:    ELFCLASS32
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_MIPS
+  Flags:    [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64, EF_MIPS_ABI2 ]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  16
+    Size:          8
+
+Symbols:
+  Global:
+    - Name:     __start
+      Section:   .text




More information about the llvm-commits mailing list