[Mips] Teach LLD to recognize one more MIPS target triple - mips64el
authorSimon Atanasyan <simon@atanasyan.com>
Sun, 25 Jan 2015 19:15:35 +0000 (19:15 +0000)
committerSimon Atanasyan <simon@atanasyan.com>
Sun, 25 Jan 2015 19:15:35 +0000 (19:15 +0000)
This is initial patch to support MIPS64 object files linking.
The patch just makes some classes more generalized, and rejects
attempts to interlinking O32 and N64 ABI object files.

I try to reuse the current MIPS target related classes as much as
possible because O32 and N64 MIPS ABI are tightly related and share
almost the same set of relocations, GOT, flags etc.

llvm-svn: 227058

24 files changed:
lld/lib/Driver/GnuLdDriver.cpp
lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h
lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
lld/test/elf/Mips/base-address-64.test [new file with mode: 0644]
lld/test/elf/Mips/dynlib-fileheader-64.test [new file with mode: 0644]
lld/test/elf/Mips/dynlib-fileheader-micro-64.test [new file with mode: 0644]
lld/test/elf/Mips/e-flags-merge-1-64.test [new file with mode: 0644]
lld/test/elf/Mips/e-flags-merge-2-64.test [new file with mode: 0644]
lld/test/elf/Mips/e-flags-merge-3-64.test [new file with mode: 0644]
lld/test/elf/Mips/e-flags-merge-4-64.test [new file with mode: 0644]
lld/test/elf/Mips/e-flags-merge-5-64.test [new file with mode: 0644]
lld/test/elf/Mips/e-flags-merge-6-64.test [new file with mode: 0644]
lld/test/elf/Mips/e-flags-merge-7-64.test [new file with mode: 0644]
lld/test/elf/Mips/exe-fileheader-64.test [new file with mode: 0644]
lld/test/elf/Mips/exe-fileheader-micro-64.test [new file with mode: 0644]
lld/test/elf/Mips/interpreter-64.test [new file with mode: 0644]

index 67d0e68..8d655a5 100644 (file)
@@ -186,8 +186,11 @@ getArchType(const llvm::Triple &triple, StringRef value) {
       return llvm::Triple::x86_64;
     return llvm::None;
   case llvm::Triple::mipsel:
+  case llvm::Triple::mips64el:
     if (value == "elf32ltsmip")
       return llvm::Triple::mipsel;
+    if (value == "elf64ltsmip")
+      return llvm::Triple::mips64el;
     return llvm::None;
   case llvm::Triple::aarch64:
     if (value == "aarch64linux")
index 058173c..446ac90 100644 (file)
@@ -80,6 +80,7 @@ uint16_t ELFLinkingContext::getOutputMachine() const {
   case llvm::Triple::hexagon:
     return llvm::ELF::EM_HEXAGON;
   case llvm::Triple::mipsel:
+  case llvm::Triple::mips64el:
     return llvm::ELF::EM_MIPS;
   case llvm::Triple::ppc:
     return llvm::ELF::EM_PPC;
index 1e7b41d..595f9c2 100644 (file)
@@ -57,19 +57,22 @@ static bool matchMipsISA(unsigned base, unsigned ext) {
   return false;
 }
 
-MipsELFFlagsMerger::MipsELFFlagsMerger() : _flags(0) {}
+MipsELFFlagsMerger::MipsELFFlagsMerger(bool is64Bits)
+    : _is64Bit(is64Bits), _flags(0) {}
 
 uint32_t MipsELFFlagsMerger::getMergedELFFlags() const { return _flags; }
 
 std::error_code MipsELFFlagsMerger::merge(uint8_t newClass, uint32_t newFlags) {
-  // Reject 64-bit binaries.
-  if (newClass != ELFCLASS32)
+  // Check bitness.
+  if (_is64Bit != (newClass == ELFCLASS64))
     return make_dynamic_error_code(
         Twine("Bitness is incompatible with that of the selected target"));
 
-  // We support the only ABI - O32 ...
-  uint32_t abi = newFlags & EF_MIPS_ABI;
-  if (abi != EF_MIPS_ABI_O32)
+  // We support two ABI: O32 and N64. The last one does not have
+  // the corresponding ELF flag.
+  uint32_t inAbi = newFlags & EF_MIPS_ABI;
+  uint32_t supportedAbi = _is64Bit ? 0 : EF_MIPS_ABI_O32;
+  if (inAbi != supportedAbi)
     return make_dynamic_error_code(Twine("Unsupported ABI"));
 
   // ... and reduced set of architectures ...
index 1067f97..6ade86f 100644 (file)
@@ -17,7 +17,7 @@ namespace elf {
 
 class MipsELFFlagsMerger {
 public:
-  MipsELFFlagsMerger();
+  MipsELFFlagsMerger(bool is64Bits);
 
   uint32_t getMergedELFFlags() const;
 
@@ -25,6 +25,7 @@ public:
   std::error_code merge(uint8_t newClass, uint32_t newFlags);
 
 private:
+  const bool _is64Bit;
   std::mutex _mutex;
   uint32_t _flags;
 };
index 2982423..2b05c16 100644 (file)
@@ -18,15 +18,29 @@ using namespace lld::elf;
 
 std::unique_ptr<ELFLinkingContext>
 MipsLinkingContext::create(llvm::Triple triple) {
-  if (triple.getArch() == llvm::Triple::mipsel)
-    return std::unique_ptr<ELFLinkingContext>(
-             new MipsLinkingContext(triple));
+  if (triple.getArch() == llvm::Triple::mipsel ||
+      triple.getArch() == llvm::Triple::mips64el)
+    return std::unique_ptr<ELFLinkingContext>(new MipsLinkingContext(triple));
   return nullptr;
 }
 
+typedef std::unique_ptr<TargetHandlerBase> TargetHandlerBasePtr;
+
+static TargetHandlerBasePtr createTarget(llvm::Triple triple,
+                                         MipsLinkingContext &ctx) {
+  switch (triple.getArch()) {
+  case llvm::Triple::mipsel:
+    return TargetHandlerBasePtr(new MipsTargetHandler<Mips32ELType>(ctx));
+  case llvm::Triple::mips64el:
+    return TargetHandlerBasePtr(new MipsTargetHandler<Mips64ELType>(ctx));
+  default:
+    llvm_unreachable("Unhandled arch");
+  }
+}
+
 MipsLinkingContext::MipsLinkingContext(llvm::Triple triple)
-    : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
-                                    new MipsTargetHandler(*this))) {}
+    : ELFLinkingContext(triple, createTarget(triple, *this)),
+      _flagsMerger(triple.isArch64Bit()) {}
 
 uint32_t MipsLinkingContext::getMergedELFFlags() const {
   return _flagsMerger.getMergedELFFlags();
@@ -38,7 +52,7 @@ MipsELFFlagsMerger &MipsLinkingContext::getELFFlagsMerger() {
 
 uint64_t MipsLinkingContext::getBaseAddress() const {
   if (_baseAddress == 0 && getOutputELFType() == llvm::ELF::ET_EXEC)
-    return 0x400000;
+    return getTriple().isArch64Bit() ? 0x120000000 : 0x400000;
   return _baseAddress;
 }
 
@@ -49,7 +63,7 @@ StringRef MipsLinkingContext::entrySymbolName() const {
 }
 
 StringRef MipsLinkingContext::getDefaultInterpreter() const {
-  return "/lib/ld.so.1";
+  return getTriple().isArch64Bit() ? "/lib64/ld.so.1" : "/lib/ld.so.1";
 }
 
 void MipsLinkingContext::addPasses(PassManager &pm) {
index 38231a5..cdedd3a 100644 (file)
@@ -33,9 +33,8 @@ enum {
   LLD_R_MICROMIPS_GLOBAL_26_S1 = 1030,
 };
 
-typedef llvm::object::ELFType<llvm::support::little, 2, false> Mips32ElELFType;
-
-template <class ELFType> class MipsTargetLayout;
+typedef llvm::object::ELFType<llvm::support::little, 2, false> Mips32ELType;
+typedef llvm::object::ELFType<llvm::support::little, 2, true> Mips64ELType;
 
 class MipsLinkingContext final : public ELFLinkingContext {
 public:
index 5d118f8..5765ce1 100644 (file)
@@ -188,17 +188,38 @@ static uint32_t microShuffle(uint32_t ins) {
   return ((ins & 0xffff) << 16) | ((ins & 0xffff0000) >> 16);
 }
 
-std::error_code MipsTargetRelocationHandler::applyRelocation(
+namespace {
+
+template <class ELFT> class RelocationHandler : public TargetRelocationHandler {
+public:
+  RelocationHandler(MipsLinkingContext &ctx) : _ctx(ctx) {}
+
+  std::error_code applyRelocation(ELFWriter &writer,
+                                  llvm::FileOutputBuffer &buf,
+                                  const lld::AtomLayout &atom,
+                                  const Reference &ref) const override;
+
+private:
+  MipsLinkingContext &_ctx;
+
+  MipsTargetLayout<ELFT> &getTargetLayout() const {
+    return static_cast<MipsTargetLayout<ELFT> &>(
+        _ctx.getTargetHandler<ELFT>().getTargetLayout());
+  }
+};
+
+template <class ELFT>
+std::error_code RelocationHandler<ELFT>::applyRelocation(
     ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
     const Reference &ref) const {
   if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
     return std::error_code();
   assert(ref.kindArch() == Reference::KindArch::Mips);
 
-  AtomLayout *gpAtom = _mipsTargetLayout.getGP();
+  AtomLayout *gpAtom = getTargetLayout().getGP();
   uint64_t gpAddr = gpAtom ? gpAtom->_virtualAddr : 0;
 
-  AtomLayout *gpDispAtom = _mipsTargetLayout.getGPDisp();
+  AtomLayout *gpDispAtom = getTargetLayout().getGPDisp();
   bool isGpDisp = gpDispAtom && ref.target() == gpDispAtom->_atom;
 
   uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
@@ -349,3 +370,19 @@ std::error_code MipsTargetRelocationHandler::applyRelocation(
   endian::write<uint32_t, little, 2>(location, ins);
   return std::error_code();
 }
+
+} // end anon namespace
+
+template <>
+std::unique_ptr<TargetRelocationHandler>
+lld::elf::createMipsRelocationHandler<Mips32ELType>(MipsLinkingContext &ctx) {
+  return std::unique_ptr<TargetRelocationHandler>(
+      new RelocationHandler<Mips32ELType>(ctx));
+}
+
+template <>
+std::unique_ptr<TargetRelocationHandler>
+lld::elf::createMipsRelocationHandler<Mips64ELType>(MipsLinkingContext &ctx) {
+  return std::unique_ptr<TargetRelocationHandler>(
+      new RelocationHandler<Mips64ELType>(ctx));
+}
index fb4f755..b70dfa2 100644 (file)
@@ -9,25 +9,15 @@
 #ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_RELOCATION_HANDLER_H
 #define LLD_READER_WRITER_ELF_MIPS_MIPS_RELOCATION_HANDLER_H
 
-#include "MipsLinkingContext.h"
-
 namespace lld {
 namespace elf {
 
-class MipsTargetHandler;
-
-class MipsTargetRelocationHandler final : public TargetRelocationHandler {
-public:
-  MipsTargetRelocationHandler(MipsTargetLayout<Mips32ElELFType> &layout)
-      : _mipsTargetLayout(layout) {}
-
-  std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
-                                  const lld::AtomLayout &,
-                                  const Reference &) const override;
+class MipsLinkingContext;
+class TargetRelocationHandler;
 
-private:
-  MipsTargetLayout<Mips32ElELFType> &_mipsTargetLayout;
-};
+template <class ELFT>
+std::unique_ptr<TargetRelocationHandler>
+createMipsRelocationHandler(MipsLinkingContext &ctx);
 
 } // elf
 } // lld
index e4e6c10..6f30f5f 100644 (file)
@@ -949,12 +949,23 @@ RelocationPass<ELFT>::getObjectEntry(const SharedLibraryAtom *a) {
 
 } // end anon namespace
 
+static std::unique_ptr<Pass> createPass(MipsLinkingContext &ctx) {
+  switch (ctx.getTriple().getArch()) {
+  case llvm::Triple::mipsel:
+    return std::unique_ptr<Pass>(new RelocationPass<Mips32ELType>(ctx));
+  case llvm::Triple::mips64el:
+    return std::unique_ptr<Pass>(new RelocationPass<Mips64ELType>(ctx));
+  default:
+    llvm_unreachable("Unhandled arch");
+  }
+}
+
 std::unique_ptr<Pass>
 lld::elf::createMipsRelocationPass(MipsLinkingContext &ctx) {
   switch (ctx.getOutputELFType()) {
   case llvm::ELF::ET_EXEC:
   case llvm::ELF::ET_DYN:
-    return std::unique_ptr<Pass>(new RelocationPass<Mips32ElELFType>(ctx));
+    return createPass(ctx);
   case llvm::ELF::ET_REL:
     return std::unique_ptr<Pass>();
   default:
index ed80a48..408c56b 100644 (file)
@@ -7,43 +7,19 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ELFFile.h"
-#include "MipsDynamicLibraryWriter.h"
-#include "MipsExecutableWriter.h"
-#include "MipsLinkingContext.h"
 #include "MipsTargetHandler.h"
 
 using namespace lld;
 using namespace elf;
 
-MipsTargetHandler::MipsTargetHandler(MipsLinkingContext &ctx)
-    : _ctx(ctx), _runtimeFile(new MipsRuntimeFile<Mips32ElELFType>(ctx)),
-      _targetLayout(new MipsTargetLayout<Mips32ElELFType>(ctx)),
-      _relocationHandler(new MipsTargetRelocationHandler(*_targetLayout)) {}
-
-std::unique_ptr<Writer> MipsTargetHandler::getWriter() {
-  switch (_ctx.getOutputELFType()) {
-  case llvm::ELF::ET_EXEC:
-    return std::unique_ptr<Writer>(
-        new MipsExecutableWriter<Mips32ElELFType>(_ctx, *_targetLayout));
-  case llvm::ELF::ET_DYN:
-    return std::unique_ptr<Writer>(
-        new MipsDynamicLibraryWriter<Mips32ElELFType>(_ctx, *_targetLayout));
-  case llvm::ELF::ET_REL:
-    llvm_unreachable("TODO: support -r mode");
-  default:
-    llvm_unreachable("unsupported output type");
-  }
-}
-
-void MipsTargetHandler::registerRelocationNames(Registry &registry) {
+void MipsRelocationStringTable::registerTable(Registry &registry) {
   registry.addKindTable(Reference::KindNamespace::ELF,
                         Reference::KindArch::Mips, kindStrings);
 }
 
 #define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
 
-const Registry::KindStrings MipsTargetHandler::kindStrings[] = {
+const Registry::KindStrings MipsRelocationStringTable::kindStrings[] = {
 #include "llvm/Support/ELFRelocs/Mips.def"
   LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT),
   LLD_KIND_STRING_ENTRY(LLD_R_MIPS_32_HI16),
index b8f91ea..056f418 100644 (file)
@@ -10,7 +10,9 @@
 #define LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
 
 #include "DefaultTargetHandler.h"
+#include "MipsDynamicLibraryWriter.h"
 #include "MipsELFReader.h"
+#include "MipsExecutableWriter.h"
 #include "MipsLinkingContext.h"
 #include "MipsRelocationHandler.h"
 #include "MipsSectionChunks.h"
@@ -81,39 +83,63 @@ public:
       : CRuntimeFile<ELFType>(ctx, "Mips runtime file") {}
 };
 
+/// \brief Auxiliary class holds relocation's names table.
+class MipsRelocationStringTable {
+  static const Registry::KindStrings kindStrings[];
+
+public:
+  static void registerTable(Registry &registry);
+};
+
 /// \brief TargetHandler for Mips
-class MipsTargetHandler final : public DefaultTargetHandler<Mips32ElELFType> {
+template <class ELFT>
+class MipsTargetHandler final : public DefaultTargetHandler<ELFT> {
 public:
-  MipsTargetHandler(MipsLinkingContext &ctx);
+  MipsTargetHandler(MipsLinkingContext &ctx)
+      : _ctx(ctx), _runtimeFile(new MipsRuntimeFile<ELFT>(ctx)),
+        _targetLayout(new MipsTargetLayout<ELFT>(ctx)),
+        _relocationHandler(createMipsRelocationHandler<ELFT>(ctx)) {}
 
-  MipsTargetLayout<Mips32ElELFType> &getTargetLayout() override {
-    return *_targetLayout;
-  }
+  MipsTargetLayout<ELFT> &getTargetLayout() override { return *_targetLayout; }
 
   std::unique_ptr<Reader> getObjReader(bool atomizeStrings) override {
     return std::unique_ptr<Reader>(
-        new MipsELFObjectReader<Mips32ElELFType>(_ctx, atomizeStrings));
+        new MipsELFObjectReader<ELFT>(_ctx, atomizeStrings));
   }
 
   std::unique_ptr<Reader> getDSOReader(bool useShlibUndefines) override {
     return std::unique_ptr<Reader>(
-        new MipsELFDSOReader<Mips32ElELFType>(_ctx, useShlibUndefines));
+        new MipsELFDSOReader<ELFT>(_ctx, useShlibUndefines));
   }
 
-  const MipsTargetRelocationHandler &getRelocationHandler() const override {
+  const TargetRelocationHandler &getRelocationHandler() const override {
     return *_relocationHandler;
   }
 
-  std::unique_ptr<Writer> getWriter() override;
+  std::unique_ptr<Writer> getWriter() override {
+    switch (_ctx.getOutputELFType()) {
+    case llvm::ELF::ET_EXEC:
+      return std::unique_ptr<Writer>(
+          new MipsExecutableWriter<ELFT>(_ctx, *_targetLayout));
+    case llvm::ELF::ET_DYN:
+      return std::unique_ptr<Writer>(
+          new MipsDynamicLibraryWriter<ELFT>(_ctx, *_targetLayout));
+    case llvm::ELF::ET_REL:
+      llvm_unreachable("TODO: support -r mode");
+    default:
+      llvm_unreachable("unsupported output type");
+    }
+  }
 
-  void registerRelocationNames(Registry &registry) override;
+  void registerRelocationNames(Registry &registry) override {
+    MipsRelocationStringTable::registerTable(registry);
+  }
 
 private:
-  static const Registry::KindStrings kindStrings[];
   MipsLinkingContext &_ctx;
-  std::unique_ptr<MipsRuntimeFile<Mips32ElELFType>> _runtimeFile;
-  std::unique_ptr<MipsTargetLayout<Mips32ElELFType>> _targetLayout;
-  std::unique_ptr<MipsTargetRelocationHandler> _relocationHandler;
+  std::unique_ptr<MipsRuntimeFile<ELFT>> _runtimeFile;
+  std::unique_ptr<MipsTargetLayout<ELFT>> _targetLayout;
+  std::unique_ptr<TargetRelocationHandler> _relocationHandler;
 };
 
 template <class ELFT> class MipsSymbolTable : public SymbolTable<ELFT> {
diff --git a/lld/test/elf/Mips/base-address-64.test b/lld/test/elf/Mips/base-address-64.test
new file mode 100644 (file)
index 0000000..07110e7
--- /dev/null
@@ -0,0 +1,78 @@
+# Check executable base address configuration. Base address should be
+# equal to 0x400000 and the MIPS_BASE_ADDRESS dynamic tag's value should
+# be the same.
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mips64el --noinhibit-exec -o %t.exe %t.o
+# RUN: llvm-readobj -dynamic-table -program-headers %t.exe | FileCheck %s
+
+# CHECK: DynamicSection [ (13 entries)
+# CHECK:        Tag                Type                 Name/Value
+# CHECK-NEXT:   0x0000000000000004 HASH                 0x{{[0-9A-F]+}}
+# CHECK-NEXT:   0x0000000000000005 STRTAB               0x{{[0-9A-F]+}}
+# CHECK-NEXT:   0x0000000000000006 SYMTAB               0x{{[0-9A-F]+}}
+# CHECK-NEXT:   0x000000000000000A STRSZ                1 (bytes)
+# CHECK-NEXT:   0x000000000000000B SYMENT               24 (bytes)
+# CHECK-NEXT:   0x0000000070000001 MIPS_RLD_VERSION     1
+# CHECK-NEXT:   0x0000000070000005 MIPS_FLAGS           NOTPOT
+# CHECK-NEXT:   0x0000000070000006 MIPS_BASE_ADDRESS    0x120000000
+# CHECK-NEXT:   0x000000007000000A MIPS_LOCAL_GOTNO     2
+# CHECK-NEXT:   0x0000000070000011 MIPS_SYMTABNO        1
+# CHECK-NEXT:   0x0000000070000013 MIPS_GOTSYM          0x1
+# CHECK-NEXT:   0x0000000000000003 PLTGOT               0x120001000
+# CHECK-NEXT:   0x0000000000000000 NULL                 0x0
+# CHECK-NEXT: ]
+
+# CHECK:   ProgramHeaders [
+# CHECK:     ProgramHeader {
+# CHECK:       Type: PT_PHDR (0x6)
+# CHECK:       Offset: 0x40
+# CHECK:       VirtualAddress: 0x{{[0-9A-F]+}}
+# CHECK:     }
+# CHECK:     ProgramHeader {
+# CHECK:       Type: PT_INTERP (0x3)
+# CHECK:       Offset: 0x190
+# CHECK:       VirtualAddress: 0x{{[0-9A-F]+}}
+# CHECK:     }
+# CHECK:     ProgramHeader {
+# CHECK:       Type: PT_LOAD (0x1)
+# CHECK-NEXT:  Offset: 0x0
+# CHECK-NEXT:  VirtualAddress: 0x120000000
+
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+                     EF_MIPS_ARCH_64R2 ]
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+  - Name:          .data
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:  0x10
+    Size:          0x00
+  - Name:          .bss
+    Type:          SHT_NOBITS
+    Flags:         [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:  0x10
+    Size:          0x00
+
+Symbols:
+  Local:
+    - Name:        .text
+      Type:        STT_SECTION
+      Section:     .text
+    - Name:        .data
+      Type:        STT_SECTION
+      Section:     .data
+    - Name:        .bss
+      Type:        STT_SECTION
+      Section:     .bss
+  Global:
+    - Name:        main
+      Section:     .text
diff --git a/lld/test/elf/Mips/dynlib-fileheader-64.test b/lld/test/elf/Mips/dynlib-fileheader-64.test
new file mode 100644 (file)
index 0000000..206f4fa
--- /dev/null
@@ -0,0 +1,72 @@
+# Check ELF Header for 64-bit shared library.
+
+# Build shared library
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t.o
+# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
+
+# CHECK: Format: ELF64-mips
+# CHECK: Arch: mips64el
+# CHECK: AddressSize: 64bit
+# CHECK: LoadName:
+# CHECK: ElfHeader {
+# CHECK:   Ident {
+# CHECK:     Magic: (7F 45 4C 46)
+# CHECK:     Class: 64-bit (0x2)
+# CHECK:     DataEncoding: LittleEndian (0x1)
+# CHECK:     FileVersion: 1
+# CHECK:     OS/ABI: SystemV (0x0)
+# CHECK:     ABIVersion: 0
+# CHECK:     Unused: (00 00 00 00 00 00 00)
+# CHECK:   }
+# CHECK:   Type: SharedObject (0x3)
+# CHECK:   Machine: EM_MIPS (0x8)
+# CHECK:   Version: 1
+# CHECK:   Entry: 0x170
+# CHECK:   ProgramHeaderOffset: 0x40
+# CHECK:   SectionHeaderOffset: 0x2140
+# CHECK:   Flags [ (0x80000006)
+# CHECK:     EF_MIPS_ARCH_64R2 (0x80000000)
+# CHECK:     EF_MIPS_CPIC (0x4)
+# CHECK:     EF_MIPS_PIC (0x2)
+# CHECK:   ]
+# CHECK:   HeaderSize: 64
+# CHECK:   ProgramHeaderEntrySize: 56
+# CHECK:   ProgramHeaderCount: 4
+# CHECK:   SectionHeaderEntrySize: 64
+# CHECK:   SectionHeaderCount: 11
+# CHECK:   StringTableSectionIndex: 8
+# CHECK: }
+
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64R2 ]
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+  - Name:          .data
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Local:
+    - Name:        .text
+      Type:        STT_SECTION
+      Section:     .text
+    - Name:        .data
+      Type:        STT_SECTION
+      Section:     .data
+  Global:
+    - Name:        data
+      Type:        STT_OBJECT
+      Section:     .data
+      Size:        0x04
+...
diff --git a/lld/test/elf/Mips/dynlib-fileheader-micro-64.test b/lld/test/elf/Mips/dynlib-fileheader-micro-64.test
new file mode 100644 (file)
index 0000000..c03a951
--- /dev/null
@@ -0,0 +1,75 @@
+# Check ELF Header for shared library in case of microMIPS symbols.
+
+# Build shared library
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t.o
+# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
+
+# CHECK:      Format: ELF64-mips
+# CHECK-NEXT: Arch: mips64el
+# CHECK-NEXT: AddressSize: 64bit
+# CHECK-NEXT: LoadName:
+# CHECK-NEXT: ElfHeader {
+# CHECK-NEXT:   Ident {
+# CHECK-NEXT:    Magic: (7F 45 4C 46)
+# CHECK-NEXT:    Class: 64-bit (0x2)
+# CHECK-NEXT:    DataEncoding: LittleEndian (0x1)
+# CHECK-NEXT:    FileVersion: 1
+# CHECK-NEXT:    OS/ABI: SystemV (0x0)
+# CHECK-NEXT:    ABIVersion: 0
+# CHECK-NEXT:    Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT:  }
+# CHECK-NEXT:  Type: SharedObject (0x3)
+# CHECK-NEXT:  Machine: EM_MIPS (0x8)
+# CHECK-NEXT:  Version: 1
+# CHECK-NEXT:  Entry: 0x170
+# CHECK-NEXT:  ProgramHeaderOffset: 0x40
+# CHECK-NEXT:  SectionHeaderOffset: 0x2140
+# CHECK-NEXT:  Flags [ (0x82000007)
+# CHECK-NEXT:    EF_MIPS_ARCH_64R2 (0x80000000)
+# CHECK-NEXT:    EF_MIPS_CPIC (0x4)
+# CHECK-NEXT:    EF_MIPS_MICROMIPS (0x2000000)
+# CHECK-NEXT:    EF_MIPS_NOREORDER (0x1)
+# CHECK-NEXT:    EF_MIPS_PIC (0x2)
+# CHECK-NEXT:  ]
+# CHECK-NEXT:  HeaderSize: 64
+# CHECK-NEXT:  ProgramHeaderEntrySize: 56
+# CHECK-NEXT:  ProgramHeaderCount: 4
+# CHECK-NEXT:  SectionHeaderEntrySize: 64
+# CHECK-NEXT:  SectionHeaderCount: 11
+# CHECK-NEXT:  StringTableSectionIndex: 8
+# CHECK-NEXT:}
+
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+                     EF_MIPS_MICROMIPS, EF_MIPS_ARCH_64R2 ]
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+  - Name:          .data
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Local:
+    - Name:        .text
+      Type:        STT_SECTION
+      Section:     .text
+    - Name:        .data
+      Type:        STT_SECTION
+      Section:     .data
+  Global:
+    - Name:        foo
+      Type:        STT_FUNC
+      Section:     .text
+      Size:        0x08
+      Other:       [ STO_MIPS_MICROMIPS ]
diff --git a/lld/test/elf/Mips/e-flags-merge-1-64.test b/lld/test/elf/Mips/e-flags-merge-1-64.test
new file mode 100644 (file)
index 0000000..d571953
--- /dev/null
@@ -0,0 +1,30 @@
+# Check that the linker shows an error when object
+# file has unsupported ASE flags.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-mips16.o
+# RUN: not lld -flavor gnu -target mips64el -e T -o %t.exe %t-mips16.o 2>&1 | \
+# RUN:   FileCheck -check-prefix=MIPS16 %s
+
+# MIPS16: Unsupported extension: MIPS16
+
+# mips16.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64, EF_MIPS_ARCH_ASE_M16]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Global:
+    - Name:        T
+      Section:     .text
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-2-64.test b/lld/test/elf/Mips/e-flags-merge-2-64.test
new file mode 100644 (file)
index 0000000..a169e7e
--- /dev/null
@@ -0,0 +1,33 @@
+# Check that the linker copies ELF header flags from the single input object
+# file to the generated executable
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mips64el -e T -o %t.exe %t.o
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK:      Flags [ (0x62000001)
+# CHECK-NEXT:   EF_MIPS_ARCH_64 (0x60000000)
+# CHECK-NEXT:   EF_MIPS_MICROMIPS (0x2000000)
+# CHECK-NEXT:   EF_MIPS_NOREORDER (0x1)
+# CHECK-NEXT: ]
+
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_ARCH_64, EF_MIPS_NOREORDER, EF_MIPS_MICROMIPS ]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Global:
+    - Name:        T
+      Section:     .text
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-3-64.test b/lld/test/elf/Mips/e-flags-merge-3-64.test
new file mode 100644 (file)
index 0000000..54065a6
--- /dev/null
@@ -0,0 +1,130 @@
+# Check PIC/CPIC flags merging in case of multiple input objects.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-none.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-cpic.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-pic.o
+# RUN: yaml2obj -format=elf -docnum 4 %s > %t-both.o
+
+# RUN: lld -flavor gnu -target mips64el -e T1 -o %t-abi1.exe \
+# RUN:     %t-none.o %t-pic.o 2>&1 | FileCheck -check-prefix=ABI-CALLS-WARN %s
+# RUN: llvm-readobj -file-headers %t-abi1.exe \
+# RUN:              | FileCheck -check-prefix=ABI-CALLS1 %s
+
+# RUN: lld -flavor gnu -target mips64el -e T1 -o %t-abi2.exe \
+# RUN:     %t-cpic.o %t-none.o 2>&1 | FileCheck -check-prefix=ABI-CALLS-WARN %s
+# RUN: llvm-readobj -file-headers %t-abi2.exe \
+# RUN:              | FileCheck -check-prefix=ABI-CALLS2 %s
+
+# RUN: lld -flavor gnu -target mips64el -e T2 -o %t-cpic.exe %t-cpic.o %t-pic.o
+# RUN: llvm-readobj -file-headers %t-cpic.exe | FileCheck -check-prefix=CPIC %s
+
+# RUN: lld -flavor gnu -target mips64el -e T3 -o %t-both.exe %t-pic.o %t-both.o
+# RUN: llvm-readobj -file-headers %t-both.exe | FileCheck -check-prefix=BOTH %s
+
+# ABI-CALLS-WARN: lld warning: linking abicalls and non-abicalls files
+
+# ABI-CALLS1:      Flags [ (0x60000004)
+# ABI-CALLS1-NEXT:   EF_MIPS_ARCH_64 (0x60000000)
+# ABI-CALLS1-NEXT:   EF_MIPS_CPIC (0x4)
+# ABI-CALLS1-NEXT: ]
+
+# ABI-CALLS2:      Flags [ (0x60000004)
+# ABI-CALLS2-NEXT:   EF_MIPS_ARCH_64 (0x60000000)
+# ABI-CALLS2-NEXT:   EF_MIPS_CPIC (0x4)
+# ABI-CALLS2-NEXT: ]
+
+# CPIC:      Flags [ (0x60000004)
+# CPIC-NEXT:   EF_MIPS_ARCH_64 (0x60000000)
+# CPIC-NEXT:   EF_MIPS_CPIC (0x4)
+# CPIC-NEXT: ]
+
+# BOTH:      Flags [ (0x60000006)
+# BOTH-NEXT:   EF_MIPS_ARCH_64 (0x60000000)
+# BOTH-NEXT:   EF_MIPS_CPIC (0x4)
+# BOTH-NEXT:   EF_MIPS_PIC (0x2)
+# BOTH-NEXT: ]
+
+# none.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Global:
+    - Name:        T1
+      Section:     .text
+
+# cpic.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64, EF_MIPS_CPIC]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Global:
+    - Name:        T2
+      Section:     .text
+
+# pic.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64, EF_MIPS_PIC]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Global:
+    - Name:        T3
+      Section:     .text
+
+# both.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64, EF_MIPS_CPIC, EF_MIPS_PIC]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Global:
+    - Name:        T4
+      Section:     .text
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-4-64.test b/lld/test/elf/Mips/e-flags-merge-4-64.test
new file mode 100644 (file)
index 0000000..9ffa613
--- /dev/null
@@ -0,0 +1,64 @@
+# Check ELF flags merging.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-none.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-noreorder.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-micro.o
+
+# RUN: lld -flavor gnu -target mips64el -shared -o %t.so \
+# RUN:     %t-none.o %t-noreorder.o %t-micro.o
+# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
+
+# CHECK:      Flags [ (0x82000001)
+# CHECK-NEXT:   EF_MIPS_ARCH_64R2 (0x80000000)
+# CHECK-NEXT:   EF_MIPS_MICROMIPS (0x2000000)
+# CHECK-NEXT:   EF_MIPS_NOREORDER (0x1)
+# CHECK-NEXT: ]
+
+# none.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_5]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+# noreorder.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64, EF_MIPS_NOREORDER]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+# micro.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64R2, EF_MIPS_MICROMIPS]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-5-64.test b/lld/test/elf/Mips/e-flags-merge-5-64.test
new file mode 100644 (file)
index 0000000..e629aed
--- /dev/null
@@ -0,0 +1,42 @@
+# Check that LLD does not allow to mix 32 and 64-bit MIPS object files.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-32.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-64.o
+
+# RUN: not lld -flavor gnu -target mips64el -shared -o %t.so \
+# RUN:         %t-32.o %t-64.o 2>&1 | FileCheck %s
+
+# CHECK: Bitness is incompatible with that of the selected target
+
+# 32.o
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x04
+    Size:          0x04
+
+# 64.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-6-64.test b/lld/test/elf/Mips/e-flags-merge-6-64.test
new file mode 100644 (file)
index 0000000..fbc32b7
--- /dev/null
@@ -0,0 +1,79 @@
+# Check selecting ELF header ARCH flag.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-m3.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-m5.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-m64.o
+# RUN: yaml2obj -format=elf -docnum 4 %s > %t-m64r2.o
+
+# RUN: lld -flavor gnu -target mips64el -shared -o %t.so \
+# RUN:     %t-m64.o %t-m5.o %t-m64r2.o %t-m3.o
+# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
+
+# CHECK:      Flags [ (0x80000000)
+# CHECK-NEXT:   EF_MIPS_ARCH_64R2 (0x80000000)
+# CHECK-NEXT: ]
+
+# m3.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_3]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+# m5.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_5]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+# m64.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+# m64r2.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64R2]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-7-64.test b/lld/test/elf/Mips/e-flags-merge-7-64.test
new file mode 100644 (file)
index 0000000..07ed6bb
--- /dev/null
@@ -0,0 +1,42 @@
+# Check that LLD does not allow to mix nan2008 and legacy MIPS object files.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-2008.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-legacy.o
+
+# RUN: not lld -flavor gnu -target mips64el -shared -o %t.so \
+# RUN:         %t-2008.o %t-legacy.o 2>&1 | FileCheck %s
+
+# CHECK: Linking -mnan=2008 and -mnan=legacy modules
+
+# 2008.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64, EF_MIPS_NAN2008]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+# legacy.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [EF_MIPS_ARCH_64]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+...
diff --git a/lld/test/elf/Mips/exe-fileheader-64.test b/lld/test/elf/Mips/exe-fileheader-64.test
new file mode 100644 (file)
index 0000000..b4b5934
--- /dev/null
@@ -0,0 +1,66 @@
+# Check ELF Header for 64-bit executable file.
+
+# Build executable
+# RUN: yaml2obj -format=elf %s > %t-o.o
+# RUN: lld -flavor gnu -target mips64el -e glob -o %t.exe %t-o.o
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK: Format: ELF64-mips
+# CHECK: Arch: mips64el
+# CHECK: AddressSize: 64bit
+# CHECK: LoadName:
+# CHECK: ElfHeader {
+# CHECK:   Ident {
+# CHECK:     Magic: (7F 45 4C 46)
+# CHECK:     Class: 64-bit (0x2)
+# CHECK:     DataEncoding: LittleEndian (0x1)
+# CHECK:     FileVersion: 1
+# CHECK:     OS/ABI: SystemV (0x0)
+# CHECK:     ABIVersion: 0
+# CHECK:     Unused: (00 00 00 00 00 00 00)
+# CHECK:   }
+# CHECK:   Type: Executable (0x2)
+# CHECK:   Machine: EM_MIPS (0x8)
+# CHECK:   Version: 1
+# CHECK:   Entry: 0x1200001A0
+# CHECK:   ProgramHeaderOffset: 0x40
+# CHECK:   SectionHeaderOffset: 0x12F8
+# CHECK:   Flags [ (0x60000007)
+# CHECK:     EF_MIPS_ARCH_64 (0x60000000)
+# CHECK:     EF_MIPS_CPIC (0x4)
+# CHECK:     EF_MIPS_NOREORDER (0x1)
+# CHECK:     EF_MIPS_PIC (0x2)
+# CHECK:   ]
+# CHECK:   HeaderSize: 64
+# CHECK:   ProgramHeaderEntrySize: 56
+# CHECK:   ProgramHeaderCount: 5
+# CHECK:   SectionHeaderEntrySize: 64
+# CHECK:   SectionHeaderCount: 11
+# CHECK:   StringTableSectionIndex: 8
+# CHECK: }
+
+# o.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+                     EF_MIPS_ARCH_64 ]
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Local:
+    - Name:        .text
+      Type:        STT_SECTION
+      Section:     .text
+  Global:
+    - Name:        glob
+      Section:     .text
+...
diff --git a/lld/test/elf/Mips/exe-fileheader-micro-64.test b/lld/test/elf/Mips/exe-fileheader-micro-64.test
new file mode 100644 (file)
index 0000000..90aa127
--- /dev/null
@@ -0,0 +1,68 @@
+# Check ELF Header for 64-bit executable file in case of microMIPS entry symbol.
+
+# Build executable
+# RUN: yaml2obj -format=elf %s > %t-o.o
+# RUN: lld -flavor gnu -target mips64el -e glob -o %t.exe %t-o.o
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK: Format: ELF64-mips
+# CHECK: Arch: mips64el
+# CHECK: AddressSize: 64bit
+# CHECK: LoadName:
+# CHECK: ElfHeader {
+# CHECK:   Ident {
+# CHECK:     Magic: (7F 45 4C 46)
+# CHECK:     Class: 64-bit (0x2)
+# CHECK:     DataEncoding: LittleEndian (0x1)
+# CHECK:     FileVersion: 1
+# CHECK:     OS/ABI: SystemV (0x0)
+# CHECK:     ABIVersion: 0
+# CHECK:     Unused: (00 00 00 00 00 00 00)
+# CHECK:   }
+# CHECK:   Type: Executable (0x2)
+# CHECK:   Machine: EM_MIPS (0x8)
+# CHECK:   Version: 1
+# CHECK:   Entry: 0x1200001A1
+# CHECK:   ProgramHeaderOffset: 0x40
+# CHECK:   SectionHeaderOffset: 0x12F8
+# CHECK:   Flags [ (0x82000007)
+# CHECK:     EF_MIPS_ARCH_64R2 (0x80000000)
+# CHECK:     EF_MIPS_CPIC (0x4)
+# CHECK:     EF_MIPS_MICROMIPS (0x2000000)
+# CHECK:     EF_MIPS_NOREORDER (0x1)
+# CHECK:     EF_MIPS_PIC (0x2)
+# CHECK:   ]
+# CHECK:   HeaderSize: 64
+# CHECK:   ProgramHeaderEntrySize: 56
+# CHECK:   ProgramHeaderCount: 5
+# CHECK:   SectionHeaderEntrySize: 64
+# CHECK:   SectionHeaderCount: 11
+# CHECK:   StringTableSectionIndex: 8
+# CHECK: }
+
+# o.o
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+                     EF_MIPS_MICROMIPS, EF_MIPS_ARCH_64R2 ]
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  0x10
+    Size:          0x08
+
+Symbols:
+  Local:
+    - Name:        .text
+      Type:        STT_SECTION
+      Section:     .text
+  Global:
+    - Name:        glob
+      Section:     .text
+      Other:       [ STO_MIPS_MICROMIPS ]
+...
diff --git a/lld/test/elf/Mips/interpreter-64.test b/lld/test/elf/Mips/interpreter-64.test
new file mode 100644 (file)
index 0000000..3ece3e6
--- /dev/null
@@ -0,0 +1,26 @@
+# Check program interpreter setup.
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mips64el -e main -o %t.exe %t.o
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: Contents of section .interp:
+# CHECK-NEXT: {{[0-9a-f]+}} 2f6c6962 36342f6c 642e736f 2e3100 /lib64/ld.so.1.
+
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64 ]
+
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x10
+    Size:            0x08
+
+Symbols:
+  Global:
+    - Name:            main
+      Section:         .text