[sancov] add tracing for loads and store

add tracing for loads and stores.

The primary goal is to have more options for data-flow-guided fuzzing,
i.e. use data flow insights to perform better mutations or more agressive corpus expansion.
But the feature is general puspose, could be used for other things too.

Pipe the flag though clang and clang driver, same as for the other SanitizerCoverage flags.
While at it, change some plain arrays into std::array.

Tests: clang flags test, LLVM IR test, compiler-rt executable test.

Reviewed By: morehouse

Differential Revision: https://reviews.llvm.org/D113447
This commit is contained in:
Kostya Serebryany 2021-11-08 17:52:36 -08:00
parent c17d9b4b12
commit b7f3a4f4fa
11 changed files with 246 additions and 11 deletions

View File

@ -275,6 +275,12 @@ integer division instructions (to capture the right argument of division)
and with ``-fsanitize-coverage=trace-gep`` --
the `LLVM GEP instructions <https://llvm.org/docs/GetElementPtr.html>`_
(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")))``
===========================================================================

View File

@ -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.

View File

@ -463,7 +463,8 @@ public:
// Check if any one of SanitizeCoverage* is enabled.
bool hasSanitizeCoverage() const {
return SanitizeCoverageType || SanitizeCoverageIndirectCalls ||
SanitizeCoverageTraceCmp;
SanitizeCoverageTraceCmp || SanitizeCoverageTraceLoads ||
SanitizeCoverageTraceStores;
}
};

View File

@ -5127,6 +5127,14 @@ def fsanitize_coverage_stack_depth
: Flag<["-"], "fsanitize-coverage-stack-depth">,
HelpText<"Enable max stack depth tracing">,
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageStackDepth">>;
def fsanitize_coverage_trace_loads
: Flag<["-"], "fsanitize-coverage-trace-loads">,
HelpText<"Enable tracing of loads">,
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceLoads">>;
def fsanitize_coverage_trace_stores
: Flag<["-"], "fsanitize-coverage-trace-stores">,
HelpText<"Enable tracing of stores">,
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceStores">>;
def fpatchable_function_entry_offset_EQ
: Joined<["-"], "fpatchable-function-entry-offset=">, MetaVarName<"<M>">,
HelpText<"Generate M NOPs before function entry">,

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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 <stdint.h>
#include <stdio.h>
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");
}

View File

@ -169,6 +169,8 @@ struct SanitizerCoverageOptions {
bool PCTable = false;
bool NoPrune = false;
bool StackDepth = false;
bool TraceLoads = false;
bool TraceStores = false;
SanitizerCoverageOptions() = default;
};

View File

@ -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<bool> ClDIVTracing("sanitizer-coverage-trace-divs",
cl::desc("Tracing of DIV instructions"),
cl::Hidden, cl::init(false));
static cl::opt<bool> ClLoadTracing("sanitizer-coverage-trace-loads",
cl::desc("Tracing of load instructions"),
cl::Hidden, cl::init(false));
static cl::opt<bool> ClStoreTracing("sanitizer-coverage-trace-stores",
cl::desc("Tracing of store instructions"),
cl::Hidden, cl::init(false));
static cl::opt<bool> 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 @@ private:
ArrayRef<BinaryOperator *> DivTraceTargets);
void InjectTraceForGep(Function &F,
ArrayRef<GetElementPtrInst *> GepTraceTargets);
void InjectTraceForLoadsAndStores(Function &F, ArrayRef<LoadInst *> Loads,
ArrayRef<StoreInst *> Stores);
void InjectTraceForSwitch(Function &F,
ArrayRef<Instruction *> SwitchTraceTargets);
bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks,
@ -234,14 +256,17 @@ private:
std::string getSectionEnd(const std::string &Section) const;
FunctionCallee SanCovTracePCIndir;
FunctionCallee SanCovTracePC, SanCovTracePCGuard;
FunctionCallee SanCovTraceCmpFunction[4];
FunctionCallee SanCovTraceConstCmpFunction[4];
FunctionCallee SanCovTraceDivFunction[2];
std::array<FunctionCallee, 4> SanCovTraceCmpFunction;
std::array<FunctionCallee, 4> SanCovTraceConstCmpFunction;
std::array<FunctionCallee, 5> SanCovLoadFunction;
std::array<FunctionCallee, 5> SanCovStoreFunction;
std::array<FunctionCallee, 2> 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<Instruction *, 8> SwitchTraceTargets;
SmallVector<BinaryOperator *, 8> DivTraceTargets;
SmallVector<GetElementPtrInst *, 8> GepTraceTargets;
SmallVector<LoadInst *, 8> Loads;
SmallVector<StoreInst *, 8> 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<GetElementPtrInst>(&Inst))
GepTraceTargets.push_back(GEP);
if (Options.TraceLoads)
if (LoadInst *LI = dyn_cast<LoadInst>(&Inst))
Loads.push_back(LI);
if (Options.TraceStores)
if (StoreInst *SI = dyn_cast<StoreInst>(&Inst))
Stores.push_back(SI);
if (Options.StackDepth)
if (isa<InvokeInst>(Inst) ||
(isa<CallInst>(Inst) && !isa<IntrinsicInst>(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<LoadInst *> Loads, ArrayRef<StoreInst *> Stores) {
auto CallbackIdx = [&](const Value *Ptr) -> int {
auto ElementTy = cast<PointerType>(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<Instruction *> CmpTraceTargets) {
for (auto I : CmpTraceTargets) {

View File

@ -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
}