<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">On 11/28/12 1:24 PM, Alexey Samsonov
      wrote:<br>
    </div>
    <blockquote
cite="mid:differential-rev-PHID-DREV-3wuz6colpjwbbplkyyqg-req@llvm-reviews.chandlerc.com"
      type="cite">
      <pre wrap="">Hi kcc,

This patch allows caller to enable/disable optional ASan features
by passing arguments to createAddressSanitizer{Module,Function}Pass().</pre>
    </blockquote>
    <br>
    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.<br>
    <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.<br>
    <br>
    -- John T.<br>
    <br>
    <blockquote
cite="mid:differential-rev-PHID-DREV-3wuz6colpjwbbplkyyqg-req@llvm-reviews.chandlerc.com"
      type="cite">
      <pre wrap="">

<a class="moz-txt-link-freetext" href="http://llvm-reviews.chandlerc.com/D145">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 class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
llvm-commits mailing list
<a class="moz-txt-link-abbreviated" href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a>
<a class="moz-txt-link-freetext" href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>