forked from OSchip/llvm-project
[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:
parent
c17d9b4b12
commit
b7f3a4f4fa
|
@ -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")))``
|
||||
===========================================================================
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -463,7 +463,8 @@ public:
|
|||
// Check if any one of SanitizeCoverage* is enabled.
|
||||
bool hasSanitizeCoverage() const {
|
||||
return SanitizeCoverageType || SanitizeCoverageIndirectCalls ||
|
||||
SanitizeCoverageTraceCmp;
|
||||
SanitizeCoverageTraceCmp || SanitizeCoverageTraceLoads ||
|
||||
SanitizeCoverageTraceStores;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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">,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
|
@ -169,6 +169,8 @@ struct SanitizerCoverageOptions {
|
|||
bool PCTable = false;
|
||||
bool NoPrune = false;
|
||||
bool StackDepth = false;
|
||||
bool TraceLoads = false;
|
||||
bool TraceStores = false;
|
||||
|
||||
SanitizerCoverageOptions() = default;
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue