From dfe9e7933e4d16a28f9000fc94c79cb63b76e5cc Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Wed, 28 Nov 2012 10:31:36 +0000 Subject: [PATCH] [asan] Split AddressSanitizer into two passes (FunctionPass, ModulePass), LLVM part. This requires a clang part which will follow. llvm-svn: 168781 --- llvm/include/llvm/InitializePasses.h | 1 + llvm/include/llvm/Transforms/Instrumentation.h | 3 +- .../Instrumentation/AddressSanitizer.cpp | 50 +++++++++++----------- .../Transforms/Instrumentation/Instrumentation.cpp | 1 + .../AddressSanitizer/instrument_global.ll | 2 +- .../instrument_initializer_metadata.ll | 2 +- 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index e06b892..bde2f2c 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -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&); diff --git a/llvm/include/llvm/Transforms/Instrumentation.h b/llvm/include/llvm/Transforms/Instrumentation.h index 3558251..e4c60bf 100644 --- a/llvm/include/llvm/Transforms/Instrumentation.h +++ b/llvm/include/llvm/Transforms/Instrumentation.h @@ -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(); diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 4e05c32..24dc0f2 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -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(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(); + 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. diff --git a/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp b/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp index 1e0b4a3..46394da 100644 --- a/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp @@ -21,6 +21,7 @@ using namespace llvm; /// library. void llvm::initializeInstrumentation(PassRegistry &Registry) { initializeAddressSanitizerPass(Registry); + initializeAddressSanitizerModulePass(Registry); initializeBoundsCheckingPass(Registry); initializeEdgeProfilerPass(Registry); initializeGCOVProfilerPass(Registry); diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll index 3d92946..2c183f5 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll @@ -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 diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll index c11a049..042c06b 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll @@ -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. -- 2.7.4