leonardchan created this revision. leonardchan added reviewers: chandlerc, fedor.sergeev, philip.pfaffe. leonardchan added a project: Sanitizers. Herald added subscribers: cfe-commits, hiraditya. Herald added projects: clang, LLVM.
This patch merges the sancov module and funciton passes into one module pass. The reason for this is because we ran into an out of memory error when attempting to run asan fuzzer on some protobufs (pc.cc files). I traced the OOM error to the destructor of `SanitizerCoverage` where we only call `appendTo[Compiler]Used` which calls `appendToUsedList`. I'm not sure where precisely in `appendToUsedList` causes the OOM, but I am able to confirm that it's calling this function *repeatedly* that causes the OOM. (I hacked sancov a bit such that I can still create and destroy a new sancov on every function run, but only call `appendToUsedList` after all functions in the module have finished. This passes, but when I make it such that `appendToUsedList` is called on every sancov destruction, we hit OOM.) I don't think the OOM is from just adding to the `SmallSet` and `SmallVector` inside `appendToUsedList` since in either case for a given module, they'll have the same max size. I suspect that when the existing `llvm.compiler.used` global is erased, the memory behind it isn't freed. I could be wrong on this though. This patch works around the OOM issue by just calling `appendToUsedList` at the end of every module run instead of function run. The same amount of constants still get added to `llvm.compiler.used`, abd we make the pass usage and logic simpler by not having any inter-pass dependencies. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D66988 Files: clang/lib/CodeGen/BackendUtil.cpp llvm/include/llvm/InitializePasses.h llvm/include/llvm/Transforms/Instrumentation/SanitizerCoverage.h llvm/lib/Passes/PassRegistry.def llvm/lib/Transforms/Instrumentation/Instrumentation.cpp llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/test/Instrumentation/SanitizerCoverage/abort-in-entry-block.ll llvm/test/Instrumentation/SanitizerCoverage/backedge-pruning.ll llvm/test/Instrumentation/SanitizerCoverage/chains.ll llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_64.ll llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll llvm/test/Instrumentation/SanitizerCoverage/coff-comdat.ll llvm/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-8bit-counters.ll llvm/test/Instrumentation/SanitizerCoverage/coff-used-ctor.ll llvm/test/Instrumentation/SanitizerCoverage/const-cmp-tracing.ll llvm/test/Instrumentation/SanitizerCoverage/coverage-dbg.ll llvm/test/Instrumentation/SanitizerCoverage/coverage.ll llvm/test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll llvm/test/Instrumentation/SanitizerCoverage/div-tracing.ll llvm/test/Instrumentation/SanitizerCoverage/gep-tracing.ll llvm/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll llvm/test/Instrumentation/SanitizerCoverage/interposable-symbol-nocomdat.ll llvm/test/Instrumentation/SanitizerCoverage/no-func.ll llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll llvm/test/Instrumentation/SanitizerCoverage/postdominator_check.ll llvm/test/Instrumentation/SanitizerCoverage/seh.ll llvm/test/Instrumentation/SanitizerCoverage/stack-depth-variable-declared-by-user.ll llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll llvm/test/Instrumentation/SanitizerCoverage/switch-tracing.ll llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-comdat.ll llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-8bit-counters.ll llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-nocomdat.ll llvm/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll llvm/test/Instrumentation/SanitizerCoverage/tracing.ll llvm/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll llvm/test/Instrumentation/SanitizerCoverage/wineh.ll
Index: llvm/test/Instrumentation/SanitizerCoverage/wineh.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/wineh.ll +++ llvm/test/Instrumentation/SanitizerCoverage/wineh.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK ; Generated from this C++ source: ; $ clang -O2 t.cpp -S -emit-llvm Index: llvm/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll +++ llvm/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -S -sancov -sanitizer-coverage-level=3 | FileCheck %s -; RUN: opt < %s -S -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 | FileCheck %s +; RUN: opt < %s -S -passes='module(sancov-module)' -sanitizer-coverage-level=3 | FileCheck %s ; The critical edges to unreachable_bb should not be split. define i32 @foo(i32 %c, i32 %d) { Index: llvm/test/Instrumentation/SanitizerCoverage/tracing.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/tracing.ll +++ llvm/test/Instrumentation/SanitizerCoverage/tracing.ll @@ -3,9 +3,9 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S -mtriple=x86_64-apple-macosx | FileCheck %s --check-prefix=CHECK_PC_GUARD_DARWIN -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S -mtriple=x86_64-apple-macosx | FileCheck %s --check-prefix=CHECK_PC_GUARD_DARWIN +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S -mtriple=x86_64-apple-macosx | FileCheck %s --check-prefix=CHECK_PC_GUARD_DARWIN 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" Index: llvm/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll +++ llvm/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll @@ -3,8 +3,8 @@ ; Make sure asan does not instrument __sancov_gen_ ; RUN: opt < %s -sancov -asan -asan-module -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s -; RUN: opt < %s -passes='module(require<asan-globals-md>,sancov-module,asan-module),function(sancov-func,asan)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s +; RUN: opt < %s -passes='module(require<asan-globals-md>,sancov-module,asan-module),function(asan)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" $Foo = comdat any Index: llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-nocomdat.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-nocomdat.ll +++ llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-nocomdat.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD 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-apple-darwin10.0.0" Index: llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-8bit-counters.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-8bit-counters.ll +++ llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-8bit-counters.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s ; Module ctors should have stable names across modules, not something like ; @sancov.module_ctor.3 that may cause duplicate ctors after linked together. Index: llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-comdat.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-comdat.ll +++ llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-comdat.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD 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" Index: llvm/test/Instrumentation/SanitizerCoverage/switch-tracing.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/switch-tracing.ll +++ llvm/test/Instrumentation/SanitizerCoverage/switch-tracing.ll @@ -1,6 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 (instrumenting a switch) ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -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" Index: llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll +++ llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll @@ -4,9 +4,9 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 \ ; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \ ; RUN: -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 \ +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 \ ; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 \ +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 \ ; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \ ; RUN: -S | FileCheck %s Index: llvm/test/Instrumentation/SanitizerCoverage/stack-depth-variable-declared-by-user.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/stack-depth-variable-declared-by-user.ll +++ llvm/test/Instrumentation/SanitizerCoverage/stack-depth-variable-declared-by-user.ll @@ -2,7 +2,7 @@ ; user declares `__sancov_lowest_stack` with an unexpected type. ; RUN: not opt < %s -sancov -sanitizer-coverage-level=1 \ ; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s -; RUN: not opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 \ +; RUN: not opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 \ ; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: llvm/test/Instrumentation/SanitizerCoverage/seh.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/seh.ll +++ llvm/test/Instrumentation/SanitizerCoverage/seh.ll @@ -1,9 +1,9 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=0 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=0 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=2 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=0 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 -S | FileCheck %s target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "i686-pc-windows-msvc18.0.0" Index: llvm/test/Instrumentation/SanitizerCoverage/postdominator_check.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/postdominator_check.ll +++ llvm/test/Instrumentation/SanitizerCoverage/postdominator_check.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=CHECK_NO_PRUNE -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=CHECK_NO_PRUNE +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=CHECK_NO_PRUNE define i32 @foo(i32) #0 { %2 = icmp sgt i32 %0, 0 Index: llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll +++ llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll @@ -1,8 +1,8 @@ ; Test -sanitizer-coverage-pc-table=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -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" Index: llvm/test/Instrumentation/SanitizerCoverage/no-func.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/no-func.ll +++ llvm/test/Instrumentation/SanitizerCoverage/no-func.ll @@ -1,7 +1,7 @@ ; Tests that we don't insert __sanitizer_cov_trace_pc_guard_init or some such ; when there is no instrumentation. ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: llvm/test/Instrumentation/SanitizerCoverage/interposable-symbol-nocomdat.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/interposable-symbol-nocomdat.ll +++ llvm/test/Instrumentation/SanitizerCoverage/interposable-symbol-nocomdat.ll @@ -1,8 +1,8 @@ ; Test that interposable symbols do not get put in comdats. ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s define void @Vanilla() { entry: Index: llvm/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll +++ llvm/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll @@ -1,6 +1,6 @@ ; Test -sanitizer-coverage-inline-8bit-counters=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -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" Index: llvm/test/Instrumentation/SanitizerCoverage/gep-tracing.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/gep-tracing.ll +++ llvm/test/Instrumentation/SanitizerCoverage/gep-tracing.ll @@ -1,6 +1,6 @@ ; Test -sanitizer-coverage-trace-geps=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: llvm/test/Instrumentation/SanitizerCoverage/div-tracing.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/div-tracing.ll +++ llvm/test/Instrumentation/SanitizerCoverage/div-tracing.ll @@ -1,6 +1,6 @@ ; Test -sanitizer-coverage-trace-divs=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -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" Index: llvm/test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll +++ llvm/test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll @@ -1,7 +1,7 @@ ; Test that coverage instrumentation does not lose debug location. ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=2 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 -S | FileCheck %s ; C++ source: ; 1: void foo(int *a) { Index: llvm/test/Instrumentation/SanitizerCoverage/coverage.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/coverage.ll +++ llvm/test/Instrumentation/SanitizerCoverage/coverage.ll @@ -1,8 +1,8 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE 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" Index: llvm/test/Instrumentation/SanitizerCoverage/coverage-dbg.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/coverage-dbg.ll +++ llvm/test/Instrumentation/SanitizerCoverage/coverage-dbg.ll @@ -1,7 +1,7 @@ ; Test that coverage instrumentation does not lose debug location. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -S | FileCheck %s ; C++ source: ; 1: struct A { Index: llvm/test/Instrumentation/SanitizerCoverage/const-cmp-tracing.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/const-cmp-tracing.ll +++ llvm/test/Instrumentation/SanitizerCoverage/const-cmp-tracing.ll @@ -1,6 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -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" Index: llvm/test/Instrumentation/SanitizerCoverage/coff-used-ctor.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/coff-used-ctor.ll +++ llvm/test/Instrumentation/SanitizerCoverage/coff-used-ctor.ll @@ -1,6 +1,6 @@ ; Checks that sancov.module_ctor is marked used. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc19.14.26433" Index: llvm/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-8bit-counters.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-8bit-counters.ll +++ llvm/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-8bit-counters.ll @@ -1,6 +1,6 @@ ; Checks that the PC and 8-bit Counter Arrays are placed in their own sections in COFF binaries. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc19.14.26433" Index: llvm/test/Instrumentation/SanitizerCoverage/coff-comdat.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/coff-comdat.ll +++ llvm/test/Instrumentation/SanitizerCoverage/coff-comdat.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; Make sure we use the right comdat groups for COFF to avoid relocations ; against discarded sections. Internal linkage functions are also different from Index: llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll +++ llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing.ll @@ -1,6 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -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" Index: llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_64.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_64.ll +++ llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_64.ll @@ -1,6 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 API declarations on x86_64 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s target triple = "x86_64-unknown-linux-gnu" define i32 @foo() #0 { Index: llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll +++ llvm/test/Instrumentation/SanitizerCoverage/cmp-tracing-api-x86_32.ll @@ -1,6 +1,6 @@ ; Test -sanitizer-coverage-trace-compares=1 API declarations on a non-x86_64 arch ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s target triple = "i386-unknown-linux-gnu" define i32 @foo() #0 { Index: llvm/test/Instrumentation/SanitizerCoverage/chains.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/chains.ll +++ llvm/test/Instrumentation/SanitizerCoverage/chains.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s define i32 @blah(i32) #0 { %2 = icmp sgt i32 %0, 1 Index: llvm/test/Instrumentation/SanitizerCoverage/backedge-pruning.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/backedge-pruning.ll +++ llvm/test/Instrumentation/SanitizerCoverage/backedge-pruning.ll @@ -1,8 +1,8 @@ ; Test -sanitizer-coverage-trace-compares=1 and how it prunes backedge compares. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE 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" Index: llvm/test/Instrumentation/SanitizerCoverage/abort-in-entry-block.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/abort-in-entry-block.ll +++ llvm/test/Instrumentation/SanitizerCoverage/abort-in-entry-block.ll @@ -1,6 +1,6 @@ ; Checks that a function with no-return in the entry block is not instrumented. ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s ; CHECK-NOT: call void @__sanitizer_cov_trace_pc_guard target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -177,168 +177,21 @@ return Options; } -bool canInstrumentWithSancov(const Function &F) { - if (F.empty()) - return false; - if (F.getName().find(".module_ctor") != std::string::npos) - return false; // Should not instrument sanitizer init functions. - if (F.getName().startswith("__sanitizer_")) - return false; // Don't instrument __sanitizer_* callbacks. - // Don't touch available_externally functions, their actual body is elewhere. - if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) - return false; - // Don't instrument MSVC CRT configuration helpers. They may run before normal - // initialization. - if (F.getName() == "__local_stdio_printf_options" || - F.getName() == "__local_stdio_scanf_options") - return false; - if (isa<UnreachableInst>(F.getEntryBlock().getTerminator())) - return false; - // Don't instrument functions using SEH for now. Splitting basic blocks like - // we do for coverage breaks WinEHPrepare. - // FIXME: Remove this when SEH no longer uses landingpad pattern matching. - if (F.hasPersonalityFn() && - isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) - return false; - return true; -} - -std::string getSectionStartImpl(const Triple &TargetTriple, - const std::string &Section) { - if (TargetTriple.isOSBinFormatMachO()) - return "\1section$start$__DATA$__" + Section; - return "__start___" + Section; -} +using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>; +using PostDomTreeCallback = + function_ref<const PostDominatorTree *(Function &F)>; -std::string getSectionEndImpl(const Triple &TargetTriple, - const std::string &Section) { - if (TargetTriple.isOSBinFormatMachO()) - return "\1section$end$__DATA$__" + Section; - return "__stop___" + Section; -} - -/// This is a class for instrumenting the module to add calls to initializing -/// the trace PC guards and 8bit counter globals. This should only be done -/// though if there is at least one function that can be instrumented with -/// Sancov. class ModuleSanitizerCoverage { public: - ModuleSanitizerCoverage(const SanitizerCoverageOptions &Options) + ModuleSanitizerCoverage( + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) : Options(OverrideFromCL(Options)) {} - - bool instrumentModule(Module &M) { - if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) - return false; - - Function *Ctor = nullptr; - LLVMContext *C = &(M.getContext()); - const DataLayout *DL = &M.getDataLayout(); - TargetTriple = Triple(M.getTargetTriple()); - IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); - Type *IntptrPtrTy = PointerType::getUnqual(IntptrTy); - IRBuilder<> IRB(*C); - Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); - Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); - Int8Ty = IRB.getInt8Ty(); - - // Check that the __sancov_lowest_stack marker does not already exist. - Constant *SanCovLowestStackConstant = - M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); - GlobalVariable *SanCovLowestStack = - dyn_cast<GlobalVariable>(SanCovLowestStackConstant); - if (!SanCovLowestStack) { - C->emitError(StringRef("'") + SanCovLowestStackName + - "' should not be declared by the user"); - return true; - } - - // We want to emit guard init calls if the module contains a function that - // we can instrument with SanitizerCoverage. We ignore any functions that - // were inserted by SanitizerCoverage and get the result from the analysis - // that checks for a valid function that the analysis may have run over. - if (!llvm::any_of( - M, [](const Function &F) { return canInstrumentWithSancov(F); })) - return false; - - // Emit the init calls. - if (Options.TracePCGuard) - Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName, - SanCovTracePCGuardInitName, Int32PtrTy, - SanCovGuardsSectionName); - if (Options.Inline8bitCounters) - Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName, - SanCov8bitCountersInitName, Int8PtrTy, - SanCovCountersSectionName); - if (Ctor && Options.PCTable) { - auto SecStartEnd = - CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy); - FunctionCallee InitFunction = declareSanitizerInitFunction( - M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); - IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); - IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); - } - return Ctor; - } - -private: - Function *CreateInitCallsForSections(Module &M, const char *CtorName, - const char *InitFunctionName, Type *Ty, - const char *Section); - std::pair<Value *, Value *> CreateSecStartEnd(Module &M, const char *Section, - Type *Ty); - std::string getSectionStart(const std::string &Section) const { - return getSectionStartImpl(TargetTriple, Section); - } - std::string getSectionEnd(const std::string &Section) const { - return getSectionEndImpl(TargetTriple, Section); - } - - SanitizerCoverageOptions Options; - Triple TargetTriple; - Type *IntptrTy, *Int8PtrTy, *Int8Ty; -}; - -class ModuleSanitizerCoverageLegacyPass : public ModulePass { -public: - static char ID; - - ModuleSanitizerCoverageLegacyPass( - SanitizerCoverageOptions Options = SanitizerCoverageOptions()) - : ModulePass(ID), Options(Options) { - initializeModuleSanitizerCoverageLegacyPassPass( - *PassRegistry::getPassRegistry()); - } - - bool runOnModule(Module &M) override { - ModuleSanitizerCoverage ModuleSancov(Options); - return ModuleSancov.instrumentModule(M); - }; - - StringRef getPassName() const override { - return "ModuleSanitizerCoverageLegacyPass"; - } - -private: - SanitizerCoverageOptions Options; -}; - -char ModuleSanitizerCoverageLegacyPass::ID = 0; - -class SanitizerCoverage { -public: - SanitizerCoverage(Function &F, const SanitizerCoverageOptions &Options) - : CurModule(F.getParent()), Options(OverrideFromCL(Options)) { - initializeModule(*F.getParent()); - } - - ~SanitizerCoverage() { finalizeModule(*CurModule); } - - bool instrumentFunction(Function &F, const DominatorTree *DT, - const PostDominatorTree *PDT); + bool instrumentModule(Module &M, DomTreeCallback DTCallback, + PostDomTreeCallback PDTCallback); private: - void initializeModule(Module &M); - void finalizeModule(Module &M); + void instrumentFunction(Function &F, DomTreeCallback DTCallback, + PostDomTreeCallback PDTCallback); void InjectCoverageForIndirectCalls(Function &F, ArrayRef<Instruction *> IndirCalls); void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets); @@ -357,6 +210,11 @@ void CreateFunctionLocalArrays(Function &F, ArrayRef<BasicBlock *> AllBlocks); void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, bool IsLeafFunc = true); + Function *CreateInitCallsForSections(Module &M, const char *CtorName, + const char *InitFunctionName, Type *Ty, + const char *Section); + std::pair<Value *, Value *> CreateSecStartEnd(Module &M, const char *Section, + Type *Ty); void SetNoSanitizeMetadata(Instruction *I) { I->setMetadata(I->getModule()->getMDKindID("nosanitize"), @@ -392,33 +250,30 @@ SanitizerCoverageOptions Options; }; -class SanitizerCoverageLegacyPass : public FunctionPass { +class ModuleSanitizerCoverageLegacyPass : public ModulePass { public: - static char ID; // Pass identification, replacement for typeid - - SanitizerCoverageLegacyPass( - SanitizerCoverageOptions Options = SanitizerCoverageOptions()) - : FunctionPass(ID), Options(Options) { - initializeSanitizerCoverageLegacyPassPass(*PassRegistry::getPassRegistry()); + ModuleSanitizerCoverageLegacyPass( + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) + : ModulePass(ID), Options(Options) { + initializeModuleSanitizerCoverageLegacyPassPass( + *PassRegistry::getPassRegistry()); } - - bool runOnFunction(Function &F) override { - const DominatorTree *DT = - &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - const PostDominatorTree *PDT = - &getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree(); - SanitizerCoverage Sancov(F, Options); - return Sancov.instrumentFunction(F, DT, PDT); + bool runOnModule(Module &M) override { + ModuleSanitizerCoverage ModuleSancov(Options); + auto DTCallback = [this](Function &F) -> const DominatorTree * { + return &this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree(); + }; + auto PDTCallback = [this](Function &F) -> const PostDominatorTree * { + return &this->getAnalysis<PostDominatorTreeWrapperPass>(F) + .getPostDomTree(); + }; + return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback); } - StringRef getPassName() const override { - return "SanitizerCoverageLegacyPass"; - } + static char ID; // Pass identification, replacement for typeid + StringRef getPassName() const override { return "ModuleSanitizerCoverage"; } void getAnalysisUsage(AnalysisUsage &AU) const override { - // Make the module sancov pass required by this pass so that it runs when - // -sancov is passed. - AU.addRequired<ModuleSanitizerCoverageLegacyPass>(); AU.addRequired<DominatorTreeWrapperPass>(); AU.addRequired<PostDominatorTreeWrapperPass>(); } @@ -429,20 +284,17 @@ } // namespace -PreservedAnalyses SanitizerCoveragePass::run(Function &F, - FunctionAnalysisManager &AM) { - const DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(F); - const PostDominatorTree *PDT = &AM.getResult<PostDominatorTreeAnalysis>(F); - SanitizerCoverage Sancov(F, Options); - if (Sancov.instrumentFunction(F, DT, PDT)) - return PreservedAnalyses::none(); - return PreservedAnalyses::all(); -} - PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &M, - ModuleAnalysisManager &AM) { + ModuleAnalysisManager &MAM) { ModuleSanitizerCoverage ModuleSancov(Options); - if (ModuleSancov.instrumentModule(M)) + auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { + return &FAM.getResult<DominatorTreeAnalysis>(F); + }; + auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree * { + return &FAM.getResult<PostDominatorTreeAnalysis>(F); + }; + if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback)) return PreservedAnalyses::none(); return PreservedAnalyses::all(); } @@ -458,7 +310,6 @@ new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr, getSectionEnd(Section)); SecEnd->setVisibility(GlobalValue::HiddenVisibility); - IRBuilder<> IRB(M.getContext()); Value *SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty); if (!TargetTriple.isOSBinFormatCOFF()) @@ -504,11 +355,13 @@ return CtorFunc; } -void SanitizerCoverage::initializeModule(Module &M) { +bool ModuleSanitizerCoverage::instrumentModule( + Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) - return; + return false; C = &(M.getContext()); DL = &M.getDataLayout(); + CurModule = &M; CurModuleUniqueId = getUniqueModuleId(CurModule); TargetTriple = Triple(M.getTargetTriple()); FunctionGuardArray = nullptr; @@ -576,6 +429,11 @@ Constant *SanCovLowestStackConstant = M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); SanCovLowestStack = dyn_cast<GlobalVariable>(SanCovLowestStackConstant); + if (!SanCovLowestStack) { + C->emitError(StringRef("'") + SanCovLowestStackName + + "' should not be declared by the user"); + return true; + } SanCovLowestStack->setThreadLocalMode( GlobalValue::ThreadLocalMode::InitialExecTLSModel); if (Options.StackDepth && !SanCovLowestStack->isDeclaration()) @@ -589,14 +447,33 @@ SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy); SanCovTracePCGuard = M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy); -} -void SanitizerCoverage::finalizeModule(Module &M) { + for (auto &F : M) + instrumentFunction(F, DTCallback, PDTCallback); + + Function *Ctor = nullptr; + + if (FunctionGuardArray) + Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName, + SanCovTracePCGuardInitName, Int32PtrTy, + SanCovGuardsSectionName); + if (Function8bitCounterArray) + Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName, + SanCov8bitCountersInitName, Int8PtrTy, + SanCovCountersSectionName); + if (Ctor && Options.PCTable) { + auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy); + FunctionCallee InitFunction = declareSanitizerInitFunction( + M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); + IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); + IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); + } // We don't reference these arrays directly in any of our runtime functions, // so we need to prevent them from being dead stripped. if (TargetTriple.isOSBinFormatMachO()) appendToUsed(M, GlobalsToAppendToUsed); appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); + return true; } // True if block has successors and it dominates all of them. @@ -687,12 +564,30 @@ return true; } -bool SanitizerCoverage::instrumentFunction(Function &F, const DominatorTree *DT, - const PostDominatorTree *PDT) { - if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) - return false; - if (!canInstrumentWithSancov(F)) - return false; +void ModuleSanitizerCoverage::instrumentFunction( + Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { + if (F.empty()) + return; + if (F.getName().find(".module_ctor") != std::string::npos) + return; // Should not instrument sanitizer init functions. + if (F.getName().startswith("__sanitizer_")) + return; // Don't instrument __sanitizer_* callbacks. + // Don't touch available_externally functions, their actual body is elewhere. + if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) + return; + // Don't instrument MSVC CRT configuration helpers. They may run before normal + // initialization. + if (F.getName() == "__local_stdio_printf_options" || + F.getName() == "__local_stdio_scanf_options") + return; + if (isa<UnreachableInst>(F.getEntryBlock().getTerminator())) + return; + // Don't instrument functions using SEH for now. Splitting basic blocks like + // we do for coverage breaks WinEHPrepare. + // FIXME: Remove this when SEH no longer uses landingpad pattern matching. + if (F.hasPersonalityFn() && + isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) + return; if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); SmallVector<Instruction *, 8> IndirCalls; @@ -702,6 +597,8 @@ SmallVector<BinaryOperator *, 8> DivTraceTargets; SmallVector<GetElementPtrInst *, 8> GepTraceTargets; + const DominatorTree *DT = DTCallback(F); + const PostDominatorTree *PDT = PDTCallback(F); bool IsLeafFunc = true; for (auto &BB : F) { @@ -741,10 +638,9 @@ InjectTraceForSwitch(F, SwitchTraceTargets); InjectTraceForDiv(F, DivTraceTargets); InjectTraceForGep(F, GepTraceTargets); - return true; } -GlobalVariable *SanitizerCoverage::CreateFunctionLocalArrayInSection( +GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( size_t NumElements, Function &F, Type *Ty, const char *Section) { ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); auto Array = new GlobalVariable( @@ -767,8 +663,8 @@ } GlobalVariable * -SanitizerCoverage::CreatePCArray(Function &F, - ArrayRef<BasicBlock *> AllBlocks) { +ModuleSanitizerCoverage::CreatePCArray(Function &F, + ArrayRef<BasicBlock *> AllBlocks) { size_t N = AllBlocks.size(); assert(N); SmallVector<Constant *, 32> PCs; @@ -794,7 +690,7 @@ return PCArray; } -void SanitizerCoverage::CreateFunctionLocalArrays( +void ModuleSanitizerCoverage::CreateFunctionLocalArrays( Function &F, ArrayRef<BasicBlock *> AllBlocks) { if (Options.TracePCGuard) FunctionGuardArray = CreateFunctionLocalArrayInSection( @@ -808,9 +704,9 @@ FunctionPCsArray = CreatePCArray(F, AllBlocks); } -bool SanitizerCoverage::InjectCoverage(Function &F, - ArrayRef<BasicBlock *> AllBlocks, - bool IsLeafFunc) { +bool ModuleSanitizerCoverage::InjectCoverage(Function &F, + ArrayRef<BasicBlock *> AllBlocks, + bool IsLeafFunc) { if (AllBlocks.empty()) return false; CreateFunctionLocalArrays(F, AllBlocks); for (size_t i = 0, N = AllBlocks.size(); i < N; i++) @@ -825,7 +721,7 @@ // The cache is used to speed up recording the caller-callee pairs. // The address of the caller is passed implicitly via caller PC. // CacheSize is encoded in the name of the run-time function. -void SanitizerCoverage::InjectCoverageForIndirectCalls( +void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls( Function &F, ArrayRef<Instruction *> IndirCalls) { if (IndirCalls.empty()) return; @@ -844,7 +740,7 @@ // __sanitizer_cov_trace_switch(CondValue, // {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... }) -void SanitizerCoverage::InjectTraceForSwitch( +void ModuleSanitizerCoverage::InjectTraceForSwitch( Function &, ArrayRef<Instruction *> SwitchTraceTargets) { for (auto I : SwitchTraceTargets) { if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) { @@ -883,7 +779,7 @@ } } -void SanitizerCoverage::InjectTraceForDiv( +void ModuleSanitizerCoverage::InjectTraceForDiv( Function &, ArrayRef<BinaryOperator *> DivTraceTargets) { for (auto BO : DivTraceTargets) { IRBuilder<> IRB(BO); @@ -901,7 +797,7 @@ } } -void SanitizerCoverage::InjectTraceForGep( +void ModuleSanitizerCoverage::InjectTraceForGep( Function &, ArrayRef<GetElementPtrInst *> GepTraceTargets) { for (auto GEP : GepTraceTargets) { IRBuilder<> IRB(GEP); @@ -912,7 +808,7 @@ } } -void SanitizerCoverage::InjectTraceForCmp( +void ModuleSanitizerCoverage::InjectTraceForCmp( Function &, ArrayRef<Instruction *> CmpTraceTargets) { for (auto I : CmpTraceTargets) { if (ICmpInst *ICMP = dyn_cast<ICmpInst>(I)) { @@ -947,8 +843,9 @@ } } -void SanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, - size_t Idx, bool IsLeafFunc) { +void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, + size_t Idx, + bool IsLeafFunc) { BasicBlock::iterator IP = BB.getFirstInsertionPt(); bool IsEntryBB = &BB == &F.getEntryBlock(); DebugLoc EntryLoc; @@ -1007,7 +904,7 @@ } std::string -SanitizerCoverage::getSectionName(const std::string &Section) const { +ModuleSanitizerCoverage::getSectionName(const std::string &Section) const { if (TargetTriple.isOSBinFormatCOFF()) { if (Section == SanCovCountersSectionName) return ".SCOV$CM"; @@ -1020,24 +917,29 @@ return "__" + Section; } -INITIALIZE_PASS(ModuleSanitizerCoverageLegacyPass, "module-sancov", - "Pass for inserting sancov top-level initialization calls", - false, false) +std::string +ModuleSanitizerCoverage::getSectionStart(const std::string &Section) const { + if (TargetTriple.isOSBinFormatMachO()) + return "\1section$start$__DATA$__" + Section; + return "__start___" + Section; +} + +std::string +ModuleSanitizerCoverage::getSectionEnd(const std::string &Section) const { + if (TargetTriple.isOSBinFormatMachO()) + return "\1section$end$__DATA$__" + Section; + return "__stop___" + Section; +} -char SanitizerCoverageLegacyPass::ID = 0; -INITIALIZE_PASS_BEGIN(SanitizerCoverageLegacyPass, "sancov", +char ModuleSanitizerCoverageLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov", "Pass for instrumenting coverage on functions", false, false) -INITIALIZE_PASS_DEPENDENCY(ModuleSanitizerCoverageLegacyPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) -INITIALIZE_PASS_END(SanitizerCoverageLegacyPass, "sancov", +INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov", "Pass for instrumenting coverage on functions", false, false) -FunctionPass *llvm::createSanitizerCoverageLegacyPassPass( - const SanitizerCoverageOptions &Options) { - return new SanitizerCoverageLegacyPass(Options); -} ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( const SanitizerCoverageOptions &Options) { return new ModuleSanitizerCoverageLegacyPass(Options); Index: llvm/lib/Transforms/Instrumentation/Instrumentation.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/Instrumentation.cpp +++ llvm/lib/Transforms/Instrumentation/Instrumentation.cpp @@ -116,7 +116,7 @@ initializeMemorySanitizerLegacyPassPass(Registry); initializeHWAddressSanitizerLegacyPassPass(Registry); initializeThreadSanitizerLegacyPassPass(Registry); - initializeSanitizerCoverageLegacyPassPass(Registry); + initializeModuleSanitizerCoverageLegacyPassPass(Registry); initializeDataFlowSanitizerPass(Registry); } Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -246,7 +246,6 @@ FUNCTION_PASS("msan", MemorySanitizerPass({})) FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true})) FUNCTION_PASS("tsan", ThreadSanitizerPass()) -FUNCTION_PASS("sancov-func", SanitizerCoveragePass()) #undef FUNCTION_PASS #ifndef FUNCTION_PASS_WITH_PARAMS Index: llvm/include/llvm/Transforms/Instrumentation/SanitizerCoverage.h =================================================================== --- llvm/include/llvm/Transforms/Instrumentation/SanitizerCoverage.h +++ llvm/include/llvm/Transforms/Instrumentation/SanitizerCoverage.h @@ -16,29 +16,16 @@ #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERCOVERAGE_H #define LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERCOVERAGE_H -#include "llvm/IR/Function.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/Transforms/Instrumentation.h" namespace llvm { -/// This is the SanitizerCoverage pass used in the new pass manager. The -/// pass instruments functions for coverage. -class SanitizerCoveragePass : public PassInfoMixin<SanitizerCoveragePass> { -public: - explicit SanitizerCoveragePass( - SanitizerCoverageOptions Options = SanitizerCoverageOptions()) - : Options(Options) {} - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); - -private: - SanitizerCoverageOptions Options; -}; - -/// This is the ModuleSanitizerCoverage pass used in the new pass manager. This -/// adds initialization calls to the module for trace PC guards and 8bit -/// counters if they are requested. +/// This is the ModuleSanitizerCoverage pass used in the new pass manager. The +/// pass instruments functions for coverage, adds initialization calls to the +/// module for trace PC guards and 8bit counters if they are requested, and +/// appends globals to llvm.compiler.used. class ModuleSanitizerCoveragePass : public PassInfoMixin<ModuleSanitizerCoveragePass> { public: @@ -52,8 +39,6 @@ }; // Insert SanitizerCoverage instrumentation. -FunctionPass *createSanitizerCoverageLegacyPassPass( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()); ModulePass *createModuleSanitizerCoverageLegacyPassPass( const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()); Index: llvm/include/llvm/InitializePasses.h =================================================================== --- llvm/include/llvm/InitializePasses.h +++ llvm/include/llvm/InitializePasses.h @@ -362,8 +362,6 @@ void initializeSafeStackLegacyPassPass(PassRegistry&); void initializeSafepointIRVerifierPass(PassRegistry&); void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&); -void initializeSanitizerCoverageFunctionCheckLegacyPassPass(PassRegistry &); -void initializeSanitizerCoverageLegacyPassPass(PassRegistry &); void initializeModuleSanitizerCoverageLegacyPassPass(PassRegistry &); void initializeScalarEvolutionWrapperPassPass(PassRegistry&); void initializeScalarizeMaskedMemIntrinPass(PassRegistry&); Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -224,7 +224,6 @@ const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); auto Opts = getSancovOptsFromCGOpts(CGOpts); PM.add(createModuleSanitizerCoverageLegacyPassPass(Opts)); - PM.add(createSanitizerCoverageLegacyPassPass(Opts)); } // Check if ASan should use GC-friendly instrumentation for globals. @@ -1159,11 +1158,6 @@ [SancovOpts](ModulePassManager &MPM) { MPM.addPass(ModuleSanitizerCoveragePass(SancovOpts)); }); - PB.registerOptimizerLastEPCallback( - [SancovOpts](FunctionPassManager &FPM, - PassBuilder::OptimizationLevel Level) { - FPM.addPass(SanitizerCoveragePass(SancovOpts)); - }); } // Register callbacks to schedule sanitizer passes at the appropriate part of @@ -1249,8 +1243,6 @@ CodeGenOpts.SanitizeCoverageTraceCmp) { auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts); MPM.addPass(ModuleSanitizerCoveragePass(SancovOpts)); - MPM.addPass(createModuleToFunctionPassAdaptor( - SanitizerCoveragePass(SancovOpts))); } addSanitizersAtO0(MPM, TargetTriple, LangOpts, CodeGenOpts);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits