From aea92e530df12c6766fff852ca5a9381f5cdcef5 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Mon, 3 Dec 2012 13:20:43 +0000 Subject: [PATCH] Add -fsanitize=memory. llvm-svn: 169124 --- .../clang/Basic/DiagnosticDriverKinds.td | 2 ++ clang/include/clang/Basic/Sanitizers.def | 3 +++ clang/lib/CodeGen/BackendUtil.cpp | 12 +++++++++ clang/lib/Driver/SanitizerArgs.h | 2 ++ clang/lib/Driver/Tools.cpp | 26 +++++++++++++++++++ 5 files changed, 45 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 4b430351756a..4a37ea78371e 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -101,6 +101,8 @@ def err_drv_mg_requires_m_or_mm : Error< "option '-MG' requires '-M' or '-MM'">; def err_drv_asan_android_requires_pie : Error< "AddressSanitizer on Android requires '-pie'">; +def err_drv_sanitizer_requires_pie : Error< + "%select{Thread|Memory}0Sanitizer requires '-pie'">; def err_drv_unknown_objc_runtime : Error< "unknown or ill-formed Objective-C runtime '%0'">; diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index 5b6df6f2c1b1..57ca6eb1858a 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -48,6 +48,9 @@ SANITIZER("use-after-scope", UseAfterScope) SANITIZER_GROUP("address-full", AddressFull, Address | InitOrder | UseAfterReturn | UseAfterScope) +// MemorySanitizer +SANITIZER("memory", Memory) + // ThreadSanitizer SANITIZER("thread", Thread) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index a5cc2ea00415..4fe1c80e48ac 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -179,6 +179,11 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, PM.add(createAddressSanitizerModulePass(LangOpts.SanitizeInitOrder)); } +static void addMemorySanitizerPass(const PassManagerBuilder &Builder, + PassManagerBase &PM) { + PM.add(createMemorySanitizerPass()); +} + static void addThreadSanitizerPass(const PassManagerBuilder &Builder, PassManagerBase &PM) { PM.add(createThreadSanitizerPass()); @@ -227,6 +232,13 @@ void EmitAssemblyHelper::CreatePasses(TargetMachine *TM) { addAddressSanitizerPasses); } + if (LangOpts.SanitizeMemory) { + PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, + addMemorySanitizerPass); + PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, + addMemorySanitizerPass); + } + if (LangOpts.SanitizeThread) { PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addThreadSanitizerPass); diff --git a/clang/lib/Driver/SanitizerArgs.h b/clang/lib/Driver/SanitizerArgs.h index af92fa070c31..c7d1ea68dd47 100644 --- a/clang/lib/Driver/SanitizerArgs.h +++ b/clang/lib/Driver/SanitizerArgs.h @@ -30,6 +30,7 @@ class SanitizerArgs { #include "clang/Basic/Sanitizers.def" NeedsAsanRt = AddressFull, NeedsTsanRt = Thread, + NeedsMsanRt = Memory, NeedsUbsanRt = (Undefined & ~Bounds) | Integer }; unsigned Kind; @@ -41,6 +42,7 @@ class SanitizerArgs { bool needsAsanRt() const { return Kind & NeedsAsanRt; } bool needsTsanRt() const { return Kind & NeedsTsanRt; } + bool needsMsanRt() const { return Kind & NeedsMsanRt; } bool needsUbsanRt() const { return Kind & NeedsUbsanRt; } bool sanitizesVptr() const { return Kind & Vptr; } diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 16218e1fc542..92c96b25c955 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1524,6 +1524,9 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) { + if (!Args.hasArg(options::OPT_pie)) + TC.getDriver().Diag(diag::err_drv_sanitizer_requires_pie) << + /* Thread */ 0; // LibTsan is "libclang_rt.tsan-.a" in the Linux library // resource directory. SmallString<128> LibTsan(TC.getDriver().ResourceDir); @@ -1537,6 +1540,27 @@ static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, } } +/// If MemorySanitizer is enabled, add appropriate linker flags (Linux). +/// This needs to be called before we add the C run-time (malloc, etc). +static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + if (!Args.hasArg(options::OPT_shared)) { + if (!Args.hasArg(options::OPT_pie)) + TC.getDriver().Diag(diag::err_drv_sanitizer_requires_pie) << + /* Memory */ 1; + // LibMsan is "libclang_rt.msan-.a" in the Linux library + // resource directory. + SmallString<128> LibMsan(TC.getDriver().ResourceDir); + llvm::sys::path::append(LibMsan, "lib", "linux", + (Twine("libclang_rt.msan-") + + TC.getArchName() + ".a")); + CmdArgs.push_back(Args.MakeArgString(LibMsan)); + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-ldl"); + CmdArgs.push_back("-export-dynamic"); + } +} + /// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags /// (Linux). static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args, @@ -5443,6 +5467,8 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, addAsanRTLinux(getToolChain(), Args, CmdArgs); if (Sanitize.needsTsanRt()) addTsanRTLinux(getToolChain(), Args, CmdArgs); + if (Sanitize.needsMsanRt()) + addMsanRTLinux(getToolChain(), Args, CmdArgs); if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib) &&