summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
Diffstat (limited to 'lld')
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt1
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h11
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp87
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h34
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsELFReader.h43
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h16
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h13
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp7
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h8
-rw-r--r--lld/test/elf/Mips/e-flags-merge-1.test132
-rw-r--r--lld/test/elf/Mips/e-flags-merge-2.test35
-rw-r--r--lld/test/elf/Mips/e-flags-merge-3.test133
-rw-r--r--lld/test/elf/Mips/e-flags-merge-4.test65
-rw-r--r--lld/test/elf/Mips/e-flags-merge-5.test42
-rw-r--r--lld/test/elf/Mips/e-flags-merge-6.test80
-rw-r--r--lld/test/elf/Mips/e-flags-merge-7.test42
16 files changed, 720 insertions, 29 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
index 7d3f4477897..1b38c6fb458 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
@@ -1,5 +1,6 @@
add_lld_library(lldMipsELFTarget
MipsCtorsOrderPass.cpp
+ MipsELFFlagsMerger.cpp
MipsLinkingContext.cpp
MipsRelocationHandler.cpp
MipsRelocationPass.cpp
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h b/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h
index f62cf98f3c8..3a6df13b09d 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h
@@ -24,7 +24,8 @@ template <class ELFT>
class MipsDynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
public:
MipsDynamicLibraryWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout);
+ MipsTargetLayout<ELFT> &layout,
+ MipsELFFlagsMerger &elfFlagsMerger);
protected:
// Add any runtime files and their atoms to the output
@@ -51,9 +52,11 @@ private:
template <class ELFT>
MipsDynamicLibraryWriter<ELFT>::MipsDynamicLibraryWriter(
- MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
- : DynamicLibraryWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout),
- _mipsContext(ctx), _mipsTargetLayout(layout) {}
+ MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
+ MipsELFFlagsMerger &elfFlagsMerger)
+ : DynamicLibraryWriter<ELFT>(ctx, layout),
+ _writeHelper(ctx, layout, elfFlagsMerger), _mipsContext(ctx),
+ _mipsTargetLayout(layout) {}
template <class ELFT>
bool MipsDynamicLibraryWriter<ELFT>::createImplicitFiles(
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
new file mode 100644
index 00000000000..4db009dd84c
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
@@ -0,0 +1,87 @@
+//===- lib/ReaderWriter/ELF/MipsELFFlagsMerger.cpp ------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsELFFlagsMerger.h"
+#include "lld/Core/Error.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lld;
+using namespace lld::elf;
+
+MipsELFFlagsMerger::MipsELFFlagsMerger() : _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 != llvm::ELF::ELFCLASS32)
+ 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 & llvm::ELF::EF_MIPS_ABI;
+ if (abi != llvm::ELF::EF_MIPS_ABI_O32)
+ return make_dynamic_error_code(Twine("Unsupported ABI"));
+
+ // ... and reduced set of architectures ...
+ uint32_t newArch = newFlags & llvm::ELF::EF_MIPS_ARCH;
+ switch (newArch) {
+ case llvm::ELF::EF_MIPS_ARCH_1:
+ case llvm::ELF::EF_MIPS_ARCH_2:
+ case llvm::ELF::EF_MIPS_ARCH_32:
+ case llvm::ELF::EF_MIPS_ARCH_32R2:
+ case llvm::ELF::EF_MIPS_ARCH_32R6:
+ break;
+ default:
+ return make_dynamic_error_code(Twine("Unsupported architecture"));
+ }
+
+ // ... and still do not support MIPS-16 extension.
+ if (newFlags & llvm::ELF::EF_MIPS_ARCH_ASE_M16)
+ return make_dynamic_error_code(Twine("Unsupported extension: MIPS16"));
+
+ std::lock_guard<std::mutex> lock(_mutex);
+
+ // If the old set of flags is empty, use the new one as a result.
+ if (!_flags) {
+ _flags = newFlags;
+ return std::error_code();
+ }
+
+ // Check PIC / CPIC flags compatibility.
+ uint32_t newPic =
+ newFlags & (llvm::ELF::EF_MIPS_PIC | llvm::ELF::EF_MIPS_CPIC);
+ uint32_t oldPic = _flags & (llvm::ELF::EF_MIPS_PIC | llvm::ELF::EF_MIPS_CPIC);
+
+ if ((newPic != 0) != (oldPic != 0))
+ llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
+
+ if (newPic != 0)
+ _flags |= llvm::ELF::EF_MIPS_CPIC;
+ if (!(newPic & llvm::ELF::EF_MIPS_PIC))
+ _flags &= ~llvm::ELF::EF_MIPS_PIC;
+
+ // Check mixing -mnan=2008 / -mnan=legacy modules.
+ if ((newFlags & llvm::ELF::EF_MIPS_NAN2008) !=
+ (_flags & llvm::ELF::EF_MIPS_NAN2008))
+ return make_dynamic_error_code(
+ Twine("Linking -mnan=2008 and -mnan=legacy modules"));
+
+ // Set the "largest" ISA.
+ uint32_t oldArch = _flags & llvm::ELF::EF_MIPS_ARCH;
+ _flags |= std::max(newArch, oldArch);
+
+ _flags |= newFlags & llvm::ELF::EF_MIPS_NOREORDER;
+ _flags |= newFlags & llvm::ELF::EF_MIPS_MICROMIPS;
+ _flags |= newFlags & llvm::ELF::EF_MIPS_NAN2008;
+
+ return std::error_code();
+}
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h
new file mode 100644
index 00000000000..bed63fa2616
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h
@@ -0,0 +1,34 @@
+//===- lib/ReaderWriter/ELF/MipsELFFlagsMerger.h --------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_FLAGS_MERGER_H
+#define LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_FLAGS_MERGER_H
+
+#include <mutex>
+
+namespace lld {
+namespace elf {
+
+class MipsELFFlagsMerger {
+public:
+ MipsELFFlagsMerger();
+
+ uint32_t getMergedELFFlags() const;
+
+ /// \brief Merge saved ELF header flags and the new set of flags.
+ std::error_code merge(uint8_t newClass, uint32_t newFlags);
+
+private:
+ std::mutex _mutex;
+ uint32_t _flags;
+};
+
+} // namespace elf
+} // namespace lld
+
+#endif
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFReader.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFReader.h
index ef847f44c37..7ccc8124061 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFReader.h
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFReader.h
@@ -11,6 +11,7 @@
#include "ELFReader.h"
#include "MipsELFFile.h"
+#include "MipsELFFlagsMerger.h"
namespace lld {
namespace elf {
@@ -39,18 +40,48 @@ struct MipsDynamicFileCreateELFTraits {
class MipsELFObjectReader
: public ELFObjectReader<Mips32ElELFType, MipsELFFileCreateTraits> {
+ typedef ELFObjectReader<Mips32ElELFType, MipsELFFileCreateTraits>
+ BaseReaderType;
+
public:
- MipsELFObjectReader(bool atomizeStrings)
- : ELFObjectReader<Mips32ElELFType, MipsELFFileCreateTraits>(
- atomizeStrings, llvm::ELF::EM_MIPS) {}
+ MipsELFObjectReader(MipsELFFlagsMerger &flagMerger, bool atomizeStrings)
+ : BaseReaderType(atomizeStrings, llvm::ELF::EM_MIPS),
+ _flagMerger(flagMerger) {}
+
+ std::error_code
+ parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &registry,
+ std::vector<std::unique_ptr<File>> &result) const override {
+ auto &hdr = *elfHeader(*mb);
+ if (std::error_code ec = _flagMerger.merge(hdr.getFileClass(), hdr.e_flags))
+ return ec;
+ return BaseReaderType::parseFile(mb, registry, result);
+ }
+
+private:
+ MipsELFFlagsMerger &_flagMerger;
};
class MipsELFDSOReader
: public ELFDSOReader<Mips32ElELFType, MipsDynamicFileCreateELFTraits> {
+ typedef ELFDSOReader<Mips32ElELFType, MipsDynamicFileCreateELFTraits>
+ BaseReaderType;
+
public:
- MipsELFDSOReader(bool useUndefines)
- : ELFDSOReader<Mips32ElELFType, MipsDynamicFileCreateELFTraits>(
- useUndefines, llvm::ELF::EM_MIPS) {}
+ MipsELFDSOReader(MipsELFFlagsMerger &flagMerger, bool useUndefines)
+ : BaseReaderType(useUndefines, llvm::ELF::EM_MIPS),
+ _flagMerger(flagMerger) {}
+
+ std::error_code
+ parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &registry,
+ std::vector<std::unique_ptr<File>> &result) const override {
+ auto &hdr = *elfHeader(*mb);
+ if (std::error_code ec = _flagMerger.merge(hdr.getFileClass(), hdr.e_flags))
+ return ec;
+ return BaseReaderType::parseFile(mb, registry, result);
+ }
+
+private:
+ MipsELFFlagsMerger &_flagMerger;
};
} // namespace elf
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
index 3b8a397b9c3..f4c4d0817dc 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
@@ -9,6 +9,7 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_WRITERS_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_WRITERS_H
+#include "MipsELFFlagsMerger.h"
#include "MipsLinkingContext.h"
#include "OutputELFWriter.h"
@@ -21,8 +22,10 @@ template <class ELFT> class MipsTargetLayout;
template <typename ELFT> class MipsELFWriter {
public:
- MipsELFWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout)
- : _ctx(ctx), _targetLayout(targetLayout) {}
+ MipsELFWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
+ MipsELFFlagsMerger &elfFlagsMerger)
+ : _ctx(ctx), _targetLayout(targetLayout),
+ _elfFlagsMerger(elfFlagsMerger) {}
void setELFHeader(ELFHeader<ELFT> &elfHeader) {
elfHeader.e_version(1);
@@ -33,13 +36,7 @@ public:
else
elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 0);
- // FIXME (simon): Read elf flags from all inputs, check compatibility,
- // merge them and write result here.
- uint32_t flags = llvm::ELF::EF_MIPS_NOREORDER | llvm::ELF::EF_MIPS_ABI_O32 |
- llvm::ELF::EF_MIPS_CPIC | llvm::ELF::EF_MIPS_ARCH_32R2;
- if (_ctx.getOutputELFType() == llvm::ELF::ET_DYN)
- flags |= EF_MIPS_PIC;
- elfHeader.e_flags(flags);
+ elfHeader.e_flags(_elfFlagsMerger.getMergedELFFlags());
}
void finalizeMipsRuntimeAtomValues() {
@@ -74,6 +71,7 @@ public:
private:
MipsLinkingContext &_ctx;
MipsTargetLayout<ELFT> &_targetLayout;
+ MipsELFFlagsMerger &_elfFlagsMerger;
void setAtomValue(StringRef name, uint64_t value) {
auto atom = _targetLayout.findAbsoluteAtom(name);
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h b/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h
index 85b79d26aa6..0e351b46b2a 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h
@@ -22,7 +22,8 @@ template <typename ELFT> class MipsTargetLayout;
template <class ELFT>
class MipsExecutableWriter : public ExecutableWriter<ELFT> {
public:
- MipsExecutableWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout);
+ MipsExecutableWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
+ MipsELFFlagsMerger &elfFlagsMerger);
protected:
void buildDynamicSymbolTable(const File &file) override;
@@ -50,10 +51,12 @@ private:
};
template <class ELFT>
-MipsExecutableWriter<ELFT>::MipsExecutableWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout)
- : ExecutableWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout),
- _mipsContext(ctx), _mipsTargetLayout(layout) {}
+MipsExecutableWriter<ELFT>::MipsExecutableWriter(
+ MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
+ MipsELFFlagsMerger &elfFlagsMerger)
+ : ExecutableWriter<ELFT>(ctx, layout),
+ _writeHelper(ctx, layout, elfFlagsMerger), _mipsContext(ctx),
+ _mipsTargetLayout(layout) {}
template <class ELFT>
void MipsExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
index 45415ee0820..caec0c4a7e4 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
@@ -27,11 +27,12 @@ MipsTargetHandler::MipsTargetHandler(MipsLinkingContext &ctx)
std::unique_ptr<Writer> MipsTargetHandler::getWriter() {
switch (_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
- return std::unique_ptr<Writer>(
- new MipsExecutableWriter<Mips32ElELFType>(_ctx, *_targetLayout));
+ return std::unique_ptr<Writer>(new MipsExecutableWriter<Mips32ElELFType>(
+ _ctx, *_targetLayout, _elfFlagsMerger));
case llvm::ELF::ET_DYN:
return std::unique_ptr<Writer>(
- new MipsDynamicLibraryWriter<Mips32ElELFType>(_ctx, *_targetLayout));
+ new MipsDynamicLibraryWriter<Mips32ElELFType>(_ctx, *_targetLayout,
+ _elfFlagsMerger));
case llvm::ELF::ET_REL:
llvm_unreachable("TODO: support -r mode");
default:
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
index a34d6d0d065..29b4cd6afc8 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
@@ -10,6 +10,7 @@
#define LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
#include "DefaultTargetHandler.h"
+#include "MipsELFFlagsMerger.h"
#include "MipsELFReader.h"
#include "MipsLinkingContext.h"
#include "MipsRelocationHandler.h"
@@ -108,11 +109,13 @@ public:
}
std::unique_ptr<Reader> getObjReader(bool atomizeStrings) override {
- return std::unique_ptr<Reader>(new MipsELFObjectReader(atomizeStrings));
+ return std::unique_ptr<Reader>(
+ new MipsELFObjectReader(_elfFlagsMerger, atomizeStrings));
}
std::unique_ptr<Reader> getDSOReader(bool useShlibUndefines) override {
- return std::unique_ptr<Reader>(new MipsELFDSOReader(useShlibUndefines));
+ return std::unique_ptr<Reader>(
+ new MipsELFDSOReader(_elfFlagsMerger, useShlibUndefines));
}
const MipsTargetRelocationHandler &getRelocationHandler() const override {
@@ -126,6 +129,7 @@ public:
private:
static const Registry::KindStrings kindStrings[];
MipsLinkingContext &_ctx;
+ MipsELFFlagsMerger _elfFlagsMerger;
std::unique_ptr<MipsRuntimeFile<Mips32ElELFType>> _runtimeFile;
std::unique_ptr<MipsTargetLayout<Mips32ElELFType>> _targetLayout;
std::unique_ptr<MipsTargetRelocationHandler> _relocationHandler;
diff --git a/lld/test/elf/Mips/e-flags-merge-1.test b/lld/test/elf/Mips/e-flags-merge-1.test
new file mode 100644
index 00000000000..f3308daeed4
--- /dev/null
+++ b/lld/test/elf/Mips/e-flags-merge-1.test
@@ -0,0 +1,132 @@
+# Check that the linker shows an error when object file has missed
+# or unsupported ABI and ARCH flags or unsupported ASE flags.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-no-abi.o
+# RUN: not lld -flavor gnu -target mipsel -e T -o %t.exe %t-no-abi.o 2>&1 | \
+# RUN: FileCheck -check-prefix=INVALID-ABI %s
+
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-arch3.o
+# RUN: not lld -flavor gnu -target mipsel -e T -o %t.exe %t-arch3.o 2>&1 | \
+# RUN: FileCheck -check-prefix=INVALID-ARCH %s
+
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-arch4.o
+# RUN: not lld -flavor gnu -target mipsel -e T -o %t.exe %t-arch4.o 2>&1 | \
+# RUN: FileCheck -check-prefix=INVALID-ARCH %s
+
+# RUN: yaml2obj -format=elf -docnum 4 %s > %t-arch64.o
+# RUN: not lld -flavor gnu -target mipsel -e T -o %t.exe %t-arch64.o 2>&1 | \
+# RUN: FileCheck -check-prefix=INVALID-ARCH %s
+
+# RUN: yaml2obj -format=elf -docnum 5 %s > %t-mips16.o
+# RUN: not lld -flavor gnu -target mipsel -e T -o %t.exe %t-mips16.o 2>&1 | \
+# RUN: FileCheck -check-prefix=MIPS16 %s
+
+# INVALID-ABI: Unsupported ABI
+# INVALID-ARCH: Unsupported architecture
+# MIPS16: Unsupported extension: MIPS16
+
+# no-abi.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: []
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T
+ Section: .text
+
+# arch3.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_3]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T
+ Section: .text
+
+# arch4.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_4]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T
+ Section: .text
+
+# arch64.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_64]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T
+ Section: .text
+
+# mips16.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_M16]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T
+ Section: .text
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-2.test b/lld/test/elf/Mips/e-flags-merge-2.test
new file mode 100644
index 00000000000..41d4a0b0c45
--- /dev/null
+++ b/lld/test/elf/Mips/e-flags-merge-2.test
@@ -0,0 +1,35 @@
+# 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 mipsel -e T -o %t.exe %t.o
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK: Flags [ (0x52001001)
+# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
+# CHECK-NEXT: EF_MIPS_ARCH_32 (0x50000000)
+# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
+# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
+# CHECK-NEXT: ]
+
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32,
+ EF_MIPS_NOREORDER, EF_MIPS_MICROMIPS]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T
+ Section: .text
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-3.test b/lld/test/elf/Mips/e-flags-merge-3.test
new file mode 100644
index 00000000000..4551eb1d7fa
--- /dev/null
+++ b/lld/test/elf/Mips/e-flags-merge-3.test
@@ -0,0 +1,133 @@
+# 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 mipsel -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 mipsel -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 mipsel -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 mipsel -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 [ (0x50001000)
+# ABI-CALLS1-NEXT: EF_MIPS_ABI_O32 (0x1000)
+# ABI-CALLS1-NEXT: EF_MIPS_ARCH_32 (0x50000000)
+# ABI-CALLS1-NEXT: ]
+
+# ABI-CALLS2: Flags [ (0x50001004)
+# ABI-CALLS2-NEXT: EF_MIPS_ABI_O32 (0x1000)
+# ABI-CALLS2-NEXT: EF_MIPS_ARCH_32 (0x50000000)
+# ABI-CALLS2-NEXT: EF_MIPS_CPIC (0x4)
+# ABI-CALLS2-NEXT: ]
+
+# CPIC: Flags [ (0x50001004)
+# CPIC-NEXT: EF_MIPS_ABI_O32 (0x1000)
+# CPIC-NEXT: EF_MIPS_ARCH_32 (0x50000000)
+# CPIC-NEXT: EF_MIPS_CPIC (0x4)
+# CPIC-NEXT: ]
+
+# BOTH: Flags [ (0x50001006)
+# BOTH-NEXT: EF_MIPS_ABI_O32 (0x1000)
+# BOTH-NEXT: EF_MIPS_ARCH_32 (0x50000000)
+# BOTH-NEXT: EF_MIPS_CPIC (0x4)
+# BOTH-NEXT: EF_MIPS_PIC (0x2)
+# BOTH-NEXT: ]
+
+# none.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
+
+Symbols:
+ Global:
+ - Name: T1
+ Section: .text
+
+# cpic.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T2
+ Section: .text
+
+# pic.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_PIC]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T3
+ Section: .text
+
+# both.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_PIC]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+Symbols:
+ Global:
+ - Name: T4
+ Section: .text
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-4.test b/lld/test/elf/Mips/e-flags-merge-4.test
new file mode 100644
index 00000000000..096b04d676e
--- /dev/null
+++ b/lld/test/elf/Mips/e-flags-merge-4.test
@@ -0,0 +1,65 @@
+# 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 mipsel -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 [ (0x52001001)
+# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
+# CHECK-NEXT: EF_MIPS_ARCH_32 (0x50000000)
+# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
+# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
+# CHECK-NEXT: ]
+
+# none.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
+
+# noreorder.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_NOREORDER]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+# micro.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_MICROMIPS]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-5.test b/lld/test/elf/Mips/e-flags-merge-5.test
new file mode 100644
index 00000000000..3b5b397ab78
--- /dev/null
+++ b/lld/test/elf/Mips/e-flags-merge-5.test
@@ -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 mipsel -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: 0x04
+ Size: 0x04
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-6.test b/lld/test/elf/Mips/e-flags-merge-6.test
new file mode 100644
index 00000000000..759c8b63c97
--- /dev/null
+++ b/lld/test/elf/Mips/e-flags-merge-6.test
@@ -0,0 +1,80 @@
+# Check selecting ELF header ARCH flag.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-m1.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-m2.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-m32.o
+# RUN: yaml2obj -format=elf -docnum 4 %s > %t-m32r2.o
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so \
+# RUN: %t-m32.o %t-m2.o %t-m32r2.o %t-m1.o
+# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
+
+# CHECK: Flags [ (0x70001000)
+# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
+# CHECK-NEXT: EF_MIPS_ARCH_32R2 (0x70000000)
+# CHECK-NEXT: ]
+
+# m1.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_1]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+# m2.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_2]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+# m32.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
+
+# m32r2.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+...
diff --git a/lld/test/elf/Mips/e-flags-merge-7.test b/lld/test/elf/Mips/e-flags-merge-7.test
new file mode 100644
index 00000000000..7e114ff968f
--- /dev/null
+++ b/lld/test/elf/Mips/e-flags-merge-7.test
@@ -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 mipsel -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: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_NAN2008]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+# legacy.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
+...
OpenPOWER on IntegriCloud