From 8854d8a6f18dba654d5a55d3749849906a905c30 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 4 Jun 2015 19:21:24 +0000 Subject: [PATCH] COFF: Add /failifmismatch option. llvm-svn: 239073 --- lld/COFF/Config.h | 4 ++++ lld/COFF/Driver.cpp | 11 +++++++++++ lld/COFF/Driver.h | 6 ++++++ lld/COFF/DriverUtils.cpp | 24 ++++++++++++++++++++++++ lld/test/COFF/failifmismatch.test | 11 +++++++++++ 5 files changed, 56 insertions(+) create mode 100644 lld/test/COFF/failifmismatch.test diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 66ffa65..a49906c 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 +#include #include #include @@ -35,6 +36,9 @@ public: std::set NoDefaultLibs; bool NoDefaultLibAll = false; + // Used by /failifmismatch option. + std::map 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 659249f..0700f1a 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -110,6 +110,11 @@ LinkerDriver::parseDirectives(StringRef S, return EC; std::unique_ptr 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 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 Inputs; diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 09213c7..3186074 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 0f58a33..0fc6f2f90 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 0000000..91a6fbc --- /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 -- 2.7.4