llvm.org GIT mirror llvm / d016c6f
[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 Kostya Serebryany 4 years ago
4 changed file(s) with 41 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
119119 struct SanitizerCoverageOptions {
120120 SanitizerCoverageOptions()
121121 : CoverageType(SCK_None), IndirectCalls(false), TraceBB(false),
122 TraceCmp(false), Use8bitCounters(false) {}
122 TraceCmp(false), Use8bitCounters(false), TracePC(false) {}
123123
124124 enum Type {
125125 SCK_None = 0,
131131 bool TraceBB;
132132 bool TraceCmp;
133133 bool Use8bitCounters;
134 bool TracePC;
134135 };
135136
136137 // Insert SanitizerCoverage instrumentation.
5656 static const char *const kSanCovName = "__sanitizer_cov";
5757 static const char *const kSanCovWithCheckName = "__sanitizer_cov_with_check";
5858 static const char *const kSanCovIndirCallName = "__sanitizer_cov_indir_call16";
59 static const char *const kSanCovTracePCIndir = "__sanitizer_cov_trace_pc_indir";
5960 static const char *const kSanCovTraceEnter = "__sanitizer_cov_trace_func_enter";
6061 static const char *const kSanCovTraceBB = "__sanitizer_cov_trace_basic_block";
62 static const char *const kSanCovTracePC = "__sanitizer_cov_trace_pc";
6163 static const char *const kSanCovTraceCmp = "__sanitizer_cov_trace_cmp";
6264 static const char *const kSanCovTraceSwitch = "__sanitizer_cov_trace_switch";
6365 static const char *const kSanCovModuleCtorName = "sancov.module_ctor";
8082 cl::desc("Experimental basic-block tracing: insert "
8183 "callbacks at every basic block"),
8284 cl::Hidden, cl::init(false));
85
86 static cl::opt ClExperimentalTracePC("sanitizer-coverage-trace-pc",
87 cl::desc("Experimental pc tracing"),
88 cl::Hidden, cl::init(false));
8389
8490 static cl::opt
8591 ClExperimentalCMPTracing("sanitizer-coverage-experimental-trace-compares",
130136 Options.TraceBB |= ClExperimentalTracing;
131137 Options.TraceCmp |= ClExperimentalCMPTracing;
132138 Options.Use8bitCounters |= ClUse8bitCounters;
139 Options.TracePC |= ClExperimentalTracePC;
133140 return Options;
134141 }
135142
161168 }
162169 Function *SanCovFunction;
163170 Function *SanCovWithCheckFunction;
164 Function *SanCovIndirCallFunction;
165 Function *SanCovTraceEnter, *SanCovTraceBB;
171 Function *SanCovIndirCallFunction, *SanCovTracePCIndir;
172 Function *SanCovTraceEnter, *SanCovTraceBB, *SanCovTracePC;
166173 Function *SanCovTraceCmpFunction;
167174 Function *SanCovTraceSwitchFunction;
168175 InlineAsm *EmptyAsm;
197204 M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr));
198205 SanCovWithCheckFunction = checkSanitizerInterfaceFunction(
199206 M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr));
207 SanCovTracePCIndir =
208 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
209 kSanCovTracePCIndir, VoidTy, IntptrTy, nullptr));
200210 SanCovIndirCallFunction =
201211 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
202212 kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr));
212222 StringRef(""), StringRef(""),
213223 /*hasSideEffects=*/true);
214224
225 SanCovTracePC = checkSanitizerInterfaceFunction(
226 M.getOrInsertFunction(kSanCovTracePC, VoidTy, nullptr));
215227 SanCovTraceEnter = checkSanitizerInterfaceFunction(
216228 M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, Int32PtrTy, nullptr));
217229 SanCovTraceBB = checkSanitizerInterfaceFunction(
363375 *F.getParent(), Ty, false, GlobalValue::PrivateLinkage,
364376 Constant::getNullValue(Ty), "__sancov_gen_callee_cache");
365377 CalleeCache->setAlignment(kCacheAlignment);
366 IRB.CreateCall(SanCovIndirCallFunction,
367 {IRB.CreatePointerCast(Callee, IntptrTy),
368 IRB.CreatePointerCast(CalleeCache, IntptrTy)});
378 if (Options.TracePC)
379 IRB.CreateCall(SanCovTracePCIndir,
380 IRB.CreatePointerCast(Callee, IntptrTy));
381 else
382 IRB.CreateCall(SanCovIndirCallFunction,
383 {IRB.CreatePointerCast(Callee, IntptrTy),
384 IRB.CreatePointerCast(CalleeCache, IntptrTy)});
369385 }
370386 }
371387
463479 ConstantInt::get(IntptrTy, (1 + NumberOfInstrumentedBlocks()) * 4));
464480 Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
465481 GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy);
466 if (Options.TraceBB) {
482 if (Options.TracePC) {
483 IRB.CreateCall(SanCovTracePC);
484 } else if (Options.TraceBB) {
467485 IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
468486 } else if (UseCalls) {
469487 IRB.CreateCall(SanCovWithCheckFunction, GuardP);
55 ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=1 -S | FileCheck %s --check-prefix=CHECK_WITH_CHECK
66 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-block-threshold=10 -S | FileCheck %s --check-prefix=CHECK3
77 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -S | FileCheck %s --check-prefix=CHECK4
8 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_INDIR
89 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-8bit-counters=1 -S | FileCheck %s --check-prefix=CHECK-8BIT
910
1011 ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=10 \
119120 ; CHECK4-NOT: call void @__sanitizer_cov_indir_call16({{.*}},[[CACHE]])
120121 ; CHECK4: ret void
121122
123 ; CHECK_TRACE_PC_INDIR-LABEL: define void @CallViaVptr
124 ; CHECK_TRACE_PC_INDIR: call void @__sanitizer_cov_trace_pc_indir
125 ; CHECK_TRACE_PC_INDIR: call void @__sanitizer_cov_trace_pc_indir
126 ; CHECK_TRACE_PC_INDIR: ret void
127
122128 define void @call_unreachable() uwtable sanitize_address {
123129 entry:
124130 unreachable
0 ; Test -sanitizer-coverage-experimental-tracing
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK1
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK3
3 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC
34
45 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"
56 target triple = "x86_64-unknown-linux-gnu"
3031 ; CHECK3: call void @__sanitizer_cov_trace_basic_block
3132 ; CHECK3-NOT: call void @__sanitizer_cov_trace_basic_block
3233 ; CHECK3: ret void
34
35 ; CHECK_PC-LABEL: define void @foo
36 ; CHECK_PC: call void @__sanitizer_cov_trace_pc
37 ; CHECK_PC: call void @__sanitizer_cov_trace_pc
38 ; CHECK_PC: call void @__sanitizer_cov_trace_pc
39 ; CHECK_PC: call void @__sanitizer_cov_trace_pc
40 ; CHECK_PC-NOT: call void @__sanitizer_cov_trace_pc
41 ; CHECK_PC: ret void