[asan] Split AddressSanitizer into two passes (FunctionPass, ModulePass), LLVM part...
authorKostya Serebryany <kcc@google.com>
Wed, 28 Nov 2012 10:31:36 +0000 (10:31 +0000)
committerKostya Serebryany <kcc@google.com>
Wed, 28 Nov 2012 10:31:36 +0000 (10:31 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168781 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/InitializePasses.h
include/llvm/Transforms/Instrumentation.h
lib/Transforms/Instrumentation/AddressSanitizer.cpp
lib/Transforms/Instrumentation/Instrumentation.cpp
test/Instrumentation/AddressSanitizer/instrument_global.ll
test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll

index e06b8928741993a92bee18b012be86ae1c0b5dc6..bde2f2ca768872b15fab2e70c6b6a6f182aa8181 100644 (file)
@@ -110,6 +110,7 @@ void initializeExpandPostRAPass(PassRegistry&);
 void initializePathProfilerPass(PassRegistry&);
 void initializeGCOVProfilerPass(PassRegistry&);
 void initializeAddressSanitizerPass(PassRegistry&);
+void initializeAddressSanitizerModulePass(PassRegistry&);
 void initializeThreadSanitizerPass(PassRegistry&);
 void initializeEarlyCSEPass(PassRegistry&);
 void initializeExpandISelPseudosPass(PassRegistry&);
index 3558251a4339785144b4f9851160913984c2f9c6..e4c60bf8d160186fc607738ff45b5d6e07d37fe1 100644 (file)
@@ -34,7 +34,8 @@ ModulePass *createGCOVProfilerPass(bool EmitNotes = true, bool EmitData = true,
                                    bool UseExtraChecksum = false);
 
 // Insert AddressSanitizer (address sanity checking) instrumentation
-FunctionPass *createAddressSanitizerPass();
+FunctionPass *createAddressSanitizerFunctionPass();
+ModulePass *createAddressSanitizerModulePass();
 // Insert ThreadSanitizer (race detection) instrumentation
 FunctionPass *createThreadSanitizerPass();
 
index 4e05c3200ceb43987795f329ed4a508ef07a3fb3..24dc0f267a349b92caf20c0443ebed9e850c1370 100644 (file)
@@ -187,7 +187,9 @@ static size_t RedzoneSize() {
 /// AddressSanitizer: instrument the code in module to find memory bugs.
 struct AddressSanitizer : public FunctionPass {
   AddressSanitizer();
-  virtual const char *getPassName() const;
+  virtual const char *getPassName() const {
+    return "AddressSanitizerFunctionPass";
+  }
   void instrumentMop(Instruction *I);
   void instrumentAddress(Instruction *OrigIns, IRBuilder<> &IRB,
                          Value *Addr, uint32_t TypeSize, bool IsWrite);
@@ -206,7 +208,6 @@ struct AddressSanitizer : public FunctionPass {
   bool maybeInsertAsanInitAtFunctionEntry(Function &F);
   bool poisonStackInFunction(Function &F);
   virtual bool doInitialization(Module &M);
-  virtual bool doFinalization(Module &M);
   static char ID;  // Pass identification, replacement for typeid
 
  private:
@@ -247,10 +248,14 @@ struct AddressSanitizer : public FunctionPass {
   SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals;
 };
 
-// FIXME: inherit this from ModulePass and actually use it as a ModulePass.
-class AddressSanitizerCreateGlobalRedzonesPass {
+class AddressSanitizerModule : public ModulePass {
  public:
-  bool runOnModule(Module &M, DataLayout *TD);
+  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,
@@ -260,6 +265,7 @@ class AddressSanitizerCreateGlobalRedzonesPass {
   SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals;
   Type *IntptrTy;
   LLVMContext *C;
+  DataLayout *TD;
 };
 
 }  // namespace
@@ -269,12 +275,16 @@ INITIALIZE_PASS(AddressSanitizer, "asan",
     "AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
     false, false)
 AddressSanitizer::AddressSanitizer() : FunctionPass(ID) { }
-FunctionPass *llvm::createAddressSanitizerPass() {
+FunctionPass *llvm::createAddressSanitizerFunctionPass() {
   return new AddressSanitizer();
 }
 
-const char *AddressSanitizer::getPassName() const {
-  return "AddressSanitizer";
+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();
 }
 
 static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
@@ -492,7 +502,7 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
   Crash->setDebugLoc(OrigIns->getDebugLoc());
 }
 
-void AddressSanitizerCreateGlobalRedzonesPass::createInitializerPoisonCalls(
+void AddressSanitizerModule::createInitializerPoisonCalls(
     Module &M, Value *FirstAddr, Value *LastAddr) {
   // We do all of our poisoning and unpoisoning within _GLOBAL__I_a.
   Function *GlobalInit = M.getFunction("_GLOBAL__I_a");
@@ -524,8 +534,7 @@ void AddressSanitizerCreateGlobalRedzonesPass::createInitializerPoisonCalls(
   }
 }
 
-bool AddressSanitizerCreateGlobalRedzonesPass::ShouldInstrumentGlobal(
-    GlobalVariable *G) {
+bool AddressSanitizerModule::ShouldInstrumentGlobal(GlobalVariable *G) {
   Type *Ty = cast<PointerType>(G->getType())->getElementType();
   DEBUG(dbgs() << "GLOBAL: " << *G << "\n");
 
@@ -587,8 +596,11 @@ bool AddressSanitizerCreateGlobalRedzonesPass::ShouldInstrumentGlobal(
 // This function replaces all global variables with new variables that have
 // trailing redzones. It also creates a function that poisons
 // redzones and inserts this function into llvm.global_ctors.
-bool AddressSanitizerCreateGlobalRedzonesPass::runOnModule(Module &M,
-                                                           DataLayout *TD) {
+bool AddressSanitizerModule::runOnModule(Module &M) {
+  if (!ClGlobals) return false;
+  TD = getAnalysisIfAvailable<DataLayout>();
+  if (!TD)
+    return false;
   BL.reset(new BlackList(ClBlackListFile));
   DynamicallyInitializedGlobals.Init(M);
   C = &(M.getContext());
@@ -817,18 +829,6 @@ bool AddressSanitizer::doInitialization(Module &M) {
   return true;
 }
 
-bool AddressSanitizer::doFinalization(Module &M) {
-  // We transform the globals at the very end so that the optimization analysis
-  // works on the original globals.
-  if (ClGlobals) {
-    // FIXME: instead of doFinalization, run this as a true ModulePass.
-    AddressSanitizerCreateGlobalRedzonesPass Pass;
-    return Pass.runOnModule(M, TD);
-  }
-  return false;
-}
-
-
 bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) {
   // For each NSObject descendant having a +load method, this method is invoked
   // by the ObjC runtime before any of the static constructors is called.
index 1e0b4a348a17e5e73d3592d3932b3f0798e29e5e..46394da856ed4ba7c27fdf8366042be1424df4ea 100644 (file)
@@ -21,6 +21,7 @@ using namespace llvm;
 /// library.
 void llvm::initializeInstrumentation(PassRegistry &Registry) {
   initializeAddressSanitizerPass(Registry);
+  initializeAddressSanitizerModulePass(Registry);
   initializeBoundsCheckingPass(Registry);
   initializeEdgeProfilerPass(Registry);
   initializeGCOVProfilerPass(Registry);
index 3d92946087ecfb8b080f499e591fbd800b4e20c3..2c183f523feb2402285686ea62de06d652604d12 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt < %s -asan -S | FileCheck %s
+; RUN: opt < %s -asan -asan-module -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"
 target triple = "x86_64-unknown-linux-gnu"
 @xxx = global i32 0, align 4
index c11a0498c3a310f872b69d04a73814fc58e973fc..042c06ba969215f8845d5ba1e82d2a416c485d38 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt < %s -asan -asan-initialization-order -S | FileCheck %s
+; RUN: opt < %s -asan -asan-module -asan-initialization-order -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"
 target triple = "x86_64-unknown-linux-gnu"
 @xxx = internal global i32 0, align 4  ; With dynamic initializer.