[asan] Split AddressSanitizer into two passes (FunctionPass, ModulePass), LLVM part. This requires a clang part which will follow.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168781 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Kostya Serebryany 2012-11-28 10:31:36 +00:00
parent 3defc0bfa6
commit 1416edc30a
6 changed files with 31 additions and 28 deletions

View File

@ -110,6 +110,7 @@ void initializeExpandPostRAPass(PassRegistry&);
void initializePathProfilerPass(PassRegistry&); void initializePathProfilerPass(PassRegistry&);
void initializeGCOVProfilerPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&);
void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&);
void initializeAddressSanitizerModulePass(PassRegistry&);
void initializeThreadSanitizerPass(PassRegistry&); void initializeThreadSanitizerPass(PassRegistry&);
void initializeEarlyCSEPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&);
void initializeExpandISelPseudosPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&);

View File

@ -34,7 +34,8 @@ ModulePass *createGCOVProfilerPass(bool EmitNotes = true, bool EmitData = true,
bool UseExtraChecksum = false); bool UseExtraChecksum = false);
// Insert AddressSanitizer (address sanity checking) instrumentation // Insert AddressSanitizer (address sanity checking) instrumentation
FunctionPass *createAddressSanitizerPass(); FunctionPass *createAddressSanitizerFunctionPass();
ModulePass *createAddressSanitizerModulePass();
// Insert ThreadSanitizer (race detection) instrumentation // Insert ThreadSanitizer (race detection) instrumentation
FunctionPass *createThreadSanitizerPass(); FunctionPass *createThreadSanitizerPass();

View File

