[cfe-commits] [PATCH] Add three new sanitizers depending on ASan.
Alexey Samsonov
samsonov at google.com
Thu Nov 29 12:15:45 PST 2012
Added brief description of new sanitizer flags to UsersManual.
Moved configuring AddressSanitizer passes (possible after
r168910) to BackendUtil. There was a problem: extension
callbacks we add to PassManagerBuilder are responsible for
creating ASan passes, but can't take parameters (in our
case we need LangOpts to determine which sanitizers are enabled).
Use sneaky inheritance from PassManagerBuilder to resolve this
(as suggested by Dan Gohman).
Hi kcc, rsmith,
http://llvm-reviews.chandlerc.com/D142
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D142?vs=362&id=371#toc
Files:
lib/Driver/SanitizerArgs.h
lib/Driver/Tools.cpp
lib/CodeGen/BackendUtil.cpp
test/Driver/fsanitize.c
include/clang/Basic/Sanitizers.def
docs/UsersManual.html
Index: lib/Driver/SanitizerArgs.h
===================================================================
--- lib/Driver/SanitizerArgs.h
+++ lib/Driver/SanitizerArgs.h
@@ -28,7 +28,7 @@
#define SANITIZER(NAME, ID) ID = 1 << SO_##ID,
#define SANITIZER_GROUP(NAME, ID, ALIAS) ID = ALIAS,
#include "clang/Basic/Sanitizers.def"
- NeedsAsanRt = Address,
+ NeedsAsanRt = AddressFull,
NeedsTsanRt = Thread,
NeedsUbsanRt = (Undefined & ~Bounds) | Integer
};
@@ -44,7 +44,7 @@
bool needsUbsanRt() const { return Kind & NeedsUbsanRt; }
bool sanitizesVptr() const { return Kind & Vptr; }
-
+
void addArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
if (!Kind)
return;
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1474,6 +1474,13 @@
D.Diag(diag::err_drv_argument_not_allowed_with)
<< lastArgumentForKind(D, Args, NeedsAsan ? NeedsAsanRt : NeedsTsanRt)
<< lastArgumentForKind(D, Args, NeedsUbsan ? NeedsUbsanRt : NeedsTsanRt);
+
+ // If -fsanitize contains extra features of ASan, it should also
+ // explicitly contain -fsanitize=address.
+ if (NeedsAsan && ((Kind & Address) == 0))
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsAsanRt)
+ << "-fsanitize=address";
}
/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -135,6 +135,17 @@
void EmitAssembly(BackendAction Action, raw_ostream *OS);
};
+// We need this wrapper to access LangOpts from extension functions that
+// we add to the PassManagerBuilder.
+class PassManagerBuilderWrapper : public PassManagerBuilder {
+ public:
+ PassManagerBuilderWrapper(const LangOptions &LangOpts)
+ : PassManagerBuilder(), LangOpts(LangOpts) {}
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ private:
+ const LangOptions &LangOpts;
+};
+
}
static void addObjCARCAPElimPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
@@ -157,10 +168,16 @@
PM.add(createBoundsCheckingPass());
}
-static void addAddressSanitizerPass(const PassManagerBuilder &Builder,
- PassManagerBase &PM) {
- PM.add(createAddressSanitizerFunctionPass());
- PM.add(createAddressSanitizerModulePass());
+static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
+ PassManagerBase &PM) {
+ const PassManagerBuilderWrapper *BuilderWrapper =
+ static_cast<const PassManagerBuilderWrapper*>(&Builder);
+ assert(BuilderWrapper);
+ const LangOptions &LangOpts = BuilderWrapper->getLangOpts();
+ PM.add(createAddressSanitizerFunctionPass(LangOpts.SanitizeInitOrder,
+ LangOpts.SanitizeUseAfterReturn,
+ LangOpts.SanitizeUseAfterScope));
+ PM.add(createAddressSanitizerModulePass(LangOpts.SanitizeInitOrder));
}
static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
@@ -179,7 +196,7 @@
Inlining = CodeGenOpts.NoInlining;
}
- PassManagerBuilder PMBuilder;
+ PassManagerBuilderWrapper PMBuilder(LangOpts);
PMBuilder.OptLevel = OptLevel;
PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
@@ -206,9 +223,9 @@
if (LangOpts.SanitizeAddress) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
- addAddressSanitizerPass);
+ addAddressSanitizerPasses);
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
- addAddressSanitizerPass);
+ addAddressSanitizerPasses);
}
if (LangOpts.SanitizeThread) {
Index: test/Driver/fsanitize.c
===================================================================
--- test/Driver/fsanitize.c
+++ test/Driver/fsanitize.c
@@ -10,6 +10,9 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-thread-sanitizer -fno-sanitize=float-cast-overflow,vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED
// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|object-size|bounds),?){11}"}}
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address-full %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-FULL
+// CHECK-ASAN-FULL: "-fsanitize={{((address|init-order|use-after-return|use-after-scope),?){4}"}}
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI
// CHECK-VPTR-NO-RTTI: '-fsanitize=vptr' not allowed with '-fno-rtti'
@@ -20,6 +23,9 @@
// RUN: %clang -target x86_64-linux-gnu -faddress-sanitizer -fthread-sanitizer -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-TSAN
// CHECK-ASAN-TSAN: '-faddress-sanitizer' not allowed with '-fthread-sanitizer'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=init-order %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-EXTRA-ASAN
+// CHECK-ONLY-EXTRA-ASAN: argument '-fsanitize=init-order' only allowed with '-fsanitize=address'
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize=alignment -fsanitize=vptr -fno-sanitize=vptr %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-ASAN
// CHECK-UBSAN-ASAN: '-fsanitize=address' not allowed with '-fsanitize=alignment'
Index: include/clang/Basic/Sanitizers.def
===================================================================
--- include/clang/Basic/Sanitizers.def
+++ include/clang/Basic/Sanitizers.def
@@ -40,6 +40,13 @@
// AddressSanitizer
SANITIZER("address", Address)
+// More features of AddressSanitizer that should be turned on explicitly.
+SANITIZER("init-order", InitOrder)
+SANITIZER("use-after-return", UseAfterReturn)
+SANITIZER("use-after-scope", UseAfterScope)
+
+SANITIZER_GROUP("address-full", AddressFull,
+ Address | InitOrder | UseAfterReturn | UseAfterScope)
// ThreadSanitizer
SANITIZER("thread", Thread)
Index: docs/UsersManual.html
===================================================================
--- docs/UsersManual.html
+++ docs/UsersManual.html
@@ -886,6 +886,8 @@
<li id="opt_fsanitize_address"><tt>-fsanitize=address</tt>:
<a href="AddressSanitizer.html">AddressSanitizer</a>, a memory error
detector.</li>
+<li id="opt_fsanitize_address_full"><tt>-fsanitize=address-full</tt>:
+ AddressSanitizer with all the experimental features listed below.
<li id="opt_fsanitize_integer"><tt>-fsanitize=integer</tt>:
Enables checks for undefined or suspicious integer behavior.</li>
<li id="opt_fsanitize_thread"><tt>-fsanitize=thread</tt>:
@@ -898,7 +900,7 @@
integer overflow.</li>
</ul>
-The following more fine-grained checks are also available:
+The following more fine-grained undefined behavior checks are available:
<ul>
<li id="opt_fsanitize_alignment"><tt>-fsanitize=alignment</tt>:
@@ -941,6 +943,20 @@
<tt>-fno-rtti</tt>.</li>
</ul>
+Experimental features of AddressSanitizer (not ready for widespread use,
+require explicit <tt>-fsanitize=address</tt>):
+
+<ul>
+<li id="opt_fsanitize_init_order"><tt>-fsanitize=init-order</tt>:
+Check for dynamic initialization order problems.</li>
+<li id="opt_fsanitize_use_after_return"><tt>-fsanitize=use-after-return</tt>:
+Check for use-after-return errors (accessing local variable after the function
+exit).
+<li id="opt_fsanitize_use_after_scope"><tt>-fsanitize=use-after-scope</tt>:
+Check for use-after-scope errors (accesing local variable after it went out of
+scope).
+</ul>
+
The <tt>-fsanitize=</tt> argument must also be provided when linking, in order
to link to the appropriate runtime library. It is not possible to combine the
<tt>-fsanitize=address</tt> and <tt>-fsanitize=thread</tt> checkers in the same
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D142.2.patch
Type: text/x-patch
Size: 8307 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20121129/aa3ffed5/attachment.bin>
More information about the cfe-commits
mailing list