<div style="font-family: arial, helvetica, sans-serif; font-size: 10pt"><div>Hi John,</div><br><div class="gmail_quote">On Wed, Nov 28, 2012 at 11:53 AM, John Criswell <span dir="ltr"><<a href="mailto:criswell@illinois.edu" target="_blank">criswell@illinois.edu</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

  
    
  
  <div bgcolor="#FFFFFF" text="#000000"><div>
    <div>On 11/28/12 1:24 PM, Alexey Samsonov
      wrote:<br>
    </div>
    <blockquote type="cite">
      <pre>Hi kcc,

This patch allows caller to enable/disable optional ASan features
by passing arguments to createAddressSanitizer{Module,Function}Pass().</pre>
    </blockquote>
    <br></div>
    Just an FYI that, in my experience, passing configuration options
    via the class's constructor is less than ideal.  The problem is that
    the pass will not exhibit the same behavior when it is used via opt
    or bugpoint as it does when it is used in clang.  The user must know
    that invoking clang with one option will require invoking bugpoint
    with a similarly named option.  If the user doesn't know that, then
    he/she will get different results, and it will not be obvious why.</div></blockquote><div><br></div><div>I see your point. My plan was to make Clang create ASan pass with default arguments (i.e. the effect of "clang -fsanitize=address" would run the same pass "opt -asan").</div>
<div>We want to "expose" optional ASan instrumentation, which is currently controlled by llvm flags, to Clang users. So that</div><div>"-fsanitize=address,use-after-return" would do the same as "opt -asan -asan-use-after-return". So, we won't alter default ASan behavior unless Clang user explicitly asks for it.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000">
    <br>
    An alternative is to factor out each piece of functionality
    controlled by a command-line option into a separate pass and have
    clang schedule the pass for execution based on its command line
    options.  For example, SAFECode has an option called
    -fmemsafety-terminate that causes the generated program to terminate
    on the first memory safety error.  Instead of passing a flag into
    the instrumentation pass's constructor so that it knows how to
    instrument the program to get the desired termination behavior, the
    instrumentation pass simply assumes that the option is set to false
    and instruments the program to keep running after an error is
    detected.  If -fmemsafety-terminate is specified, clang runs an
    additional SAFECode instrumentation pass that changes the call to
    the SAFECode run-time library initialization function to specify
    termination after the first error.<br>
    <br>
    In this way, if you ask clang what passes it ran, and then you
    specify those passes to opt/bugpoint, you always get the same
    behavior.  Users don't need to know which opt/bugpoint options to
    use to get the same behavior that you see in Clang.<br>
    <br>
    I'm not sure if such a refactoring is possible for the options
    you've added, but you may want to consider it.</div></blockquote><div><br></div><div>Probably it's possible to break ASan features into several (communicating?) passes, but I think the complexity would overweight benefit from it. I'm open to other opinions, though.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div bgcolor="#FFFFFF" text="#000000">
    <br>
    -- John T.<br>
    <br>
    <blockquote type="cite"><div><div>
      <pre><a href="http://llvm-reviews.chandlerc.com/D145" target="_blank">http://llvm-reviews.chandlerc.com/D145</a>

Files:
  include/llvm/Transforms/Instrumentation.h
  lib/Transforms/Instrumentation/AddressSanitizer.cpp

Index: include/llvm/Transforms/Instrumentation.h
===================================================================
--- include/llvm/Transforms/Instrumentation.h
+++ include/llvm/Transforms/Instrumentation.h
@@ -34,8 +34,10 @@
                                    bool UseExtraChecksum = false);
 
 // Insert AddressSanitizer (address sanity checking) instrumentation
-FunctionPass *createAddressSanitizerFunctionPass();
-ModulePass *createAddressSanitizerModulePass();
+FunctionPass *createAddressSanitizerFunctionPass(
+    bool CheckInitOrder = false, bool CheckUseAfterReturn = false,
+    bool UseLifetime = false);
+ModulePass *createAddressSanitizerModulePass(bool CheckInitOrder = false);
 // Insert ThreadSanitizer (race detection) instrumentation
 FunctionPass *createThreadSanitizerPass();
 
Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp
===================================================================
--- lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -136,6 +136,10 @@
 static cl::opt<bool> ClOptGlobals("asan-opt-globals",
        cl::desc("Don't instrument scalar globals"), cl::Hidden, cl::init(true));
 
+static cl::opt<bool> ClUseLifetime("asan-use-lifetime",
+       cl::desc("Use llvm.lifetime intrinsics to insert extra checks"),
+       cl::Hidden, cl::init(false));
+
 // Debug flags.
 static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
                             cl::init(0));