@ -187,7 +187,9 @@ static size_t RedzoneSize() {
/// AddressSanitizer: instrument the code in module to find memory bugs. /// AddressSanitizer: instrument the code in module to find memory bugs.
struct AddressSanitizer : public FunctionPass { struct AddressSanitizer : public FunctionPass {
AddressSanitizer(); AddressSanitizer();
virtual const char *getPassName() const; virtual const char *getPassName() const {
return "AddressSanitizerFunctionPass";
}
void instrumentMop(Instruction *I); void instrumentMop(Instruction *I);
void instrumentAddress(Instruction *OrigIns, IRBuilder<> &IRB, void instrumentAddress(Instruction *OrigIns, IRBuilder<> &IRB,
Value *Addr, uint32_t TypeSize, bool IsWrite); Value *Addr, uint32_t TypeSize, bool IsWrite);
@ -206,7 +208,6 @@ struct AddressSanitizer : public FunctionPass {
bool maybeInsertAsanInitAtFunctionEntry(Function &F); bool maybeInsertAsanInitAtFunctionEntry(Function &F);
bool poisonStackInFunction(Function &F); bool poisonStackInFunction(Function &F);
virtual bool doInitialization(Module &M); virtual bool doInitialization(Module &M);
virtual bool doFinalization(Module &M);
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
private: private:
@ -247,10 +248,14 @@ struct AddressSanitizer : public FunctionPass {
SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals; SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals;
}; };
// FIXME: inherit this from ModulePass and actually use it as a ModulePass. class AddressSanitizerModule : public ModulePass {
class AddressSanitizerCreateGlobalRedzonesPass {
public: 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: private:
bool ShouldInstrumentGlobal(GlobalVariable *G); bool ShouldInstrumentGlobal(GlobalVariable *G);
void createInitializerPoisonCalls(Module &M, Value *FirstAddr, void createInitializerPoisonCalls(Module &M, Value *FirstAddr,
@ -260,6 +265,7 @@ class AddressSanitizerCreateGlobalRedzonesPass {
SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals; SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals;
Type *IntptrTy; Type *IntptrTy;
LLVMContext *C; LLVMContext *C;
DataLayout *TD;
}; };
} // namespace } // namespace
@ -269,12 +275,16 @@ INITIALIZE_PASS(AddressSanitizer, "asan",
"AddressSanitizer: detects use-after-free and out-of-bounds bugs.", "AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
false, false) false, false)
AddressSanitizer::AddressSanitizer() : FunctionPass(ID) { } AddressSanitizer::AddressSanitizer() : FunctionPass(ID) { }
FunctionPass *llvm::createAddressSanitizerPass() { FunctionPass *llvm::createAddressSanitizerFunctionPass() {
return new AddressSanitizer(); return new AddressSanitizer();
} }
const char *AddressSanitizer::getPassName() const { char AddressSanitizerModule::ID = 0;
return "AddressSanitizer"; 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) { static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
@ -492,7 +502,7 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
Crash->setDebugLoc(OrigIns->getDebugLoc()); Crash->setDebugLoc(OrigIns->getDebugLoc());
} }
void AddressSanitizerCreateGlobalRedzonesPass::createInitializerPoisonCalls( void AddressSanitizerModule::createInitializerPoisonCalls(
Module &M, Value *FirstAddr, Value *LastAddr) { Module &M, Value *FirstAddr, Value *LastAddr) {
// We do all of our poisoning and unpoisoning within _GLOBAL__I_a. // We do all of our poisoning and unpoisoning within _GLOBAL__I_a.
Function *GlobalInit = M.getFunction("_GLOBAL__I_a"); Function *GlobalInit = M.getFunction("_GLOBAL__I_a");
@ -524,8 +534,7 @@ void AddressSanitizerCreateGlobalRedzonesPass::createInitializerPoisonCalls(
} }
} }
bool AddressSanitizerCreateGlobalRedzonesPass::ShouldInstrumentGlobal( bool AddressSanitizerModule::ShouldInstrumentGlobal(GlobalVariable *G) {
GlobalVariable *G) {
Type *Ty = cast<PointerType>(G->getType())->getElementType(); Type *Ty = cast<PointerType>(G->getType())->getElementType();
DEBUG(dbgs() << "GLOBAL: " << *G << "\n"); DEBUG(dbgs() << "GLOBAL: " << *G << "\n");
@ -587,8 +596,11 @@ bool AddressSanitizerCreateGlobalRedzonesPass::ShouldInstrumentGlobal(
// This function replaces all global variables with new variables that have // This function replaces all global variables with new variables that have
// trailing redzones. It also creates a function that poisons // trailing redzones. It also creates a function that poisons
// redzones and inserts this function into llvm.global_ctors. // redzones and inserts this function into llvm.global_ctors.
bool AddressSanitizerCreateGlobalRedzonesPass::runOnModule(Module &M, bool AddressSanitizerModule::runOnModule(Module &M) {
DataLayout *TD) { if (!ClGlobals) return false;
TD = getAnalysisIfAvailable<DataLayout>();
if (!TD)
return false;
BL.reset(new BlackList(ClBlackListFile)); BL.reset(new BlackList(ClBlackListFile));
DynamicallyInitializedGlobals.Init(M); DynamicallyInitializedGlobals.Init(M);
C = &(M.getContext()); C = &(M.getContext());
@ -817,18 +829,6 @@ bool AddressSanitizer::doInitialization(Module &M) {
return true; 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) { bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) {
// For each NSObject descendant having a +load method, this method is invoked // For each NSObject descendant having a +load method, this method is invoked
// by the ObjC runtime before any of the static constructors is called. // by the ObjC runtime before any of the static constructors is called.

View File

@ -21,6 +21,7 @@ using namespace llvm;
/// library. /// library.
void llvm::initializeInstrumentation(PassRegistry &Registry) { void llvm::initializeInstrumentation(PassRegistry &Registry) {
initializeAddressSanitizerPass(Registry); initializeAddressSanitizerPass(Registry);
initializeAddressSanitizerModulePass(Registry);
initializeBoundsCheckingPass(Registry); initializeBoundsCheckingPass(Registry);
initializeEdgeProfilerPass(Registry); initializeEdgeProfilerPass(Registry);
initializeGCOVProfilerPass(Registry); initializeGCOVProfilerPass(Registry);

View 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 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" target triple = "x86_64-unknown-linux-gnu"
@xxx = global i32 0, align 4 @xxx = global i32 0, align 4

View 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 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" target triple = "x86_64-unknown-linux-gnu"
@xxx = internal global i32 0, align 4 ; With dynamic initializer. @xxx = internal global i32 0, align 4 ; With dynamic initializer.