[llvm] r184927 - [asan] add option -asan-keep-uninstrumented-functions

Kostya Serebryany kcc at google.com
Wed Jun 26 02:18:17 PDT 2013


Author: kcc
Date: Wed Jun 26 04:18:17 2013
New Revision: 184927

URL: http://llvm.org/viewvc/llvm-project?rev=184927&view=rev
Log:
[asan] add option -asan-keep-uninstrumented-functions

Added:
    llvm/trunk/test/Instrumentation/AddressSanitizer/keep-instrumented_functions.ll
Modified:
    llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Modified: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp?rev=184927&r1=184926&r2=184927&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp Wed Jun 26 04:18:17 2013
@@ -44,6 +44,7 @@
 #include "llvm/Support/system_error.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/BlackList.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <algorithm>
@@ -131,6 +132,19 @@ static cl::opt<std::string> ClBlacklistF
        cl::desc("File containing the list of objects to ignore "
                 "during instrumentation"), cl::Hidden);
 
+// This is an experimental feature that will allow to choose between
+// instrumented and non-instrumented code at link-time.
+// If this option is on, just before instrumenting a function we create its
+// clone; if the function is not changed by asan the clone is deleted.
+// If we end up with a clone, we put the instrumented function into a section
+// called "ASAN" and the uninstrumented function into a section called "NOASAN".
+//
+// This is still a prototype, we need to figure out a way to keep two copies of
+// a function so that the linker can easily choose one of them.
+static cl::opt<bool> ClKeepUninstrumented("asan-keep-uninstrumented-functions",
+       cl::desc("Keep uninstrumented copies of functions"),
+       cl::Hidden, cl::init(false));
+
 // These flags allow to change the shadow mapping.
 // The shadow mapping looks like
 //    Shadow = (Mem >> scale) + (1 << offset_log)
@@ -1106,8 +1120,7 @@ bool AddressSanitizer::runOnFunction(Fun
   // If needed, insert __asan_init before checking for SanitizeAddress attr.
   maybeInsertAsanInitAtFunctionEntry(F);
 
-  if (!F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
-                                      Attribute::SanitizeAddress))
+  if (!F.hasFnAttribute(Attribute::SanitizeAddress))
     return false;
 
   if (!ClDebugFunc.empty() && ClDebugFunc != F.getName())
@@ -1118,6 +1131,7 @@ bool AddressSanitizer::runOnFunction(Fun
   SmallSet<Value*, 16> TempsToInstrument;
   SmallVector<Instruction*, 16> ToInstrument;
   SmallVector<Instruction*, 8> NoReturnCalls;
+  int NumAllocas = 0;
   bool IsWrite;
 
   // Fill the set of memory operations to instrument.
@@ -1136,6 +1150,8 @@ bool AddressSanitizer::runOnFunction(Fun
       } else if (isa<MemIntrinsic>(BI) && ClMemIntrin) {
         // ok, take it.
       } else {
+        if (isa<AllocaInst>(BI))
+          NumAllocas++;
         CallSite CS(BI);
         if (CS) {
           // A call inside BB.
@@ -1152,6 +1168,17 @@ bool AddressSanitizer::runOnFunction(Fun
     }
   }
 
+  Function *UninstrumentedDuplicate = 0;
+  bool LikelyToInstrument =
+      !NoReturnCalls.empty() || !ToInstrument.empty() || (NumAllocas > 0);
+  if (ClKeepUninstrumented && LikelyToInstrument) {
+    ValueToValueMapTy VMap;
+    UninstrumentedDuplicate = CloneFunction(&F, VMap, false);
+    UninstrumentedDuplicate->removeFnAttr(Attribute::SanitizeAddress);
+    UninstrumentedDuplicate->setName("NOASAN_" + F.getName());
+    F.getParent()->getFunctionList().push_back(UninstrumentedDuplicate);
+  }
+
   // Instrument.
   int NumInstrumented = 0;
   for (size_t i = 0, n = ToInstrument.size(); i != n; i++) {
@@ -1176,9 +1203,25 @@ bool AddressSanitizer::runOnFunction(Fun
     IRBuilder<> IRB(CI);
     IRB.CreateCall(AsanHandleNoReturnFunc);
   }
-  DEBUG(dbgs() << "ASAN done instrumenting:\n" << F << "\n");
 
-  return NumInstrumented > 0 || ChangedStack || !NoReturnCalls.empty();
+  bool res = NumInstrumented > 0 || ChangedStack || !NoReturnCalls.empty();
+  DEBUG(dbgs() << "ASAN done instrumenting: " << res << " " << F << "\n");
+
+  if (ClKeepUninstrumented) {
+    if (!res) {
+      // No instrumentation is done, no need for the duplicate.
+      if (UninstrumentedDuplicate)
+        UninstrumentedDuplicate->eraseFromParent();
+    } else {
+      // The function was instrumented. We must have the duplicate.
+      assert(UninstrumentedDuplicate);
+      UninstrumentedDuplicate->setSection("NOASAN");
+      assert(!F.hasSection());
+      F.setSection("ASAN");
+    }
+  }
+
+  return res;
 }
 
 static uint64_t ValueForPoison(uint64_t PoisonByte, size_t ShadowRedzoneSize) {

Added: llvm/trunk/test/Instrumentation/AddressSanitizer/keep-instrumented_functions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/AddressSanitizer/keep-instrumented_functions.ll?rev=184927&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/AddressSanitizer/keep-instrumented_functions.ll (added)
+++ llvm/trunk/test/Instrumentation/AddressSanitizer/keep-instrumented_functions.ll Wed Jun 26 04:18:17 2013
@@ -0,0 +1,23 @@
+; Test the -asan-keep-uninstrumented-functions flag: FOO should get cloned
+; RUN: opt < %s -asan -asan-keep-uninstrumented-functions -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at a = global i32 0, align 4
+
+define i32 @main() sanitize_address {
+entry:
+  tail call void @FOO(i32* @a)
+  ret i32 0
+}
+
+define void @FOO(i32* nocapture %x) sanitize_address {
+entry:
+  store i32 1, i32* %x, align 4
+  ret void
+}
+
+; main should not be cloned since it is not being instrumented by asan.
+; CHECK-NOT: NOASAN_main
+; CHECK: define void @FOO{{.*}} section "ASAN"
+; CHECK: define void @NOASAN_FOO{{.*}} section "NOASAN"





More information about the llvm-commits mailing list