From 29524a98714e5a102ef7d68d5f668577d8e68ca4 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Sun, 20 Jan 2013 13:12:12 +0000 Subject: [PATCH] Add top-level Clang flag -f(no-)sanitize-address-zero-base-shadow that makes AddressSanitizer use bottom of the address space for the shadow memory. On Linux it can be used with -fPIE/-pie to improve performance. llvm-svn: 172974 --- clang/include/clang/Driver/Options.td | 9 +++++++-- clang/include/clang/Frontend/CodeGenOptions.def | 6 ++++-- clang/lib/CodeGen/BackendUtil.cpp | 18 +++++++++++------- clang/lib/Driver/SanitizerArgs.h | 8 +++++++- clang/lib/Driver/Tools.cpp | 19 +++++++++++++++++-- clang/lib/Frontend/CompilerInvocation.cpp | 4 +++- clang/test/Driver/fsanitize.c | 12 ++++++++++++ 7 files changed, 61 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 2d8b17f..01e1623 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -392,6 +392,12 @@ def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group, "address (memory errors) | thread (race detection) | " "undefined (miscellaneous undefined behavior)">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group; +def fsanitize_address_zero_base_shadow : Flag<["-"], "fsanitize-address-zero-base-shadow">, + Group, Flags<[CC1Option]>, + HelpText<"Make AddressSanitizer map shadow memory" + "at zero offset">; +def fno_sanitize_address_zero_base_shadow : Flag<["-"], "fno-sanitize-address-zero-base-shadow">, + Group; def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, Group, Flags<[CC1Option]>, HelpText<"Path to blacklist file for sanitizers">; @@ -402,8 +408,7 @@ def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins Group, Flags<[CC1Option]>, HelpText<"Enable origins tracking in MemorySanitizer">; def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">, - Group, - HelpText<"Disable origins tracking in MemorySanitizer">; + Group; def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, diff --git a/clang/include/clang/Frontend/CodeGenOptions.def b/clang/include/clang/Frontend/CodeGenOptions.def index 5e87dab..64eff9c 100644 --- a/clang/include/clang/Frontend/CodeGenOptions.def +++ b/clang/include/clang/Frontend/CodeGenOptions.def @@ -61,8 +61,6 @@ CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to ///< be generated. -CODEGENOPT(MemorySanitizerTrackOrigins , 1, 0) ///< Enable tracking origins in - ///< MemorySanitizer CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants. CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled. CODEGENOPT(NoDwarf2CFIAsm , 1, 0) ///< Set when -fno-dwarf2-cfi-asm is enabled. @@ -85,6 +83,10 @@ VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. +CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero + ///< offset in AddressSanitizer. +CODEGENOPT(SanitizeMemoryTrackOrigins, 1, 0) ///< Enable tracking origins in + ///< MemorySanitizer CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 8a3ee39..b938aac 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -164,12 +164,16 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, static_cast(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); const LangOptions &LangOpts = BuilderWrapper.getLangOpts(); - PM.add(createAddressSanitizerFunctionPass(LangOpts.Sanitize.InitOrder, - LangOpts.Sanitize.UseAfterReturn, - LangOpts.Sanitize.UseAfterScope, - CGOpts.SanitizerBlacklistFile)); - PM.add(createAddressSanitizerModulePass(LangOpts.Sanitize.InitOrder, - CGOpts.SanitizerBlacklistFile)); + PM.add(createAddressSanitizerFunctionPass( + LangOpts.Sanitize.InitOrder, + LangOpts.Sanitize.UseAfterReturn, + LangOpts.Sanitize.UseAfterScope, + CGOpts.SanitizerBlacklistFile, + CGOpts.SanitizeAddressZeroBaseShadow)); + PM.add(createAddressSanitizerModulePass( + LangOpts.Sanitize.InitOrder, + CGOpts.SanitizerBlacklistFile, + CGOpts.SanitizeAddressZeroBaseShadow)); } static void addMemorySanitizerPass(const PassManagerBuilder &Builder, @@ -177,7 +181,7 @@ static void addMemorySanitizerPass(const PassManagerBuilder &Builder, const PassManagerBuilderWrapper &BuilderWrapper = static_cast(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - PM.add(createMemorySanitizerPass(CGOpts.MemorySanitizerTrackOrigins, + PM.add(createMemorySanitizerPass(CGOpts.SanitizeMemoryTrackOrigins, CGOpts.SanitizerBlacklistFile)); } diff --git a/clang/lib/Driver/SanitizerArgs.h b/clang/lib/Driver/SanitizerArgs.h index 0955889..ea89904 100644 --- a/clang/lib/Driver/SanitizerArgs.h +++ b/clang/lib/Driver/SanitizerArgs.h @@ -41,9 +41,11 @@ class SanitizerArgs { unsigned Kind; std::string BlacklistFile; bool MsanTrackOrigins; + bool AsanZeroBaseShadow; public: - SanitizerArgs() : Kind(0), BlacklistFile(""), MsanTrackOrigins(false) {} + SanitizerArgs() : Kind(0), BlacklistFile(""), MsanTrackOrigins(false), + AsanZeroBaseShadow(false) {} /// Parses the sanitizer arguments from an argument list. SanitizerArgs(const Driver &D, const ArgList &Args); @@ -72,6 +74,10 @@ class SanitizerArgs { if (MsanTrackOrigins) CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins")); + + if (AsanZeroBaseShadow) + CmdArgs.push_back(Args.MakeArgString( + "-fsanitize-address-zero-base-shadow")); } private: diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 3132e75..0cc9ea2 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1444,7 +1444,8 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { } SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args) - : Kind(0), BlacklistFile(""), MsanTrackOrigins(false) { + : Kind(0), BlacklistFile(""), MsanTrackOrigins(false), + AsanZeroBaseShadow(false) { for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { unsigned Add, Remove; @@ -1493,11 +1494,18 @@ SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args) } // Parse -f(no-)sanitize-memory-track-origins options. - if (Kind & Memory) + if (NeedsMsan) MsanTrackOrigins = Args.hasFlag(options::OPT_fsanitize_memory_track_origins, options::OPT_fno_sanitize_memory_track_origins, /* Default */false); + + // Parse -f(no-)sanitize-address-zero-base-shadow options. + if (NeedsAsan) + AsanZeroBaseShadow = + Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow, + options::OPT_fno_sanitize_address_zero_base_shadow, + /* Default */false); } /// If AddressSanitizer is enabled, add appropriate linker flags (Linux). @@ -1517,6 +1525,13 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan)); } else { if (!Args.hasArg(options::OPT_shared)) { + bool ZeroBaseShadow = Args.hasFlag( + options::OPT_fsanitize_address_zero_base_shadow, + options::OPT_fno_sanitize_address_zero_base_shadow, false); + if (ZeroBaseShadow && !Args.hasArg(options::OPT_pie)) { + TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) << + "-fsanitize-address-zero-base-shadow" << "-pie"; + } // LibAsan is "libclang_rt.asan-.a" in the Linux library // resource directory. SmallString<128> LibAsan(TC.getDriver().ResourceDir); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 9329b3b..a16b822 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -404,8 +404,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file); Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist); - Opts.MemorySanitizerTrackOrigins = + Opts.SanitizeMemoryTrackOrigins = Args.hasArg(OPT_fsanitize_memory_track_origins); + Opts.SanitizeAddressZeroBaseShadow = + Args.hasArg(OPT_fsanitize_address_zero_base_shadow); Opts.SSPBufferSize = Args.getLastArgIntValue(OPT_stack_protector_buffer_size, 8, Diags); Opts.StackRealignment = Args.hasArg(OPT_mstackrealign); diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 857ae32..a4c8700 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -39,6 +39,9 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-EXTRA-TRACK-ORIGINS // CHECK-NO-EXTRA-TRACK-ORIGINS-NOT: "-fsanitize-memory-track-origins" +// RUN: %clang -target x86_64-linux-gnu -fsanitize-address-zero-base-shadow -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-ASAN-ZERO-BASE-SHADOW +// CHECK-ONLY-ASAN-ZERO-BASE-SHADOW: warning: argument unused during compilation: '-fsanitize-address-zero-base-shadow' + // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize=alignment -fsanitize=vptr -fno-sanitize=vptr %s -### 2>&1 // OK @@ -51,6 +54,9 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-sanitize=vptr -fsanitize=undefined,address %s -### 2>&1 // OK +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-zero-base-shadow -pie %s -### 2>&1 +// OK + // RUN: %clang -target x86_64-linux-gnu -fcatch-undefined-behavior -fthread-sanitizer -fno-thread-sanitizer -faddress-sanitizer -fno-address-sanitizer -fbounds-checking -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-DEPRECATED // CHECK-DEPRECATED: argument '-fcatch-undefined-behavior' is deprecated, use '-fsanitize=undefined' instead // CHECK-DEPRECATED: argument '-fthread-sanitizer' is deprecated, use '-fsanitize=thread' instead @@ -65,6 +71,12 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-NO-PIE // CHECK-MSAN-NO-PIE: invalid argument '-fsanitize=memory' only allowed with '-pie' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-zero-base-shadow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ZERO-BASE-SHADOW-NO-PIE +// CHECK-ASAN-ZERO-BASE-SHADOW-NO-PIE: invalid argument '-fsanitize-address-zero-base-shadow' only allowed with '-pie' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-zero-base-shadow -fno-sanitize-address-zero-base-shadow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ZERO-BASE-SHADOW-CANCEL +// CHECK-ASAN-ZERO-BASE-SHADOW-CANCEL-NOT: '-fsanitize-address-zero-base-shadow' only allowed with '-pie' + // RUN: %clang -target arm-linux-androideabi -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ANDROID-ASAN-NO-PIE // CHECK-ANDROID-ASAN-NO-PIE: AddressSanitizer on Android requires '-pie' -- 2.7.4