summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
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 /lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
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
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp')
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp87
1 files changed, 87 insertions, 0 deletions
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();
+}
OpenPOWER on IntegriCloud