summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Atanasyan <simon@atanasyan.com>2014-11-06 05:53:10 +0000
committerSimon Atanasyan <simon@atanasyan.com>2014-11-06 05:53:10 +0000
commitb915d07a8e62839ca745a48fc54d2c7ed793ebcd (patch)
tree325a59a03a613970db9f69766b32611b0e8f0d5c
parent4c6bd6a10d06be042837df9004d7a5afc5ebca70 (diff)
downloadbcm5719-llvm-b915d07a8e62839ca745a48fc54d2c7ed793ebcd.tar.gz
bcm5719-llvm-b915d07a8e62839ca745a48fc54d2c7ed793ebcd.zip
[Mips] Check ELF flags to prevent linking of incompatible files
1. The path checks ELF header flags to prevent linking of incompatible files. For example we do not allow to link files with different ABI, -mnan flags, some combination of target CPU etc. 2. The patch merge ELF header flags from input object files to put their combination to the generated file. For example, if some input files have EF_MIPS_NOREORDER flag we need to put this flag to the output file header. I use the `parseFile()` (not `canParse()`) method because in case of recognition of incorrect input flags combination we should show detailed error message and stop the linking process and should not try to use another `Reader`. llvm-svn: 221439
-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