From d016c6f389e17fbcdf7d9ca8348f8b6cff5a6b93 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Wed, 17 Feb 2016 21:34:43 +0000 Subject: [PATCH] [sanitizer-coverage] implement -fsanitize-coverage=trace-pc. This is similar to trace-bb, but has a different API. We already use the equivalent flag in GCC for Linux kernel fuzzing. We may be able to use this flag with AFL too git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261159 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Transforms/Instrumentation.h | 3 ++- .../Instrumentation/SanitizerCoverage.cpp | 30 +++++++++++++++++----- test/Instrumentation/SanitizerCoverage/coverage.ll | 6 +++++ test/Instrumentation/SanitizerCoverage/tracing.ll | 9 +++++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index d9402631574..ad65e0db9ba 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -120,7 +120,7 @@ ModulePass *createDataFlowSanitizerPass( struct SanitizerCoverageOptions { SanitizerCoverageOptions() : CoverageType(SCK_None), IndirectCalls(false), TraceBB(false), - TraceCmp(false), Use8bitCounters(false) {} + TraceCmp(false), Use8bitCounters(false), TracePC(false) {} enum Type { SCK_None = 0, @@ -132,6 +132,7 @@ struct SanitizerCoverageOptions { bool TraceBB; bool TraceCmp; bool Use8bitCounters; + bool TracePC; }; // Insert SanitizerCoverage instrumentation. diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 82a070843bf..34e8b579c1c 100644 --- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -57,8 +57,10 @@ static const char *const kSanCovModuleInitName = "__sanitizer_cov_module_init"; static const char *const kSanCovName = "__sanitizer_cov"; static const char *const kSanCovWithCheckName = "__sanitizer_cov_with_check"; static const char *const kSanCovIndirCallName = "__sanitizer_cov_indir_call16"; +static const char *const kSanCovTracePCIndir = "__sanitizer_cov_trace_pc_indir"; static const char *const kSanCovTraceEnter = "__sanitizer_cov_trace_func_enter"; static const char *const kSanCovTraceBB = "__sanitizer_cov_trace_basic_block"; +static const char *const kSanCovTracePC = "__sanitizer_cov_trace_pc"; static const char *const kSanCovTraceCmp = "__sanitizer_cov_trace_cmp"; static const char *const kSanCovTraceSwitch = "__sanitizer_cov_trace_switch"; static const char *const kSanCovModuleCtorName = "sancov.module_ctor"; @@ -82,6 +84,10 @@ static cl::opt "callbacks at every basic block"), cl::Hidden, cl::init(false)); +static cl::opt ClExperimentalTracePC("sanitizer-coverage-trace-pc", + cl::desc("Experimental pc tracing"), + cl::Hidden, cl::init(false)); + static cl::opt ClExperimentalCMPTracing("sanitizer-coverage-experimental-trace-compares", cl::desc("Experimental tracing of CMP and similar " @@ -131,6 +137,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { Options.TraceBB |= ClExperimentalTracing; Options.TraceCmp |= ClExperimentalCMPTracing; Options.Use8bitCounters |= ClUse8bitCounters; + Options.TracePC |= ClExperimentalTracePC; return Options; } @@ -162,8 +169,8 @@ class SanitizerCoverageModule : public ModulePass { } Function *SanCovFunction; Function *SanCovWithCheckFunction; - Function *SanCovIndirCallFunction; - Function *SanCovTraceEnter, *SanCovTraceBB; + Function *SanCovIndirCallFunction, *SanCovTracePCIndir; + Function *SanCovTraceEnter, *SanCovTraceBB, *SanCovTracePC; Function *SanCovTraceCmpFunction; Function *SanCovTraceSwitchFunction; InlineAsm *EmptyAsm; @@ -198,6 +205,9 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr)); SanCovWithCheckFunction = checkSanitizerInterfaceFunction( M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr)); + SanCovTracePCIndir = + checkSanitizerInterfaceFunction(M.getOrInsertFunction( + kSanCovTracePCIndir, VoidTy, IntptrTy, nullptr)); SanCovIndirCallFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr)); @@ -213,6 +223,8 @@ bool SanitizerCoverageModule::runOnModule(Module &M) { StringRef(""), StringRef(""), /*hasSideEffects=*/true); + SanCovTracePC = checkSanitizerInterfaceFunction( + M.getOrInsertFunction(kSanCovTracePC, VoidTy, nullptr)); SanCovTraceEnter = checkSanitizerInterfaceFunction( M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, Int32PtrTy, nullptr)); SanCovTraceBB = checkSanitizerInterfaceFunction( @@ -364,9 +376,13 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls( *F.getParent(), Ty, false, GlobalValue::PrivateLinkage, Constant::getNullValue(Ty), "__sancov_gen_callee_cache"); CalleeCache->setAlignment(kCacheAlignment); - IRB.CreateCall(SanCovIndirCallFunction, - {IRB.CreatePointerCast(Callee, IntptrTy), - IRB.CreatePointerCast(CalleeCache, IntptrTy)}); + if (Options.TracePC) + IRB.CreateCall(SanCovTracePCIndir, + IRB.CreatePointerCast(Callee, IntptrTy)); + else + IRB.CreateCall(SanCovIndirCallFunction, + {IRB.CreatePointerCast(Callee, IntptrTy), + IRB.CreatePointerCast(CalleeCache, IntptrTy)}); } } @@ -464,7 +480,9 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, ConstantInt::get(IntptrTy, (1 + NumberOfInstrumentedBlocks()) * 4)); Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy); - if (Options.TraceBB) { + if (Options.TracePC) { + IRB.CreateCall(SanCovTracePC); + } else if (Options.TraceBB) { IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP); } else if (UseCalls) { IRB.CreateCall(SanCovWithCheckFunction, GuardP); diff --git a/test/Instrumentation/SanitizerCoverage/coverage.ll b/test/Instrumentation/SanitizerCoverage/coverage.ll index 71fdbbb5ada..f7fa983a002 100644 --- a/test/Instrumentation/SanitizerCoverage/coverage.ll +++ b/test/Instrumentation/SanitizerCoverage/coverage.ll @@ -6,6 +6,7 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=1 -S | FileCheck %s --check-prefix=CHECK_WITH_CHECK ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-block-threshold=10 -S | FileCheck %s --check-prefix=CHECK3 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -S | FileCheck %s --check-prefix=CHECK4 +; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_INDIR ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-8bit-counters=1 -S | FileCheck %s --check-prefix=CHECK-8BIT ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=10 \ @@ -120,6 +121,11 @@ entry: ; CHECK4-NOT: call void @__sanitizer_cov_indir_call16({{.*}},[[CACHE]]) ; CHECK4: ret void +; CHECK_TRACE_PC_INDIR-LABEL: define void @CallViaVptr +; CHECK_TRACE_PC_INDIR: call void @__sanitizer_cov_trace_pc_indir +; CHECK_TRACE_PC_INDIR: call void @__sanitizer_cov_trace_pc_indir +; CHECK_TRACE_PC_INDIR: ret void + define void @call_unreachable() uwtable sanitize_address { entry: unreachable diff --git a/test/Instrumentation/SanitizerCoverage/tracing.ll b/test/Instrumentation/SanitizerCoverage/tracing.ll index 8c3a6df93a0..e6b9ae8538a 100644 --- a/test/Instrumentation/SanitizerCoverage/tracing.ll +++ b/test/Instrumentation/SanitizerCoverage/tracing.ll @@ -1,6 +1,7 @@ ; Test -sanitizer-coverage-experimental-tracing ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK3 +; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC 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" @@ -31,3 +32,11 @@ entry: ; CHECK3: call void @__sanitizer_cov_trace_basic_block ; CHECK3-NOT: call void @__sanitizer_cov_trace_basic_block ; CHECK3: ret void + +; CHECK_PC-LABEL: define void @foo +; CHECK_PC: call void @__sanitizer_cov_trace_pc +; CHECK_PC: call void @__sanitizer_cov_trace_pc +; CHECK_PC: call void @__sanitizer_cov_trace_pc +; CHECK_PC: call void @__sanitizer_cov_trace_pc +; CHECK_PC-NOT: call void @__sanitizer_cov_trace_pc +; CHECK_PC: ret void -- 2.11.0