mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
[asan] change the coverage collection scheme so that we can easily emit coverage for the entire process as a single bit set, and if coverage_bitset=1 actually emit that bitset
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224789 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c9e5247ea7
commit
b69d796590
@ -10,10 +10,10 @@
|
|||||||
// Coverage instrumentation that works with AddressSanitizer
|
// Coverage instrumentation that works with AddressSanitizer
|
||||||
// and potentially with other Sanitizers.
|
// and potentially with other Sanitizers.
|
||||||
//
|
//
|
||||||
// We create a Guard boolean variable with the same linkage
|
// We create a Guard variable with the same linkage
|
||||||
// as the function and inject this code into the entry block (CoverageLevel=1)
|
// as the function and inject this code into the entry block (CoverageLevel=1)
|
||||||
// or all blocks (CoverageLevel>=2):
|
// or all blocks (CoverageLevel>=2):
|
||||||
// if (Guard) {
|
// if (Guard < 0) {
|
||||||
// __sanitizer_cov(&Guard);
|
// __sanitizer_cov(&Guard);
|
||||||
// }
|
// }
|
||||||
// The accesses to Guard are atomic. The rest of the logic is
|
// The accesses to Guard are atomic. The rest of the logic is
|
||||||
@ -112,6 +112,8 @@ class SanitizerCoverageModule : public ModulePass {
|
|||||||
Type *IntptrTy;
|
Type *IntptrTy;
|
||||||
LLVMContext *C;
|
LLVMContext *C;
|
||||||
|
|
||||||
|
SmallVector<Constant *, 16> Guards;
|
||||||
|
|
||||||
int CoverageLevel;
|
int CoverageLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,6 +136,8 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
|||||||
IntptrTy = Type::getIntNTy(*C, DLP->getDataLayout().getPointerSizeInBits());
|
IntptrTy = Type::getIntNTy(*C, DLP->getDataLayout().getPointerSizeInBits());
|
||||||
Type *VoidTy = Type::getVoidTy(*C);
|
Type *VoidTy = Type::getVoidTy(*C);
|
||||||
IRBuilder<> IRB(*C);
|
IRBuilder<> IRB(*C);
|
||||||
|
Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
|
||||||
|
Type *Int32PtrPtrTy = PointerType::getUnqual(Int32PtrTy);
|
||||||
|
|
||||||
Function *CtorFunc =
|
Function *CtorFunc =
|
||||||
Function::Create(FunctionType::get(VoidTy, false),
|
Function::Create(FunctionType::get(VoidTy, false),
|
||||||
@ -142,11 +146,12 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
|||||||
appendToGlobalCtors(M, CtorFunc, kSanCtorAndDtorPriority);
|
appendToGlobalCtors(M, CtorFunc, kSanCtorAndDtorPriority);
|
||||||
|
|
||||||
SanCovFunction = checkInterfaceFunction(
|
SanCovFunction = checkInterfaceFunction(
|
||||||
M.getOrInsertFunction(kSanCovName, VoidTy, IRB.getInt8PtrTy(), nullptr));
|
M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr));
|
||||||
SanCovIndirCallFunction = checkInterfaceFunction(M.getOrInsertFunction(
|
SanCovIndirCallFunction = checkInterfaceFunction(M.getOrInsertFunction(
|
||||||
kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr));
|
kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr));
|
||||||
SanCovModuleInit = checkInterfaceFunction(M.getOrInsertFunction(
|
SanCovModuleInit = checkInterfaceFunction(
|
||||||
kSanCovModuleInitName, Type::getVoidTy(*C), IntptrTy, nullptr));
|
M.getOrInsertFunction(kSanCovModuleInitName, Type::getVoidTy(*C),
|
||||||
|
Int32PtrPtrTy, IntptrTy, nullptr));
|
||||||
SanCovModuleInit->setLinkage(Function::ExternalLinkage);
|
SanCovModuleInit->setLinkage(Function::ExternalLinkage);
|
||||||
// We insert an empty inline asm after cov callbacks to avoid callback merge.
|
// We insert an empty inline asm after cov callbacks to avoid callback merge.
|
||||||
EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false),
|
EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false),
|
||||||
@ -163,9 +168,15 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
|||||||
for (auto &F : M)
|
for (auto &F : M)
|
||||||
runOnFunction(F);
|
runOnFunction(F);
|
||||||
|
|
||||||
|
ArrayType *ArrayOfInt32PtrTy = ArrayType::get(Int32PtrTy, Guards.size());
|
||||||
IRB.SetInsertPoint(CtorFunc->getEntryBlock().getTerminator());
|
IRB.SetInsertPoint(CtorFunc->getEntryBlock().getTerminator());
|
||||||
IRB.CreateCall(SanCovModuleInit,
|
GlobalVariable *AllGuards = new GlobalVariable(
|
||||||
ConstantInt::get(IntptrTy, SanCovFunction->getNumUses()));
|
M, ArrayOfInt32PtrTy, false, GlobalVariable::InternalLinkage,
|
||||||
|
ConstantArray::get(ArrayOfInt32PtrTy, Guards), "");
|
||||||
|
assert(SanCovFunction->getNumUses() == Guards.size());
|
||||||
|
IRB.CreateCall2(SanCovModuleInit,
|
||||||
|
IRB.CreatePointerCast(AllGuards, Int32PtrPtrTy),
|
||||||
|
ConstantInt::get(IntptrTy, Guards.size()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,16 +282,16 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F,
|
|||||||
: IP->getDebugLoc();
|
: IP->getDebugLoc();
|
||||||
IRBuilder<> IRB(IP);
|
IRBuilder<> IRB(IP);
|
||||||
IRB.SetCurrentDebugLocation(EntryLoc);
|
IRB.SetCurrentDebugLocation(EntryLoc);
|
||||||
Type *Int8Ty = IRB.getInt8Ty();
|
Type *Int32Ty = IRB.getInt32Ty();
|
||||||
GlobalVariable *Guard = new GlobalVariable(
|
GlobalVariable *Guard = new GlobalVariable(
|
||||||
*F.getParent(), Int8Ty, false, GlobalValue::PrivateLinkage,
|
*F.getParent(), Int32Ty, false, GlobalValue::PrivateLinkage,
|
||||||
Constant::getNullValue(Int8Ty), "__sancov_gen_cov_" + F.getName());
|
Constant::getNullValue(Int32Ty), "__sancov_gen_cov_" + F.getName());
|
||||||
LoadInst *Load = IRB.CreateLoad(Guard);
|
LoadInst *Load = IRB.CreateLoad(Guard);
|
||||||
Load->setAtomic(Monotonic);
|
Load->setAtomic(Monotonic);
|
||||||
Load->setAlignment(1);
|
Load->setAlignment(4);
|
||||||
Load->setMetadata(F.getParent()->getMDKindID("nosanitize"),
|
Load->setMetadata(F.getParent()->getMDKindID("nosanitize"),
|
||||||
MDNode::get(*C, None));
|
MDNode::get(*C, None));
|
||||||
Value *Cmp = IRB.CreateICmpEQ(Constant::getNullValue(Int8Ty), Load);
|
Value *Cmp = IRB.CreateICmpSGE(Constant::getNullValue(Int32Ty), Load);
|
||||||
Instruction *Ins = SplitBlockAndInsertIfThen(
|
Instruction *Ins = SplitBlockAndInsertIfThen(
|
||||||
Cmp, IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
|
Cmp, IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
|
||||||
IRB.SetInsertPoint(Ins);
|
IRB.SetInsertPoint(Ins);
|
||||||
@ -288,6 +299,7 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F,
|
|||||||
// __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC.
|
// __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC.
|
||||||
IRB.CreateCall(SanCovFunction, Guard);
|
IRB.CreateCall(SanCovFunction, Guard);
|
||||||
IRB.CreateCall(EmptyAsm); // Avoids callback merge.
|
IRB.CreateCall(EmptyAsm); // Avoids callback merge.
|
||||||
|
Guards.push_back(Guard); // Save the guard for later.
|
||||||
}
|
}
|
||||||
|
|
||||||
char SanitizerCoverageModule::ID = 0;
|
char SanitizerCoverageModule::ID = 0;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
; and add sanitize_address to @_ZN1A1fEv
|
; and add sanitize_address to @_ZN1A1fEv
|
||||||
|
|
||||||
; Test that __sanitizer_cov call has !dbg pointing to the opening { of A::f().
|
; Test that __sanitizer_cov call has !dbg pointing to the opening { of A::f().
|
||||||
; CHECK: call void @__sanitizer_cov(i8*{{.*}}), !dbg [[A:!.*]]
|
; CHECK: call void @__sanitizer_cov(i32*{{.*}}), !dbg [[A:!.*]]
|
||||||
; CHECK: [[A]] = !{i32 6, i32 0, !{{.*}}, null}
|
; CHECK: [[A]] = !{i32 6, i32 0, !{{.*}}, null}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,17 +33,17 @@ entry:
|
|||||||
; CHECK0-NOT: call void @__sanitizer_cov_module_init(
|
; CHECK0-NOT: call void @__sanitizer_cov_module_init(
|
||||||
|
|
||||||
; CHECK1-LABEL: define void @foo
|
; CHECK1-LABEL: define void @foo
|
||||||
; CHECK1: %0 = load atomic i8* @__sancov_gen_cov_foo monotonic, align 1, !nosanitize
|
; CHECK1: %0 = load atomic i32* @__sancov_gen_cov_foo monotonic, align 4, !nosanitize
|
||||||
; CHECK1: %1 = icmp eq i8 0, %0
|
; CHECK1: %1 = icmp sge i32 0, %0
|
||||||
; CHECK1: br i1 %1, label %2, label %3
|
; CHECK1: br i1 %1, label %2, label %3
|
||||||
; CHECK1: call void @__sanitizer_cov(i8*{{.*}})
|
; CHECK1: call void @__sanitizer_cov(i32*{{.*}})
|
||||||
; CHECK1: call void asm sideeffect "", ""()
|
; CHECK1: call void asm sideeffect "", ""()
|
||||||
; CHECK1-NOT: call void @__sanitizer_cov
|
; CHECK1-NOT: call void @__sanitizer_cov
|
||||||
; CHECK1: ret void
|
; CHECK1: ret void
|
||||||
|
|
||||||
; CHECK1-LABEL: define internal void @sancov.module_ctor
|
; CHECK1-LABEL: define internal void @sancov.module_ctor
|
||||||
; CHECK1-NOT: ret
|
; CHECK1-NOT: ret
|
||||||
; CHECK1: call void @__sanitizer_cov_module_init(i64 2)
|
; CHECK1: call void @__sanitizer_cov_module_init({{.*}}, i64 2)
|
||||||
; CHECK1: ret
|
; CHECK1: ret
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ entry:
|
|||||||
|
|
||||||
; CHECK2-LABEL: define internal void @sancov.module_ctor
|
; CHECK2-LABEL: define internal void @sancov.module_ctor
|
||||||
; CHECK2-NOT: ret
|
; CHECK2-NOT: ret
|
||||||
; CHECK2: call void @__sanitizer_cov_module_init(i64 4)
|
; CHECK2: call void @__sanitizer_cov_module_init({{.*}}, i64 4)
|
||||||
; CHECK2: ret
|
; CHECK2: ret
|
||||||
|
|
||||||
; CHECK3-LABEL: define void @foo
|
; CHECK3-LABEL: define void @foo
|
||||||
|
@ -17,9 +17,9 @@ target triple = "x86_64-unknown-linux-gnu"
|
|||||||
; Check that __sanitizer_cov call has !dgb pointing to the beginning
|
; Check that __sanitizer_cov call has !dgb pointing to the beginning
|
||||||
; of appropriate basic blocks.
|
; of appropriate basic blocks.
|
||||||
; CHECK-LABEL:_Z3fooPi
|
; CHECK-LABEL:_Z3fooPi
|
||||||
; CHECK: call void @__sanitizer_cov(i8*{{.*}}), !dbg [[A:!.*]]
|
; CHECK: call void @__sanitizer_cov(i32*{{.*}}), !dbg [[A:!.*]]
|
||||||
; CHECK: call void @__sanitizer_cov(i8*{{.*}}), !dbg [[B:!.*]]
|
; CHECK: call void @__sanitizer_cov(i32*{{.*}}), !dbg [[B:!.*]]
|
||||||
; CHECK: call void @__sanitizer_cov(i8*{{.*}}), !dbg [[C:!.*]]
|
; CHECK: call void @__sanitizer_cov(i32*{{.*}}), !dbg [[C:!.*]]
|
||||||
; CHECK: ret void
|
; CHECK: ret void
|
||||||
; CHECK: [[A]] = !{i32 1, i32 0, !{{.*}}, null}
|
; CHECK: [[A]] = !{i32 1, i32 0, !{{.*}}, null}
|
||||||
; CHECK: [[B]] = !{i32 3, i32 5, !{{.*}}, null}
|
; CHECK: [[B]] = !{i32 3, i32 5, !{{.*}}, null}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user