[llvm] r311186 - [SanitizerCoverage] Add stack depth tracing instrumentation.
Matt Morehouse via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 18 11:43:30 PDT 2017
Author: morehouse
Date: Fri Aug 18 11:43:30 2017
New Revision: 311186
URL: http://llvm.org/viewvc/llvm-project?rev=311186&view=rev
Log:
[SanitizerCoverage] Add stack depth tracing instrumentation.
Summary:
Augment SanitizerCoverage to insert maximum stack depth tracing for
use by libFuzzer. The new instrumentation is enabled by the flag
-fsanitize-coverage=stack-depth and is compatible with the existing
trace-pc-guard coverage. The user must also declare the following
global variable in their code:
thread_local uintptr_t __sancov_lowest_stack
https://bugs.llvm.org/show_bug.cgi?id=33857
Reviewers: vitalybuka, kcc
Reviewed By: vitalybuka
Subscribers: kubamracek, hiraditya, cfe-commits, llvm-commits
Differential Revision: https://reviews.llvm.org/D36839
Added:
llvm/trunk/test/Instrumentation/SanitizerCoverage/stack-depth.ll
Modified:
llvm/trunk/include/llvm/Transforms/Instrumentation.h
llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
llvm/trunk/lib/Fuzzer/FuzzerTracePC.h
llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
Modified: llvm/trunk/include/llvm/Transforms/Instrumentation.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=311186&r1=311185&r2=311186&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Instrumentation.h (original)
+++ llvm/trunk/include/llvm/Transforms/Instrumentation.h Fri Aug 18 11:43:30 2017
@@ -185,6 +185,7 @@ struct SanitizerCoverageOptions {
bool Inline8bitCounters = false;
bool PCTable = false;
bool NoPrune = false;
+ bool StackDepth = false;
SanitizerCoverageOptions() = default;
};
Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp?rev=311186&r1=311185&r2=311186&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp Fri Aug 18 11:43:30 2017
@@ -31,6 +31,9 @@ uint8_t __sancov_trace_pc_guard_8bit_cou
ATTRIBUTE_INTERFACE
uintptr_t __sancov_trace_pc_pcs[fuzzer::TracePC::kNumPCs];
+// Used by -fsanitize-coverage=stack-depth to track stack depth
+ATTRIBUTE_INTERFACE thread_local uintptr_t __sancov_lowest_stack;
+
namespace fuzzer {
TracePC TPC;
@@ -340,6 +343,14 @@ void TracePC::ClearInlineCounters() {
}
}
+void TracePC::RecordInitialStack() {
+ InitialStack = __sancov_lowest_stack;
+}
+
+uintptr_t TracePC::GetMaxStackOffset() const {
+ return InitialStack - __sancov_lowest_stack; // Stack grows down
+}
+
} // namespace fuzzer
extern "C" {
@@ -350,8 +361,6 @@ void __sanitizer_cov_trace_pc_guard(uint
uint32_t Idx = *Guard;
__sancov_trace_pc_pcs[Idx] = PC;
__sancov_trace_pc_guard_8bit_counters[Idx]++;
- // Uncomment the following line to get stack-depth profiling.
- // fuzzer::TPC.RecordCurrentStack();
}
// Best-effort support for -fsanitize-coverage=trace-pc, which is available
Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.h?rev=311186&r1=311185&r2=311186&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTracePC.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.h Fri Aug 18 11:43:30 2017
@@ -120,19 +120,8 @@ class TracePC {
return PCs()[Idx];
}
- void RecordCurrentStack() {
- uintptr_t Stack = GetCurrentStack();
- if (Stack < LowestStack)
- LowestStack = Stack;
- }
- void RecordInitialStack() {
- InitialStack = GetCurrentStack();
- LowestStack = InitialStack;
- }
- uintptr_t GetCurrentStack() const {
- return reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
- }
- uintptr_t GetMaxStackOffset() const { return InitialStack - LowestStack; }
+ void RecordInitialStack();
+ uintptr_t GetMaxStackOffset() const;
template<class CallBack>
void ForEachObservedPC(CallBack CB) {
@@ -167,7 +156,7 @@ private:
std::set<uintptr_t> ObservedPCs;
ValueBitMap ValueProfileMap;
- uintptr_t InitialStack, LowestStack; // Assume stack grows down.
+ uintptr_t InitialStack;
};
template <class Callback>
Modified: llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp?rev=311186&r1=311185&r2=311186&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp Fri Aug 18 11:43:30 2017
@@ -17,12 +17,15 @@
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/IR/Constant.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
@@ -73,6 +76,10 @@ static const char *const SanCovGuardsSec
static const char *const SanCovCountersSectionName = "sancov_cntrs";
static const char *const SanCovPCsSectionName = "sancov_pcs";
+static const char *const SanCovLowestStackName = "__sancov_lowest_stack";
+static const char *const SanCovLowestStackTLSWrapperName =
+ "_ZTW21__sancov_lowest_stack";
+
static cl::opt<int> ClCoverageLevel(
"sanitizer-coverage-level",
cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
@@ -119,6 +126,10 @@ static cl::opt<bool>
cl::desc("Reduce the number of instrumented blocks"),
cl::Hidden, cl::init(true));
+static cl::opt<bool> ClStackDepth("sanitizer-coverage-stack-depth",
+ cl::desc("max stack depth tracing"),
+ cl::Hidden, cl::init(false));
+
namespace {
SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) {
@@ -156,9 +167,11 @@ SanitizerCoverageOptions OverrideFromCL(
Options.TracePCGuard |= ClTracePCGuard;
Options.Inline8bitCounters |= ClInline8bitCounters;
Options.PCTable |= ClCreatePCTable;
- if (!Options.TracePCGuard && !Options.TracePC && !Options.Inline8bitCounters)
- Options.TracePCGuard = true; // TracePCGuard is default.
Options.NoPrune |= !ClPruneBlocks;
+ Options.StackDepth |= ClStackDepth;
+ if (!Options.TracePCGuard && !Options.TracePC &&
+ !Options.Inline8bitCounters && !Options.StackDepth)
+ Options.TracePCGuard = true; // TracePCGuard is default.
return Options;
}
@@ -216,6 +229,8 @@ private:
Function *SanCovTraceDivFunction[2];
Function *SanCovTraceGepFunction;
Function *SanCovTraceSwitchFunction;
+ Function *SanCovLowestStackTLSWrapper;
+ GlobalVariable *SanCovLowestStack;
InlineAsm *EmptyAsm;
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
*Int16Ty, *Int8Ty, *Int8PtrTy;
@@ -333,6 +348,24 @@ bool SanitizerCoverageModule::runOnModul
SanCovTraceSwitchFunction =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy));
+
+ Constant *SanCovLowestStackConstant =
+ M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy);
+ SanCovLowestStackTLSWrapper =
+ checkSanitizerInterfaceFunction(M.getOrInsertFunction(
+ SanCovLowestStackTLSWrapperName, IntptrTy->getPointerTo()));
+ if (Options.StackDepth) {
+ assert(isa<GlobalVariable>(SanCovLowestStackConstant));
+ SanCovLowestStack = cast<GlobalVariable>(SanCovLowestStackConstant);
+ if (!SanCovLowestStack->isDeclaration()) {
+ // Check that the user has correctly defined:
+ // thread_local uintptr_t __sancov_lowest_stack
+ // and initialize it.
+ assert(SanCovLowestStack->isThreadLocal());
+ SanCovLowestStack->setInitializer(Constant::getAllOnesValue(IntptrTy));
+ }
+ }
+
// Make sure smaller parameters are zero-extended to i64 as required by the
// x86_64 ABI.
if (TargetTriple.getArch() == Triple::x86_64) {
@@ -451,6 +484,9 @@ bool SanitizerCoverageModule::runOnFunct
if (F.getName() == "__local_stdio_printf_options" ||
F.getName() == "__local_stdio_scanf_options")
return false;
+ // Avoid infinite recursion by not instrumenting stack depth TLS wrapper
+ if (F.getName() == SanCovLowestStackTLSWrapperName)
+ 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.
@@ -728,6 +764,20 @@ void SanitizerCoverageModule::InjectCove
SetNoSanitizeMetadata(Load);
SetNoSanitizeMetadata(Store);
}
+ if (Options.StackDepth && IsEntryBB) {
+ // Check stack depth. If it's the deepest so far, record it.
+ Function *GetFrameAddr =
+ Intrinsic::getDeclaration(F.getParent(), Intrinsic::frameaddress);
+ auto FrameAddrPtr =
+ IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)});
+ auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy);
+ auto LowestStackPtr = IRB.CreateCall(SanCovLowestStackTLSWrapper);
+ auto LowestStack = IRB.CreateLoad(LowestStackPtr);
+ auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack);
+ auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false);
+ IRBuilder<> ThenIRB(ThenTerm);
+ ThenIRB.CreateStore(FrameAddrInt, LowestStackPtr);
+ }
}
std::string
Added: llvm/trunk/test/Instrumentation/SanitizerCoverage/stack-depth.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/SanitizerCoverage/stack-depth.ll?rev=311186&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/SanitizerCoverage/stack-depth.ll (added)
+++ llvm/trunk/test/Instrumentation/SanitizerCoverage/stack-depth.ll Fri Aug 18 11:43:30 2017
@@ -0,0 +1,50 @@
+; This check verifies that stack depth instrumentation works correctly.
+; RUN: opt < %s -sancov -sanitizer-coverage-level=1 \
+; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s --enable-var-scope
+; RUN: opt < %s -sancov -sanitizer-coverage-level=3 \
+; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \
+; RUN: -S | FileCheck %s --enable-var-scope
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @__sancov_lowest_stack = thread_local global i64 -1
+ at __sancov_lowest_stack = thread_local global i64 0, align 8
+
+define i32 @foo() {
+entry:
+; CHECK-LABEL: define i32 @foo
+; CHECK: [[framePtr:%[^ \t]+]] = call i8* @llvm.frameaddress(i32 0)
+; CHECK: [[frameInt:%[^ \t]+]] = ptrtoint i8* [[framePtr]] to [[$intType:i[0-9]+]]
+; CHECK: [[lowestPtr:%[^ \t]+]] = call [[$intType]]* @_ZTW21__sancov_lowest_stack
+; CHECK: [[lowestInt:%[^ \t]+]] = load [[$intType]], [[$intType]]* [[lowestPtr]]
+; CHECK: [[cmp:%[^ \t]+]] = icmp ult [[$intType]] [[frameInt]], [[lowestInt]]
+; CHECK: br i1 [[cmp]], label %[[ifLabel:[^ \t]+]], label
+; CHECK: <label>:[[ifLabel]]:
+; CHECK: store [[$intType]] [[frameInt]], [[$intType]]* [[lowestPtr]]
+; CHECK: ret i32 7
+
+ ret i32 7
+}
+
+define i32 @bar() {
+entry:
+; CHECK-LABEL: define i32 @bar
+; CHECK: [[framePtr:%[^ \t]+]] = call i8* @llvm.frameaddress(i32 0)
+; CHECK: [[frameInt:%[^ \t]+]] = ptrtoint i8* [[framePtr]] to [[$intType]]
+; CHECK: [[lowestPtr:%[^ \t]+]] = call [[$intType]]* @_ZTW21__sancov_lowest_stack
+; CHECK: [[lowestInt:%[^ \t]+]] = load [[$intType]], [[$intType]]* [[lowestPtr]]
+; CHECK: [[cmp:%[^ \t]+]] = icmp ult [[$intType]] [[frameInt]], [[lowestInt]]
+; CHECK: br i1 [[cmp]], label %[[ifLabel:[^ \t]+]], label
+; CHECK: <label>:[[ifLabel]]:
+; CHECK: store [[$intType]] [[frameInt]], [[$intType]]* [[lowestPtr]]
+; CHECK: %call = call i32 @foo()
+; CHECK: ret i32 %call
+
+ %call = call i32 @foo()
+ ret i32 %call
+}
+
+define weak_odr hidden i64* @_ZTW21__sancov_lowest_stack() {
+ ret i64* @__sancov_lowest_stack
+}
More information about the llvm-commits
mailing list