From: Peter Collingbourne Date: Thu, 2 Jul 2015 01:48:12 +0000 (+0000) Subject: Driver: add support for linking the UBSan runtime library on Windows. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=939db774136a3fbf065993704340659fabc00f74;p=clang Driver: add support for linking the UBSan runtime library on Windows. On Windows the user may invoke the linker directly, so we might not have an opportunity to add runtime library flags to the linker command line. Instead, instruct the code generator to embed linker directive in the object file that cause the required runtime libraries to be linked. We might also want to do something similar for ASan, but it seems to have its own special complexities which may make this infeasible. Differential Revision: http://reviews.llvm.org/D10862 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@241225 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index ceba912dad..11bfd417e1 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_DRIVER_SANITIZERARGS_H #include "clang/Basic/Sanitizers.h" +#include "clang/Driver/Types.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include @@ -54,8 +55,8 @@ class SanitizerArgs { bool requiresPIE() const; bool needsUnwindTables() const; bool linkCXXRuntimes() const { return LinkCXXRuntimes; } - void addArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; + void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const; private: void clear(); diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index e203aac582..3043481c71 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// #include "clang/Driver/SanitizerArgs.h" +#include "Tools.h" #include "clang/Basic/Sanitizers.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" @@ -533,8 +534,9 @@ static std::string toString(const clang::SanitizerSet &Sanitizers) { return Res; } -void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const { +void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, + types::ID InputType) const { if (Sanitizers.empty()) return; CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers))); @@ -581,6 +583,17 @@ void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args, // affect compilation. if (Sanitizers.has(Memory) || Sanitizers.has(Address)) CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new")); + + if (TC.getTriple().isOSWindows() && needsUbsanRt()) { + // Instruct the code generator to embed linker directives in the object file + // that cause the required runtime libraries to be linked. + CmdArgs.push_back(Args.MakeArgString( + "--dependent-lib=" + tools::getCompilerRT(TC, "ubsan_standalone"))); + if (types::isCXX(InputType)) + CmdArgs.push_back( + Args.MakeArgString("--dependent-lib=" + + tools::getCompilerRT(TC, "ubsan_standalone_cxx"))); + } } SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index bb56c659e8..05b0e08c1d 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -2231,10 +2231,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, // Until ARM libraries are build separately, we have them all in one library static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) { - // FIXME: handle 64-bit - if (TC.getTriple().isOSWindows() && - !TC.getTriple().isWindowsItaniumEnvironment()) - return "i386"; if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb) return "arm"; return TC.getArchName(); @@ -2251,8 +2247,8 @@ static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) { return Res; } -static SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component, - bool Shared = false) { +SmallString<128> tools::getCompilerRT(const ToolChain &TC, StringRef Component, + bool Shared) { const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android ? "-android" : ""; @@ -3927,7 +3923,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); - Sanitize.addArgs(Args, CmdArgs); + Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType); // Report an error for -faltivec on anything other than PowerPC. if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) { diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index d57df1c7b8..0cc7e6417a 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -37,6 +37,9 @@ class Compiler; using llvm::opt::ArgStringList; +SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component, + bool Shared = false); + /// \brief Clang compiler tool. class LLVM_LIBRARY_VISIBILITY Clang : public Tool { public: diff --git a/test/Driver/cl-link.c b/test/Driver/cl-link.c index 5bd2001179..78936136f7 100644 --- a/test/Driver/cl-link.c +++ b/test/Driver/cl-link.c @@ -11,7 +11,7 @@ // LINK: "bar" // LINK: "baz" -// RUN: %clang_cl /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN %s +// RUN: %clang_cl -m32 /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN %s // ASAN: link.exe // ASAN: "-debug" // ASAN: "-incremental:no" @@ -19,7 +19,7 @@ // ASAN: "{{.*}}clang_rt.asan_cxx-i386.lib" // ASAN: "{{.*}}cl-link{{.*}}.obj" -// RUN: %clang_cl /MD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-MD %s +// RUN: %clang_cl -m32 /MD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-MD %s // ASAN-MD: link.exe // ASAN-MD: "-debug" // ASAN-MD: "-incremental:no" @@ -33,8 +33,8 @@ // DLL: link.exe // "-dll" -// RUN: %clang_cl /LD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s -// RUN: %clang_cl /LDd /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s +// RUN: %clang_cl -m32 /LD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s +// RUN: %clang_cl -m32 /LDd /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s // ASAN-DLL: link.exe // ASAN-DLL: "-dll" // ASAN-DLL: "-debug" diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index b473e86bf2..96d0781016 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -16,6 +16,15 @@ // RUN: %clang -target i386-unknown-openbsd -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-OPENBSD // CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} +// RUN: %clang -target i386-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 +// RUN: %clang -target i386-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 --check-prefix=CHECK-UNDEFINED-WIN-CXX +// RUN: %clang -target x86_64-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN64 +// RUN: %clang -target x86_64-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN64 --check-prefix=CHECK-UNDEFINED-WIN-CXX +// CHECK-UNDEFINED-WIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} +// CHECK-UNDEFINED-WIN32-SAME: "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib" +// CHECK-UNDEFINED-WIN64-SAME: "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib" +// CHECK-UNDEFINED-WIN-CXX-SAME: "--dependent-lib={{[^"]*}}ubsan_standalone_cxx{{[^"]*}}.lib" + // RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER // CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent),?){5}"}}