diff --git a/clang/docs/SanitizerCoverage.rst b/clang/docs/SanitizerCoverage.rst index 81b3cfea0549f4..9e9f096ee92155 100644 --- a/clang/docs/SanitizerCoverage.rst +++ b/clang/docs/SanitizerCoverage.rst @@ -275,6 +275,12 @@ integer division instructions (to capture the right argument of division) and with ``-fsanitize-coverage=trace-gep`` -- the `LLVM GEP instructions `_ (to capture array indices). +Similarly, with ``-fsanitize-coverage=trace-loads`` and ``-fsanitize-coverage=trace-stores`` +the compiler will instrument loads and stores, respectively. + +Currently, these flags do not work by themselves - they require one +of ``-fsanitize-coverage={trace-pc,inline-8bit-counters,inline-bool}`` +flags to work. Unless ``no-prune`` option is provided, some of the comparison instructions will not be instrumented. @@ -312,6 +318,19 @@ will not be instrumented. // for every non-constant array index. void __sanitizer_cov_trace_gep(uintptr_t Idx); + // Called before a load of appropriate size. Addr is the address of the load. + void __sanitizer_cov_load1(uint8_t *addr); + void __sanitizer_cov_load2(uint16_t *addr); + void __sanitizer_cov_load4(uint32_t *addr); + void __sanitizer_cov_load8(uint64_t *addr); + void __sanitizer_cov_load16(__int128 *addr); + // Called before a store of appropriate size. Addr is the address of the store. + void __sanitizer_cov_store1(uint8_t *addr); + void __sanitizer_cov_store2(uint16_t *addr); + void __sanitizer_cov_store4(uint32_t *addr); + void __sanitizer_cov_store8(uint64_t *addr); + void __sanitizer_cov_store16(__int128 *addr); + Disabling instrumentation with ``__attribute__((no_sanitize("coverage")))`` =========================================================================== diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 61012326017557..263939670d05e8 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -261,6 +261,8 @@ CODEGENOPT(SanitizeCoverageInlineBoolFlag, 1, 0) ///< Use inline bool flag. CODEGENOPT(SanitizeCoveragePCTable, 1, 0) ///< Create a PC Table. CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning. CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing +CODEGENOPT(SanitizeCoverageTraceLoads, 1, 0) ///< Enable tracing of loads. +CODEGENOPT(SanitizeCoverageTraceStores, 1, 0) ///< Enable tracing of stores. CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 6a0bce0ad80a7e..05d8a221a54362 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -463,7 +463,8 @@ class CodeGenOptions : public CodeGenOptionsBase { // Check if any one of SanitizeCoverage* is enabled. bool hasSanitizeCoverage() const { return SanitizeCoverageType || SanitizeCoverageIndirectCalls || - SanitizeCoverageTraceCmp; + SanitizeCoverageTraceCmp || SanitizeCoverageTraceLoads || + SanitizeCoverageTraceStores; } }; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 9a657e948e33e0..33cef87b4cd83e 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5127,6 +5127,14 @@ def fsanitize_coverage_stack_depth : Flag<["-"], "fsanitize-coverage-stack-depth">, HelpText<"Enable max stack depth tracing">, MarshallingInfoFlag>; +def fsanitize_coverage_trace_loads + : Flag<["-"], "fsanitize-coverage-trace-loads">, + HelpText<"Enable tracing of loads">, + MarshallingInfoFlag>; +def fsanitize_coverage_trace_stores + : Flag<["-"], "fsanitize-coverage-trace-stores">, + HelpText<"Enable tracing of stores">, + MarshallingInfoFlag>; def fpatchable_function_entry_offset_EQ : Joined<["-"], "fpatchable-function-entry-offset=">, MetaVarName<"">, HelpText<"Generate M NOPs before function entry">, diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 1f583e639c5798..648c7b3df8ed47 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -247,6 +247,8 @@ getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) { Opts.InlineBoolFlag = CGOpts.SanitizeCoverageInlineBoolFlag; Opts.PCTable = CGOpts.SanitizeCoveragePCTable; Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth; + Opts.TraceLoads = CGOpts.SanitizeCoverageTraceLoads; + Opts.TraceStores = CGOpts.SanitizeCoverageTraceStores; return Opts; } diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 36579060d8a267..1fb3057711ab04 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -91,6 +91,8 @@ enum CoverageFeature { CoveragePCTable = 1 << 13, CoverageStackDepth = 1 << 14, CoverageInlineBoolFlag = 1 << 15, + CoverageTraceLoads = 1 << 16, + CoverageTraceStores = 1 << 17, }; /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any @@ -727,8 +729,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge; int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard | - CoverageInline8bitCounters | - CoverageInlineBoolFlag; + CoverageInline8bitCounters | CoverageTraceLoads | + CoverageTraceStores | CoverageInlineBoolFlag; if ((CoverageFeatures & InsertionPointTypes) && !(CoverageFeatures & InstrumentationTypes)) { D.Diag(clang::diag::warn_drv_deprecated_arg) @@ -1003,7 +1005,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, "-fsanitize-coverage-inline-bool-flag"), std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"), std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"), - std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")}; + std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"), + std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"), + std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores")}; for (auto F : CoverageFlags) { if (CoverageFeatures & F.first) CmdArgs.push_back(F.second); @@ -1243,6 +1247,8 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) { .Case("inline-bool-flag", CoverageInlineBoolFlag) .Case("pc-table", CoveragePCTable) .Case("stack-depth", CoverageStackDepth) + .Case("trace-loads", CoverageTraceLoads) + .Case("trace-stores", CoverageTraceStores) .Default(0); if (F == 0) D.Diag(clang::diag::err_drv_unsupported_option_argument) diff --git a/clang/test/Driver/fsanitize-coverage.c b/clang/test/Driver/fsanitize-coverage.c index 02078d847512eb..ab8a8871877e65 100644 --- a/clang/test/Driver/fsanitize-coverage.c +++ b/clang/test/Driver/fsanitize-coverage.c @@ -38,13 +38,15 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=edge %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_FUNC_BB_EDGE_DEPRECATED // CHECK_FUNC_BB_EDGE_DEPRECATED: warning: argument '-fsanitize-coverage=[func|bb|edge]' is deprecated, use '-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]' instead -// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=edge,indirect-calls,trace-pc,trace-cmp,trace-div,trace-gep %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FEATURES +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=edge,indirect-calls,trace-pc,trace-cmp,trace-loads,trace-stores,trace-div,trace-gep %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FEATURES // CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-type=3 // CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-indirect-calls // CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-cmp // CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-div // CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-gep // CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-pc +// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-loads +// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-stores // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=func,edge,indirect-calls,trace-cmp -fno-sanitize-coverage=edge,indirect-calls %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MASK // CHECK-MASK: -fsanitize-coverage-type=1 diff --git a/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_loads_stores.cpp b/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_loads_stores.cpp new file mode 100644 index 00000000000000..dd9ef53a4498b7 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_trace_loads_stores.cpp @@ -0,0 +1,68 @@ +// Tests -fsanitize-coverage=trace-pc,trace-loads,trace-stores +// +// REQUIRES: has_sancovcc,stable-runtime,x86_64 +// +// RUN: %clangxx -O0 %s -fsanitize-coverage=trace-pc,trace-loads,trace-stores -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include +#include + +extern "C" { +void __sanitizer_cov_load1(uint8_t *addr) { printf("load1: %p\n", addr); } +void __sanitizer_cov_load2(uint16_t *addr) { printf("load2: %p\n", addr); } +void __sanitizer_cov_load4(uint32_t *addr) { printf("load4: %p\n", addr); } +void __sanitizer_cov_load8(uint64_t *addr) { printf("load8: %p\n", addr); } +void __sanitizer_cov_load16(__int128 *addr) { printf("load16: %p\n", addr); } + +void __sanitizer_cov_store1(uint8_t *addr) { printf("store1: %p\n", addr); } +void __sanitizer_cov_store2(uint16_t *addr) { printf("store2: %p\n", addr); } +void __sanitizer_cov_store4(uint32_t *addr) { printf("store4: %p\n", addr); } +void __sanitizer_cov_store8(uint64_t *addr) { printf("store8: %p\n", addr); } +void __sanitizer_cov_store16(__int128 *addr) { printf("store16: %p\n", addr); } +} + +uint8_t var1; +uint16_t var2; +uint32_t var4; +uint64_t var8; +__int128 var16; +static volatile int sink; + +int main() { + printf("var1: %p\n", &var1); + sink = var1; + var1 = 42; + // CHECK: var1: [[ADDR:0x.*]] + // CHECK: load1: [[ADDR]] + // CHECK: store1: [[ADDR]] + + printf("var2: %p\n", &var2); + sink = var2; + var2 = 42; + // CHECK: var2: [[ADDR:0x.*]] + // CHECK: load2: [[ADDR]] + // CHECK: store2: [[ADDR]] + + printf("var4: %p\n", &var4); + sink = var4; + var4 = 42; + // CHECK: var4: [[ADDR:0x.*]] + // CHECK: load4: [[ADDR]] + // CHECK: store4: [[ADDR]] + + printf("var8: %p\n", &var8); + sink = var8; + var8 = 42; + // CHECK: var8: [[ADDR:0x.*]] + // CHECK: load8: [[ADDR]] + // CHECK: store8: [[ADDR]] + + printf("var16: %p\n", &var16); + sink = var16; + var16 = 42; + // CHECK: var16: [[ADDR:0x.*]] + // CHECK: load16: [[ADDR]] + // CHECK: store16: [[ADDR]] + printf("PASS\n"); +} diff --git a/llvm/include/llvm/Transforms/Instrumentation.h b/llvm/include/llvm/Transforms/Instrumentation.h index 0c822999aecf3c..a288a3972c3dac 100644 --- a/llvm/include/llvm/Transforms/Instrumentation.h +++ b/llvm/include/llvm/Transforms/Instrumentation.h @@ -169,6 +169,8 @@ struct SanitizerCoverageOptions { bool PCTable = false; bool NoPrune = false; bool StackDepth = false; + bool TraceLoads = false; + bool TraceStores = false; SanitizerCoverageOptions() = default; }; diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 7607464cc0b904..da8ee1f15bf8e8 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -55,6 +55,16 @@ const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1"; const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2"; const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4"; const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8"; +const char SanCovLoad1[] = "__sanitizer_cov_load1"; +const char SanCovLoad2[] = "__sanitizer_cov_load2"; +const char SanCovLoad4[] = "__sanitizer_cov_load4"; +const char SanCovLoad8[] = "__sanitizer_cov_load8"; +const char SanCovLoad16[] = "__sanitizer_cov_load16"; +const char SanCovStore1[] = "__sanitizer_cov_store1"; +const char SanCovStore2[] = "__sanitizer_cov_store2"; +const char SanCovStore4[] = "__sanitizer_cov_store4"; +const char SanCovStore8[] = "__sanitizer_cov_store8"; +const char SanCovStore16[] = "__sanitizer_cov_store16"; const char SanCovTraceDiv4[] = "__sanitizer_cov_trace_div4"; const char SanCovTraceDiv8[] = "__sanitizer_cov_trace_div8"; const char SanCovTraceGep[] = "__sanitizer_cov_trace_gep"; @@ -122,6 +132,14 @@ static cl::opt ClDIVTracing("sanitizer-coverage-trace-divs", cl::desc("Tracing of DIV instructions"), cl::Hidden, cl::init(false)); +static cl::opt ClLoadTracing("sanitizer-coverage-trace-loads", + cl::desc("Tracing of load instructions"), + cl::Hidden, cl::init(false)); + +static cl::opt ClStoreTracing("sanitizer-coverage-trace-stores", + cl::desc("Tracing of store instructions"), + cl::Hidden, cl::init(false)); + static cl::opt ClGEPTracing("sanitizer-coverage-trace-geps", cl::desc("Tracing of GEP instructions"), cl::Hidden, cl::init(false)); @@ -175,9 +193,11 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { Options.PCTable |= ClCreatePCTable; Options.NoPrune |= !ClPruneBlocks; Options.StackDepth |= ClStackDepth; + Options.TraceLoads |= ClLoadTracing; + Options.TraceStores |= ClStoreTracing; if (!Options.TracePCGuard && !Options.TracePC && !Options.Inline8bitCounters && !Options.StackDepth && - !Options.InlineBoolFlag) + !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) Options.TracePCGuard = true; // TracePCGuard is default. return Options; } @@ -207,6 +227,8 @@ class ModuleSanitizerCoverage { ArrayRef DivTraceTargets); void InjectTraceForGep(Function &F, ArrayRef GepTraceTargets); + void InjectTraceForLoadsAndStores(Function &F, ArrayRef Loads, + ArrayRef Stores); void InjectTraceForSwitch(Function &F, ArrayRef SwitchTraceTargets); bool InjectCoverage(Function &F, ArrayRef AllBlocks, @@ -234,14 +256,17 @@ class ModuleSanitizerCoverage { std::string getSectionEnd(const std::string &Section) const; FunctionCallee SanCovTracePCIndir; FunctionCallee SanCovTracePC, SanCovTracePCGuard; - FunctionCallee SanCovTraceCmpFunction[4]; - FunctionCallee SanCovTraceConstCmpFunction[4]; - FunctionCallee SanCovTraceDivFunction[2]; + std::array SanCovTraceCmpFunction; + std::array SanCovTraceConstCmpFunction; + std::array SanCovLoadFunction; + std::array SanCovStoreFunction; + std::array SanCovTraceDivFunction; FunctionCallee SanCovTraceGepFunction; FunctionCallee SanCovTraceSwitchFunction; GlobalVariable *SanCovLowestStack; - Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, - *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; + Type *Int128PtrTy, *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, + *Int32PtrTy, *Int16PtrTy, *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, + *Int1PtrTy; Module *CurModule; std::string CurModuleUniqueId; Triple TargetTriple; @@ -411,7 +436,9 @@ bool ModuleSanitizerCoverage::instrumentModule( IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); IRBuilder<> IRB(*C); + Int128PtrTy = PointerType::getUnqual(IRB.getInt128Ty()); Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty()); + Int16PtrTy = PointerType::getUnqual(IRB.getInt16Ty()); Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); Int1PtrTy = PointerType::getUnqual(IRB.getInt1Ty()); @@ -452,6 +479,28 @@ bool ModuleSanitizerCoverage::instrumentModule( SanCovTraceConstCmpFunction[3] = M.getOrInsertFunction(SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty); + // Loads. + SanCovLoadFunction[0] = M.getOrInsertFunction(SanCovLoad1, VoidTy, Int8PtrTy); + SanCovLoadFunction[1] = + M.getOrInsertFunction(SanCovLoad2, VoidTy, Int16PtrTy); + SanCovLoadFunction[2] = + M.getOrInsertFunction(SanCovLoad4, VoidTy, Int32PtrTy); + SanCovLoadFunction[3] = + M.getOrInsertFunction(SanCovLoad8, VoidTy, Int64PtrTy); + SanCovLoadFunction[4] = + M.getOrInsertFunction(SanCovLoad16, VoidTy, Int128PtrTy); + // Stores. + SanCovStoreFunction[0] = + M.getOrInsertFunction(SanCovStore1, VoidTy, Int8PtrTy); + SanCovStoreFunction[1] = + M.getOrInsertFunction(SanCovStore2, VoidTy, Int16PtrTy); + SanCovStoreFunction[2] = + M.getOrInsertFunction(SanCovStore4, VoidTy, Int32PtrTy); + SanCovStoreFunction[3] = + M.getOrInsertFunction(SanCovStore8, VoidTy, Int64PtrTy); + SanCovStoreFunction[4] = + M.getOrInsertFunction(SanCovStore16, VoidTy, Int128PtrTy); + { AttributeList AL; AL = AL.addParamAttribute(*C, 0, Attribute::ZExt); @@ -632,6 +681,8 @@ void ModuleSanitizerCoverage::instrumentFunction( SmallVector SwitchTraceTargets; SmallVector DivTraceTargets; SmallVector GepTraceTargets; + SmallVector Loads; + SmallVector Stores; const DominatorTree *DT = DTCallback(F); const PostDominatorTree *PDT = PDTCallback(F); @@ -661,6 +712,12 @@ void ModuleSanitizerCoverage::instrumentFunction( if (Options.TraceGep) if (GetElementPtrInst *GEP = dyn_cast(&Inst)) GepTraceTargets.push_back(GEP); + if (Options.TraceLoads) + if (LoadInst *LI = dyn_cast(&Inst)) + Loads.push_back(LI); + if (Options.TraceStores) + if (StoreInst *SI = dyn_cast(&Inst)) + Stores.push_back(SI); if (Options.StackDepth) if (isa(Inst) || (isa(Inst) && !isa(Inst))) @@ -674,6 +731,7 @@ void ModuleSanitizerCoverage::instrumentFunction( InjectTraceForSwitch(F, SwitchTraceTargets); InjectTraceForDiv(F, DivTraceTargets); InjectTraceForGep(F, GepTraceTargets); + InjectTraceForLoadsAndStores(F, Loads, Stores); } GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( @@ -857,6 +915,40 @@ void ModuleSanitizerCoverage::InjectTraceForGep( } } +void ModuleSanitizerCoverage::InjectTraceForLoadsAndStores( + Function &, ArrayRef Loads, ArrayRef Stores) { + auto CallbackIdx = [&](const Value *Ptr) -> int { + auto ElementTy = cast(Ptr->getType())->getElementType(); + uint64_t TypeSize = DL->getTypeStoreSizeInBits(ElementTy); + return TypeSize == 8 ? 0 + : TypeSize == 16 ? 1 + : TypeSize == 32 ? 2 + : TypeSize == 64 ? 3 + : TypeSize == 128 ? 4 + : -1; + }; + Type *PointerType[5] = {Int8PtrTy, Int16PtrTy, Int32PtrTy, Int64PtrTy, + Int128PtrTy}; + for (auto LI : Loads) { + IRBuilder<> IRB(LI); + auto Ptr = LI->getPointerOperand(); + int Idx = CallbackIdx(Ptr); + if (Idx < 0) + continue; + IRB.CreateCall(SanCovLoadFunction[Idx], + IRB.CreatePointerCast(Ptr, PointerType[Idx])); + } + for (auto SI : Stores) { + IRBuilder<> IRB(SI); + auto Ptr = SI->getPointerOperand(); + int Idx = CallbackIdx(Ptr); + if (Idx < 0) + continue; + IRB.CreateCall(SanCovStoreFunction[Idx], + IRB.CreatePointerCast(Ptr, PointerType[Idx])); + } +} + void ModuleSanitizerCoverage::InjectTraceForCmp( Function &, ArrayRef CmpTraceTargets) { for (auto I : CmpTraceTargets) { diff --git a/llvm/test/Instrumentation/SanitizerCoverage/trace-loads-stores.ll b/llvm/test/Instrumentation/SanitizerCoverage/trace-loads-stores.ll new file mode 100644 index 00000000000000..69519006e69978 --- /dev/null +++ b/llvm/test/Instrumentation/SanitizerCoverage/trace-loads-stores.ll @@ -0,0 +1,33 @@ +; Test -sanitizer-coverage-inline-8bit-counters=1 +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-loads=1 -S | FileCheck %s --check-prefix=LOADS +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-stores=1 -S | FileCheck %s --check-prefix=STORES + +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(i8* %p1, i16* %p2, i32* %p4, i64* %p8, i128* %p16) { +; =================== loads + %1 = load i8, i8* %p1 + %2 = load i16, i16* %p2 + %3 = load i32, i32* %p4 + %4 = load i64, i64* %p8 + %5 = load i128, i128* %p16 +; LOADS: call void @__sanitizer_cov_load1(i8* %p1) +; LOADS: call void @__sanitizer_cov_load2(i16* %p2) +; LOADS: call void @__sanitizer_cov_load4(i32* %p4) +; LOADS: call void @__sanitizer_cov_load8(i64* %p8) +; LOADS: call void @__sanitizer_cov_load16(i128* %p16) + +; =================== stores + store i8 %1, i8* %p1 + store i16 %2, i16* %p2 + store i32 %3, i32* %p4 + store i64 %4, i64* %p8 + store i128 %5, i128* %p16 +; STORES: call void @__sanitizer_cov_store1(i8* %p1) +; STORES: call void @__sanitizer_cov_store2(i16* %p2) +; STORES: call void @__sanitizer_cov_store4(i32* %p4) +; STORES: call void @__sanitizer_cov_store8(i64* %p8) +; STORES: call void @__sanitizer_cov_store16(i128* %p16) + + ret void +}