@@ -186,7 +190,13 @@
 
 /// AddressSanitizer: instrument the code in module to find memory bugs.
 struct AddressSanitizer : public FunctionPass {
-  AddressSanitizer();
+  AddressSanitizer(bool CheckInitOrder = false,
+                   bool CheckUseAfterReturn = false,
+                   bool UseLifetime = false)
+      : FunctionPass(ID),
+        CheckInitOrder(CheckInitOrder || ClInitializers),
+        CheckUseAfterReturn(CheckUseAfterReturn || ClUseAfterReturn),
+        UseLifetime(UseLifetime || ClUseLifetime) {}
   virtual const char *getPassName() const {
     return "AddressSanitizerFunctionPass";
   }
@@ -231,6 +241,9 @@
   bool LooksLikeCodeInBug11395(Instruction *I);
   void FindDynamicInitializers(Module &M);
 
+  bool CheckInitOrder;
+  bool CheckUseAfterReturn;
+  bool UseLifetime;
   LLVMContext *C;
   DataLayout *TD;
   uint64_t MappingOffset;
@@ -250,17 +263,20 @@
 
 class AddressSanitizerModule : public ModulePass {
  public:
+  AddressSanitizerModule(bool CheckInitOrder = false)
+      : ModulePass(ID),
+        CheckInitOrder(CheckInitOrder || ClInitializers) {}
   bool runOnModule(Module &M);
   static char ID;  // Pass identification, replacement for typeid
-  AddressSanitizerModule() : ModulePass(ID) { }
   virtual const char *getPassName() const {
     return "AddressSanitizerModule";
   }
  private:
   bool ShouldInstrumentGlobal(GlobalVariable *G);
   void createInitializerPoisonCalls(Module &M, Value *FirstAddr,
                                     Value *LastAddr);
 
+  bool CheckInitOrder;
   OwningPtr<BlackList> BL;
   SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals;
   Type *IntptrTy;
@@ -274,17 +290,18 @@
 INITIALIZE_PASS(AddressSanitizer, "asan",
     "AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
     false, false)
-AddressSanitizer::AddressSanitizer() : FunctionPass(ID) { }
-FunctionPass *llvm::createAddressSanitizerFunctionPass() {
-  return new AddressSanitizer();
+FunctionPass *llvm::createAddressSanitizerFunctionPass(
+    bool CheckInitOrder, bool CheckUseAfterReturn, bool UseLifetime) {
+  return new AddressSanitizer(CheckInitOrder, CheckUseAfterReturn,
+                              UseLifetime);
 }
 
 char AddressSanitizerModule::ID = 0;
 INITIALIZE_PASS(AddressSanitizerModule, "asan-module",
     "AddressSanitizer: detects use-after-free and out-of-bounds bugs."
     "ModulePass", false, false)
-ModulePass *llvm::createAddressSanitizerModulePass() {
-  return new AddressSanitizerModule();
+ModulePass *llvm::createAddressSanitizerModulePass(bool CheckInitOrder) {
+  return new AddressSanitizerModule(CheckInitOrder);
 }
 
 static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
@@ -395,7 +412,7 @@
     if (GlobalVariable *G = dyn_cast<GlobalVariable>(Addr)) {
       // If initialization order checking is disabled, a simple access to a
       // dynamically initialized global is always valid.
-      if (!ClInitializers)
+      if (!CheckInitOrder)
         return;
       // If a global variable does not have dynamic initialization we don't
       // have to instrument it.  However, if a global does not have initailizer
@@ -689,7 +706,7 @@
         NULL);
 
     // Populate the first and last globals declared in this TU.
-    if (ClInitializers && GlobalHasDynamicInitializer) {
+    if (CheckInitOrder && GlobalHasDynamicInitializer) {
       LastDynamic = ConstantExpr::getPointerCast(NewGlobal, IntptrTy);
       if (FirstDynamic == 0)
         FirstDynamic = LastDynamic;
@@ -704,7 +721,7 @@
       ConstantArray::get(ArrayOfGlobalStructTy, Initializers), "");
 
   // Create calls for poisoning before initializers run and unpoisoning after.
-  if (ClInitializers && FirstDynamic && LastDynamic)
+  if (CheckInitOrder && FirstDynamic && LastDynamic)
     createInitializerPoisonCalls(M, FirstDynamic, LastDynamic);
 
   Function *AsanRegisterGlobals = checkInterfaceFunction(M.getOrInsertFunction(
@@ -1068,7 +1085,7 @@
 
   uint64_t LocalStackSize = TotalSize + (AllocaVec.size() + 1) * RedzoneSize();
 
-  bool DoStackMalloc = ClUseAfterReturn
+  bool DoStackMalloc = CheckUseAfterReturn
       && LocalStackSize <= kMaxStackMallocSize;
 
   Instruction *InsBefore = AllocaVec[0];
</pre>
      <br>
      <fieldset></fieldset>
      <br>
      </div></div><pre>_______________________________________________
llvm-commits mailing list
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a>
</pre>
    </blockquote>
    <br>
  </div>

</blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div><br>
</div>