summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2015-06-04 19:21:24 +0000
committerRui Ueyama <ruiu@google.com>2015-06-04 19:21:24 +0000
commit8854d8a6f18dba654d5a55d3749849906a905c30 (patch)
tree6dd36f9f0d7bc6efb0abca4d18b5ea353475db7c
parent2ba7908cf978780b386fa67d30f4e6ecfc36131b (diff)
downloadbcm5719-llvm-8854d8a6f18dba654d5a55d3749849906a905c30.tar.gz
bcm5719-llvm-8854d8a6f18dba654d5a55d3749849906a905c30.zip
COFF: Add /failifmismatch option.
llvm-svn: 239073
-rw-r--r--lld/COFF/Config.h4
-rw-r--r--lld/COFF/Driver.cpp11
-rw-r--r--lld/COFF/Driver.h6
-rw-r--r--lld/COFF/DriverUtils.cpp24
-rw-r--r--lld/test/COFF/failifmismatch.test11
5 files changed, 56 insertions, 0 deletions
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 66ffa65a222..a49906c3141 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -13,6 +13,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/COFF.h"
#include <cstdint>
+#include <map>
#include <set>
#include <string>
@@ -35,6 +36,9 @@ public:
std::set<StringRef> NoDefaultLibs;
bool NoDefaultLibAll = false;
+ // Used by /failifmismatch option.
+ std::map<StringRef, StringRef> MustMatch;
+
uint64_t ImageBase = 0x140000000;
uint64_t StackReserve = 1024 * 1024;
uint64_t StackCommit = 4096;
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 659249f55c4..0700f1aad55 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -110,6 +110,11 @@ LinkerDriver::parseDirectives(StringRef S,
return EC;
std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
+ // Handle /failifmismatch
+ if (auto EC = checkFailIfMismatch(Args.get()))
+ return EC;
+
+ // Handle /defaultlib
for (auto *Arg : Args->filtered(OPT_defaultlib)) {
if (Optional<StringRef> Path = findLib(Arg->getValue())) {
auto FileOrErr = openFile(*Path);
@@ -297,6 +302,12 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
}
}
+ // Handle /failifmismatch
+ if (auto EC = checkFailIfMismatch(Args.get())) {
+ llvm::errs() << "/failifmismatch: " << EC.message() << "\n";
+ return false;
+ }
+
// Create a list of input files. Files can be given as arguments
// for /defaultlib option.
std::vector<StringRef> Inputs;
diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
index 09213c774b6..3186074c376 100644
--- a/lld/COFF/Driver.h
+++ b/lld/COFF/Driver.h
@@ -90,6 +90,12 @@ std::error_code parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor);
std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
uint32_t *Major, uint32_t *Minor);
+// Parses a string in the form of "key=value" and check
+// if value matches previous values for the key.
+// This feature used in the directive section to reject
+// incompatible objects.
+std::error_code checkFailIfMismatch(llvm::opt::InputArgList *Args);
+
// Create enum with OPT_xxx values for each option in Options.td
enum {
OPT_INVALID = 0,
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index 0f58a332df9..0fc6f2f9075 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
+#include "Config.h"
#include "Driver.h"
#include "Error.h"
#include "Memory.h"
@@ -112,6 +113,29 @@ std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
return std::error_code();
}
+// Parses a string in the form of "key=value" and check
+// if value matches previous values for the same key.
+std::error_code checkFailIfMismatch(llvm::opt::InputArgList *Args) {
+ for (auto *Arg : Args->filtered(OPT_failifmismatch)) {
+ StringRef K, V;
+ std::tie(K, V) = StringRef(Arg->getValue()).split('=');
+ if (K.empty() || V.empty()) {
+ llvm::errs() << "/failifmismatch: invalid argument: "
+ << Arg->getValue() << "\n";
+ return make_error_code(LLDError::InvalidOption);
+ }
+ StringRef Existing = Config->MustMatch[K];
+ if (!Existing.empty() && V != Existing) {
+ llvm::errs() << "/failifmismatch: mismatch detected: "
+ << Existing << " and " << V
+ << " for key " << K << "\n";
+ return make_error_code(LLDError::InvalidOption);
+ }
+ Config->MustMatch[K] = V;
+ }
+ return std::error_code();
+}
+
// Create OptTable
// Create prefix string literals used in Options.td
diff --git a/lld/test/COFF/failifmismatch.test b/lld/test/COFF/failifmismatch.test
new file mode 100644
index 00000000000..91a6fbc2b37
--- /dev/null
+++ b/lld/test/COFF/failifmismatch.test
@@ -0,0 +1,11 @@
+# RUN: lld -flavor link2 /entry:main /subsystem:console /out:%t.exe \
+# RUN: %p/Inputs/ret42.obj
+
+# RUN: lld -flavor link2 /entry:main /subsystem:console /out:%t.exe \
+# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k2=v1
+
+# RUN: lld -flavor link2 /entry:main /subsystem:console /out:%t.exe \
+# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v1
+
+# RUN: not lld -flavor link2 /entry:main /subsystem:console /out:%t.exe \
+# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v2
OpenPOWER on IntegriCloud