[PATCH] D133157: Add -sanitizer-coverage-control-flow
Navidem updated this revision to Diff 457734. Navidem added a comment. Herald added subscribers: cfe-commits, ormris, MaskRay. Herald added a project: clang. Updated docs, lit test, and added clang option. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(i32* %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x i64*] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global i64* +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global i64* Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -80,6 +80,7 @@ const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +148,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +198,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +218,7 @@ PostDomTreeCallback PDTCallback); private: + void CollectFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +277,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +386,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +511,10 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Options.CollectControlFlow) +CreateSecStartEnd(M, SanCovCFsSectionName, IntptrPtrTy); + appendToUsed(M, GlobalsToAppendToUsed); appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); return true; @@ -671,6 +684,9 @@ } } + if (Options.CollectControlFlow) +CollectFunctionControlFlow(F); + InjectCoverage(F, BlocksToInstrume
[PATCH] D133157: Add -sanitizer-coverage-control-flow
Navidem added inline comments. Comment at: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp:1055 + for (auto &BB: F) { +// blockaddress may not be used on function's entry block. +if (&BB == &F.getEntryBlock()) Navidem wrote: > kcc wrote: > > vitalybuka wrote: > > > what does happen? > > "can not" ? > Actually I started with "can not", but saw the error message from opt saying > "may not". Changing anyways :) Gives invalid IR error if `blockaddress` is used with function entry as arg. Comment at: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp:1057 +if (&BB == &F.getEntryBlock()) + CFs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); +else vitalybuka wrote: > static_cast or dyn_cast Please check lines 739-746. This usage pattern is already there. Should we change those as well? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D133157: Add -sanitizer-coverage-control-flow
Navidem added inline comments. Comment at: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll:2 +; Test -sanitizer-coverage-control-flow +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -S | FileCheck %s + vitalybuka wrote: > you don't have to, but may try to generate test with > llvm/utils/update_test_checks.py --opt-binary bin/opt > llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll > > It could be reasonable, or not Thanks! I tried it and it added many more checks, which does not seem very useful? Please let me know if you see some value in having these: ``` +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry: +; CHECK-NEXT:call void @__sanitizer_cov_trace_pc_guard(i32* getelementptr inbounds ([3 x i32], [3 x i32]* @__sancov_gen_.1, i32 0, i32 0)) #[[ATTR2:[0-9]+]] +; CHECK-NEXT:[[TOBOOL:%.*]] = icmp eq i32* [[A:%.*]], null +; CHECK-NEXT:br i1 [[TOBOOL]], label [[ENTRY_IF_END_CRIT_EDGE:%.*]], label [[IF_THEN:%.*]] +; CHECK: entry.if.end_crit_edge: +; CHECK-NEXT:call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([3 x i32]* @__sancov_gen_.1 to i64), i64 4) to i32*)) #[[ATTR2]] +; CHECK-NEXT:br label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT:call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([3 x i32]* @__sancov_gen_.1 to i64), i64 8) to i32*)) #[[ATTR2]] +; CHECK-NEXT:store i32 0, i32* [[A]], align 4 +; CHECK-NEXT:call void @foo(i32* [[A]]) +; CHECK-NEXT:br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT:ret void +; ``` Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D133157: Add -sanitizer-coverage-control-flow
Navidem updated this revision to Diff 457754. Navidem added a comment. Herald added a project: Sanitizers. Herald added a subscriber: Sanitizers. Added an initial run-time test Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(i32* %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x i64*] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global i64* +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global i64* Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -80,6 +80,7 @@ const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +148,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +198,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +218,7 @@ PostDomTreeCallback PDTCallback); private: + void CollectFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +277,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +386,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +511,10 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Options.CollectControlFlow) +CreateSecStartEnd(M, SanCovCFsSectionName, IntptrPtrTy); + appendToUsed(M, GlobalsToAppendToUsed); appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); return true; @@ -671,6 +684,9 @@ } } + if (Options.CollectControlFlow) +CollectFunctionC
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem updated this revision to Diff 458321. Navidem added a comment. Apply comments. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow. +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(ptr %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x i64*] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global i64* +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global i64* Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -80,6 +80,7 @@ const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +148,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +198,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +218,7 @@ PostDomTreeCallback PDTCallback); private: + void createFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +277,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +386,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +511,10 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Options.CollectControlFlow) +CreateSecStartEnd(M, SanCovCFsSectionName, IntptrPtrTy); + appendToUsed(M, GlobalsToAppendToUsed); appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); return true; @@ -671,6 +684,9 @@ } } + if (Options.CollectControlFlow) +createFunctionControlFlow(F); + InjectCoverage(F, BlocksToInstrument, IsLeafFunc); InjectCoverageForIndirectCalls(F, IndirCalls); InjectTraceForCmp(F, CmpTraceTargets); @@ -1028,3 +
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem updated this revision to Diff 458958. Navidem added a comment. Add __sanitizer_cov_cfs_init Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow. +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(ptr %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x ptr] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -75,11 +75,13 @@ const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; +const char SanCovCFsInitName[] = "__sanitizer_cov_cfs_init"; const char SanCovGuardsSectionName[] = "sancov_guards"; const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +149,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +199,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +219,7 @@ PostDomTreeCallback PDTCallback); private: + void createFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +278,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +387,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +512,15 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Ctor && Options.CollectControlFlow) { +auto SecStartEnd = CreateSecStartEnd(M, SanCovCFsSectionName, IntptrPtrTy); +FunctionC
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem updated this revision to Diff 459157. Navidem added a comment. Update doc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow. +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(ptr %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x ptr] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -75,11 +75,13 @@ const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; +const char SanCovCFsInitName[] = "__sanitizer_cov_cfs_init"; const char SanCovGuardsSectionName[] = "sancov_guards"; const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +149,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +199,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +219,7 @@ PostDomTreeCallback PDTCallback); private: + void createFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +278,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +387,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +512,15 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Ctor && Options.CollectControlFlow) { +auto SecStartEnd = CreateSecStartEnd(M, SanCovCFsSectionName, IntptrPtrTy); +FunctionCallee InitFunction
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem marked an inline comment as done and an inline comment as not done. Navidem added inline comments. Comment at: clang/lib/Driver/SanitizerArgs.cpp:807 << "-fsanitize-coverage=[func|bb|edge]" -<< "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]"; +<< "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc|control-flow]"; } vitalybuka wrote: > shouldn't this be: > ,[trace-pc-guard|trace-pc],[control-flow] > > probably even: > [,(trace-pc-guard|trace-pc)][,control-flow] > shouldn't this be: > ,[trace-pc-guard|trace-pc],[control-flow] > > probably even: > [,(trace-pc-guard|trace-pc)][,control-flow] Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem updated this revision to Diff 459201. Navidem added a comment. Bring back the runtime test. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow. +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(ptr %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x ptr] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -75,11 +75,13 @@ const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; +const char SanCovCFsInitName[] = "__sanitizer_cov_cfs_init"; const char SanCovGuardsSectionName[] = "sancov_guards"; const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +149,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +199,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +219,7 @@ PostDomTreeCallback PDTCallback); private: + void createFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +278,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +387,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +512,15 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Ctor && Options.CollectControlFlow) { +auto Se
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem added inline comments. Comment at: clang/lib/Driver/SanitizerArgs.cpp:814 (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters | - CoverageInlineBoolFlag)) + CoverageInlineBoolFlag | CoverageControlFlow)) CoverageFeatures |= CoverageEdge; vitalybuka wrote: > why do you need CoverageEdge if enabled CoverageControlFlow? No essential need, but here I am implicitly enabling `edge` when instrumentation type is not specified. This was the way that I could get `-fsanitizer-coverage=control-flow` working without passing `-fsanitizer-coverage=bb,control-flow`. Comment at: clang/lib/Driver/SanitizerArgs.cpp:807 << "-fsanitize-coverage=[func|bb|edge]" -<< "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]"; +<< "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc|control-flow]"; } Navidem wrote: > vitalybuka wrote: > > shouldn't this be: > > ,[trace-pc-guard|trace-pc],[control-flow] > > > > probably even: > > [,(trace-pc-guard|trace-pc)][,control-flow] > > shouldn't this be: > > ,[trace-pc-guard|trace-pc],[control-flow] > > > > probably even: > > [,(trace-pc-guard|trace-pc)][,control-flow] > > > shouldn't this be: > ,[trace-pc-guard|trace-pc],[control-flow] This makes sense, thanks! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem updated this revision to Diff 460215. Navidem added a comment. Update the rt test Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow. +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(ptr %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x ptr] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -75,11 +75,13 @@ const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; +const char SanCovCFsInitName[] = "__sanitizer_cov_cfs_init"; const char SanCovGuardsSectionName[] = "sancov_guards"; const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +149,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +199,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +219,7 @@ PostDomTreeCallback PDTCallback); private: + void createFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +278,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +387,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +512,15 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Ctor && Options.CollectControlFlow) { +auto SecStartEnd
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem updated this revision to Diff 460232. Navidem added a comment. Enhance rt test. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow. +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(ptr %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x ptr] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -75,11 +75,13 @@ const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; +const char SanCovCFsInitName[] = "__sanitizer_cov_cfs_init"; const char SanCovGuardsSectionName[] = "sancov_guards"; const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +149,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +199,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +219,7 @@ PostDomTreeCallback PDTCallback); private: + void createFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +278,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +387,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +512,15 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Ctor && Options.CollectControlFlow) { +auto SecStartEnd =
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem marked an inline comment as done. Navidem added inline comments. Comment at: compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp:15 +extern "C" void __sanitizer_cov_cfs_init(const uintptr_t *cfs_beg, + const uintptr_t *cfs_end) { + CFS_BEG = (uintptr_t *)cfs_beg; vitalybuka wrote: > vitalybuka wrote: > > would you like to add some printing function as for other coverage types? > actually printing can be don't in follow up patch, but it may simplify the > test, you will not need iterate it in the test. > actually printing can be don't in follow up patch, but it may simplify the > test, you will not need iterate it in the test. I'm not sure I follow what you are suggesting. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem updated this revision to Diff 460251. Navidem added a comment. Use CHECK-DAG and separate function for checking. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp llvm/include/llvm/Transforms/Instrumentation.h llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll Index: llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll === --- /dev/null +++ llvm/test/Instrumentation/SanitizerCoverage/control-flow.ll @@ -0,0 +1,22 @@ +; Test -sanitizer-coverage-control-flow. +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -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 triple = "x86_64-unknown-linux-gnu" +define void @foo(ptr %a) sanitize_address { +entry: + %tobool = icmp eq i32* %a, null + br i1 %tobool, label %if.end, label %if.then + + if.then: ; preds = %entry + store i32 0, i32* %a, align 4 + call void @foo(i32* %a) + br label %if.end + + if.end: ; preds = %entry, %if.then + ret void +} + +; CHECK: private constant [17 x ptr] [{{.*}}@foo{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}blockaddress{{.*}}@foo{{.*}}null{{.*}}null], section "__sancov_cfs", comdat($foo), align 8 +; CHECK: @__start___sancov_cfs = extern_weak hidden global +; CHECK-NEXT: @__stop___sancov_cfs = extern_weak hidden global Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp === --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -75,11 +75,13 @@ const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; +const char SanCovCFsInitName[] = "__sanitizer_cov_cfs_init"; const char SanCovGuardsSectionName[] = "sancov_guards"; const char SanCovCountersSectionName[] = "sancov_cntrs"; const char SanCovBoolFlagSectionName[] = "sancov_bools"; const char SanCovPCsSectionName[] = "sancov_pcs"; +const char SanCovCFsSectionName[] = "sancov_cfs"; const char SanCovLowestStackName[] = "__sancov_lowest_stack"; @@ -147,6 +149,10 @@ cl::desc("max stack depth tracing"), cl::Hidden, cl::init(false)); +static cl::opt ClCollectCF("sanitizer-coverage-control-flow", + cl::desc("collect control flow for each function"), + cl::Hidden, cl::init(false)); + namespace { SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { @@ -193,6 +199,7 @@ !Options.Inline8bitCounters && !Options.StackDepth && !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. + Options.CollectControlFlow |= ClCollectCF; return Options; } @@ -212,6 +219,7 @@ PostDomTreeCallback PDTCallback); private: + void createFunctionControlFlow(Function &F); void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, @@ -270,6 +278,7 @@ GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. GlobalVariable *FunctionBoolArray; // for inline-bool-flag. GlobalVariable *FunctionPCsArray; // for pc-table. + GlobalVariable *FunctionCFsArray; // for control flow table SmallVector GlobalsToAppendToUsed; SmallVector GlobalsToAppendToCompilerUsed; @@ -378,6 +387,7 @@ Function8bitCounterArray = nullptr; FunctionBoolArray = nullptr; FunctionPCsArray = nullptr; + FunctionCFsArray = nullptr; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); @@ -502,6 +512,15 @@ IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); } + + if (Ctor && Options.CollectContro
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem marked 3 inline comments as done. Navidem added inline comments. Comment at: compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp:15 +extern "C" void __sanitizer_cov_cfs_init(const uintptr_t *cfs_beg, + const uintptr_t *cfs_end) { + CFS_BEG = (uintptr_t *)cfs_beg; vitalybuka wrote: > Navidem wrote: > > vitalybuka wrote: > > > vitalybuka wrote: > > > > would you like to add some printing function as for other coverage > > > > types? > > > actually printing can be don't in follow up patch, but it may simplify > > > the test, you will not need iterate it in the test. > > > actually printing can be don't in follow up patch, but it may simplify > > > the test, you will not need iterate it in the test. > > > > I'm not sure I follow what you are suggesting. > Check this out D108405 > then you can hook your data into DumpCoverage() > then you can replace entire "while (pt < CFS_END) {" loop with set of CHECK: > Check this out D108405 > then you can hook your data into DumpCoverage() > then you can replace entire "while (pt < CFS_END) {" loop with set of CHECK: I see, thanks for the pointer. I think I leave it for later. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D133157: Add -fsanitizer-coverage=control-flow
Navidem added a comment. Thanks @kcc @vitalybuka, I do not have commit access. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133157/new/ https://reviews.llvm.org/D133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits