llvm.org GIT mirror llvm / a8fed47
[sanitizer-coverage] Change cmp instrumentation to distinguish const operands This implementation of SanitizerCoverage instrumentation inserts different callbacks depending on constantness of operands: 1. If both operands are non-const, then a usual __sanitizer_cov_trace_cmp[1248] call is inserted. 2. If exactly one operand is const, then a __sanitizer_cov_trace_const_cmp[1248] call is inserted. The first argument of the call is always the constant one. 3. If both operands are const, then no callback is inserted. This separation comes useful in fuzzing when tasks like "find one operand of the comparison in input arguments and replace it with the other one" have to be done. The new instrumentation allows us to not waste time on searching the constant operands in the input. Patch by Victor Chibotaru. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310600 91177308-0d34-0410-b5e6-96231b3b80d8 Alexander Potapenko 2 years ago
2 changed file(s) with 104 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
4545 static const char *const SanCovTraceCmp2 = "__sanitizer_cov_trace_cmp2";
4646 static const char *const SanCovTraceCmp4 = "__sanitizer_cov_trace_cmp4";
4747 static const char *const SanCovTraceCmp8 = "__sanitizer_cov_trace_cmp8";
48 static const char *const SanCovTraceConstCmp1 =
49 "__sanitizer_cov_trace_const_cmp1";
50 static const char *const SanCovTraceConstCmp2 =
51 "__sanitizer_cov_trace_const_cmp2";
52 static const char *const SanCovTraceConstCmp4 =
53 "__sanitizer_cov_trace_const_cmp4";
54 static const char *const SanCovTraceConstCmp8 =
55 "__sanitizer_cov_trace_const_cmp8";
4856 static const char *const SanCovTraceDiv4 = "__sanitizer_cov_trace_div4";
4957 static const char *const SanCovTraceDiv8 = "__sanitizer_cov_trace_div8";
5058 static const char *const SanCovTraceGep = "__sanitizer_cov_trace_gep";
203211 Function *SanCovTracePCIndir;
204212 Function *SanCovTracePC, *SanCovTracePCGuard;
205213 Function *SanCovTraceCmpFunction[4];
214 Function *SanCovTraceConstCmpFunction[4];
206215 Function *SanCovTraceDivFunction[2];
207216 Function *SanCovTraceGepFunction;
208217 Function *SanCovTraceSwitchFunction;
209218 InlineAsm *EmptyAsm;
210219 Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
211 *Int8Ty, *Int8PtrTy;
220 *Int16Ty, *Int8Ty, *Int8PtrTy;
212221 Module *CurModule;
213222 Triple TargetTriple;
214223 LLVMContext *C;
280289 Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
281290 Int64Ty = IRB.getInt64Ty();
282291 Int32Ty = IRB.getInt32Ty();
292 Int16Ty = IRB.getInt16Ty();
283293 Int8Ty = IRB.getInt8Ty();
284294
285295 SanCovTracePCIndir = checkSanitizerInterfaceFunction(
297307 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
298308 SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty));
299309
310 SanCovTraceConstCmpFunction[0] =
311 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
312 SanCovTraceConstCmp1, VoidTy, Int8Ty, Int8Ty));
313 SanCovTraceConstCmpFunction[1] =
314 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
315 SanCovTraceConstCmp2, VoidTy, Int16Ty, Int16Ty));
316 SanCovTraceConstCmpFunction[2] =
317 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
318 SanCovTraceConstCmp4, VoidTy, Int32Ty, Int32Ty));
319 SanCovTraceConstCmpFunction[3] =
320 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
321 SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty));
322
300323 SanCovTraceDivFunction[0] =
301324 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
302325 SanCovTraceDiv4, VoidTy, IRB.getInt32Ty()));
315338 for (int i = 0; i < 3; i++) {
316339 SanCovTraceCmpFunction[i]->addParamAttr(0, Attribute::ZExt);
317340 SanCovTraceCmpFunction[i]->addParamAttr(1, Attribute::ZExt);
341 SanCovTraceConstCmpFunction[i]->addParamAttr(0, Attribute::ZExt);
342 SanCovTraceConstCmpFunction[i]->addParamAttr(1, Attribute::ZExt);
318343 }
319344 SanCovTraceDivFunction[0]->addParamAttr(0, Attribute::ZExt);
320345 }
643668 TypeSize == 64 ? 3 : -1;
644669 if (CallbackIdx < 0) continue;
645670 // __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);
671 auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx];
672 bool FirstIsConst = isa(A0);
673 bool SecondIsConst = isa(A1);
674 // If both are const, then we don't need such a comparison.
675 if (FirstIsConst && SecondIsConst) continue;
676 // If only one is const, then make it the first callback argument.
677 if (FirstIsConst || SecondIsConst) {
678 CallbackFunc = SanCovTraceConstCmpFunction[CallbackIdx];
679 if (SecondIsConst)
680 std::swap(A0, A1);
681 }
682
646683 auto Ty = Type::getIntNTy(*C, TypeSize);
647 IRB.CreateCall(
648 SanCovTraceCmpFunction[CallbackIdx],
649 {IRB.CreateIntCast(A0, Ty, true), IRB.CreateIntCast(A1, Ty, true)});
684 IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, Ty, true),
685 IRB.CreateIntCast(A1, Ty, true)});
650686 }
651687 }
652688 }
0 ; Test -sanitizer-coverage-trace-compares=1
1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
2
3 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"
4 target triple = "x86_64-unknown-linux-gnu"
5 define i32 @foo(i32 %a, i32 %b) #0 {
6 entry:
7
8 ; compare (non-const, non-const)
9 %cmp = icmp slt i32 %a, %b
10 ; CHECK: call void @__sanitizer_cov_trace_cmp4
11 ; CHECK-NEXT: icmp slt i32 %a, %b
12
13 ; compare (const, non-const)
14 icmp slt i32 %a, 1
15 ; CHECK: call void @__sanitizer_cov_trace_const_cmp4(i32 1, i32 %a)
16 ; CHECK-NEXT: icmp slt i32 %a, 1
17
18 ; compare (non-const, const)
19 icmp slt i32 1, %a
20 ; CHECK: call void @__sanitizer_cov_trace_const_cmp4(i32 1, i32 %a)
21 ; CHECK-NEXT: icmp slt i32 1, %a
22
23 ; compare (const, const) - should not be instrumented
24 icmp slt i32 1, 0
25 ; CHECK-NOT: call void @__sanitizer_cov_trace
26 ; CHECK icmp slt i32 1, 0
27
28 ; compare variables of byte size
29 %x = trunc i32 %a to i8
30
31 icmp slt i8 %x, 1
32 ; CHECK: call void @__sanitizer_cov_trace_const_cmp1(i8 1, i8 %x)
33 ; CHECK-NEXT: icmp slt i8 %x, 1
34
35 icmp slt i8 1, %x
36 ; CHECK: call void @__sanitizer_cov_trace_const_cmp1(i8 1, i8 %x)
37 ; CHECK-NEXT: icmp slt i8 1, %x
38
39 ; compare variables of word size
40 %y = trunc i32 %a to i16
41
42 icmp slt i16 %y, 1
43 ; CHECK: call void @__sanitizer_cov_trace_const_cmp2(i16 1, i16 %y)
44 ; CHECK-NEXT: icmp slt i16 %y, 1
45
46 icmp slt i16 1, %y
47 ; CHECK: call void @__sanitizer_cov_trace_const_cmp2(i16 1, i16 %y)
48 ; CHECK-NEXT: icmp slt i16 1, %y
49
50 ; compare variables of qword size
51 %z = zext i32 %a to i64
52
53 icmp slt i64 %z, 1
54 ; CHECK: call void @__sanitizer_cov_trace_const_cmp8(i64 1, i64 %z)
55 ; CHECK-NEXT: icmp slt i64 %z, 1
56
57 icmp slt i64 1, %z
58 ; CHECK: call void @__sanitizer_cov_trace_const_cmp8(i64 1, i64 %z)
59 ; CHECK-NEXT: icmp slt i64 1, %z
60
61 %conv = zext i1 %cmp to i32
62 ret i32 %conv
63 }