Index: cfe/trunk/lib/Driver/SanitizerArgs.cpp =================================================================== --- cfe/trunk/lib/Driver/SanitizerArgs.cpp +++ cfe/trunk/lib/Driver/SanitizerArgs.cpp @@ -312,9 +312,13 @@ Add |= FuzzerNoLink; // Enable coverage if the fuzzing flag is set. - if (Add & FuzzerNoLink) + if (Add & FuzzerNoLink) { CoverageFeatures |= CoverageTracePCGuard | CoverageIndirCall | CoverageTraceCmp | CoveragePCTable; + // Due to TLS differences, stack depth tracking is only enabled on Linux + if (TC.getTriple().isOSLinux()) + CoverageFeatures |= CoverageStackDepth; + } Kinds |= Add; } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc @@ -211,5 +211,10 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_8bit_counters_init, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {} } // extern "C" +// Weak definition for code instrumented with -fsanitize-coverage=stack-depth +// and later linked with code containing a strong definition. +// E.g., -fsanitize=fuzzer-no-link +SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE +SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE uptr __sancov_lowest_stack; #endif // !SANITIZER_FUCHSIA Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_internal_defs.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_internal_defs.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_internal_defs.h @@ -35,6 +35,14 @@ # define SANITIZER_WEAK_ATTRIBUTE __attribute__((weak)) #endif +// TLS is handled differently on different platforms +#if SANITIZER_LINUX +# define SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE \ + __attribute__((tls_model("initial-exec"))) thread_local +#else +# define SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE +#endif + //--------------------------- WEAK FUNCTIONS ---------------------------------// // When working with weak functions, to simplify the code and make it more // portable, when possible define a default implementation using this macro: Index: compiler-rt/trunk/test/asan/TestCases/Darwin/interface_symbols_darwin.c =================================================================== --- compiler-rt/trunk/test/asan/TestCases/Darwin/interface_symbols_darwin.c +++ compiler-rt/trunk/test/asan/TestCases/Darwin/interface_symbols_darwin.c @@ -12,6 +12,7 @@ // RUN: | grep -v "__sanitizer_weak_hook" \ // RUN: | grep -v "__sanitizer_mz" \ // RUN: | grep -v "__ubsan_handle_dynamic_type_cache_miss" \ +// RUN: | grep -v "__sancov_lowest_stack" \ // RUN: | sed -e "s/__asan_version_mismatch_check_v[0-9]+/__asan_version_mismatch_check/" \ // RUN: > %t.exports // Index: compiler-rt/trunk/test/asan/TestCases/Linux/interface_symbols_linux.c =================================================================== --- compiler-rt/trunk/test/asan/TestCases/Linux/interface_symbols_linux.c +++ compiler-rt/trunk/test/asan/TestCases/Linux/interface_symbols_linux.c @@ -6,6 +6,7 @@ // RUN: | grep -v "__sanitizer_syscall" \ // RUN: | grep -v "__sanitizer_weak_hook" \ // RUN: | grep -v "__ubsan_handle_dynamic_type_cache_miss" \ +// RUN: | grep -v "__sancov_lowest_stack" \ // RUN: | sed -e "s/__asan_version_mismatch_check_v[0-9]+/__asan_version_mismatch_check/" \ // RUN: > %t.exports // Index: compiler-rt/trunk/test/asan/TestCases/Windows/interface_symbols_windows.c =================================================================== --- compiler-rt/trunk/test/asan/TestCases/Windows/interface_symbols_windows.c +++ compiler-rt/trunk/test/asan/TestCases/Windows/interface_symbols_windows.c @@ -38,6 +38,7 @@ // IMPORT: __asan_set_seh_filter // IMPORT: __asan_unhandled_exception_filter // IMPORT: __asan_test_only_reported_buggy_pointer +// IMPORT: __sancov_lowest_stack // // RUN: cat %t.imports1 %t.imports2 %t.imports3 | sort | uniq > %t.imports-sorted // RUN: cat %t.exports | sort | uniq > %t.exports-sorted Index: compiler-rt/trunk/test/fuzzer/deep-recursion.test =================================================================== --- compiler-rt/trunk/test/fuzzer/deep-recursion.test +++ compiler-rt/trunk/test/fuzzer/deep-recursion.test @@ -1,5 +1,5 @@ # Test that we can find a stack overflow REQUIRES: linux -RUN: %cpp_compiler -fsanitize-coverage=stack-depth %S/DeepRecursionTest.cpp -o %t +RUN: %cpp_compiler %S/DeepRecursionTest.cpp -o %t RUN: not %t -seed=1 -runs=100000000 2>&1 | FileCheck %s CHECK: ERROR: libFuzzer: deadly signal Index: llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -25,6 +25,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" @@ -200,13 +201,15 @@ ArrayRef GepTraceTargets); void InjectTraceForSwitch(Function &F, ArrayRef SwitchTraceTargets); - bool InjectCoverage(Function &F, ArrayRef AllBlocks); + bool InjectCoverage(Function &F, ArrayRef AllBlocks, + bool IsLeafFunc = true); GlobalVariable *CreateFunctionLocalArrayInSection(size_t NumElements, Function &F, Type *Ty, const char *Section); GlobalVariable *CreatePCArray(Function &F, ArrayRef AllBlocks); void CreateFunctionLocalArrays(Function &F, ArrayRef AllBlocks); - void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx); + void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, + bool IsLeafFunc = true); Function *CreateInitCallsForSections(Module &M, const char *InitFunctionName, Type *Ty, const char *Section); std::pair @@ -491,6 +494,7 @@ &getAnalysis(F).getDomTree(); const PostDominatorTree *PDT = &getAnalysis(F).getPostDomTree(); + bool IsLeafFunc = true; for (auto &BB : F) { if (shouldInstrumentBlock(F, &BB, DT, PDT, Options)) @@ -515,10 +519,14 @@ if (Options.TraceGep) if (GetElementPtrInst *GEP = dyn_cast(&Inst)) GepTraceTargets.push_back(GEP); - } + if (Options.StackDepth) + if (isa(Inst) || + (isa(Inst) && !isa(Inst))) + IsLeafFunc = false; + } } - InjectCoverage(F, BlocksToInstrument); + InjectCoverage(F, BlocksToInstrument, IsLeafFunc); InjectCoverageForIndirectCalls(F, IndirCalls); InjectTraceForCmp(F, CmpTraceTargets); InjectTraceForSwitch(F, SwitchTraceTargets); @@ -593,11 +601,12 @@ } bool SanitizerCoverageModule::InjectCoverage(Function &F, - ArrayRef AllBlocks) { + ArrayRef AllBlocks, + bool IsLeafFunc) { if (AllBlocks.empty()) return false; CreateFunctionLocalArrays(F, AllBlocks); for (size_t i = 0, N = AllBlocks.size(); i < N; i++) - InjectCoverageAtBlock(F, *AllBlocks[i], i); + InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); return true; } @@ -731,7 +740,8 @@ } void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, - size_t Idx) { + size_t Idx, + bool IsLeafFunc) { BasicBlock::iterator IP = BB.getFirstInsertionPt(); bool IsEntryBB = &BB == &F.getEntryBlock(); DebugLoc EntryLoc; @@ -770,7 +780,7 @@ SetNoSanitizeMetadata(Load); SetNoSanitizeMetadata(Store); } - if (Options.StackDepth && IsEntryBB) { + if (Options.StackDepth && IsEntryBB && !IsLeafFunc) { // Check stack depth. If it's the deepest so far, record it. Function *GetFrameAddr = Intrinsic::getDeclaration(F.getParent(), Intrinsic::frameaddress); @@ -781,7 +791,9 @@ auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false); IRBuilder<> ThenIRB(ThenTerm); - ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); + auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); + SetNoSanitizeMetadata(LowestStack); + SetNoSanitizeMetadata(Store); } } Index: llvm/trunk/test/Instrumentation/SanitizerCoverage/stack-depth.ll =================================================================== --- llvm/trunk/test/Instrumentation/SanitizerCoverage/stack-depth.ll +++ llvm/trunk/test/Instrumentation/SanitizerCoverage/stack-depth.ll @@ -1,9 +1,9 @@ ; 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: -sanitizer-coverage-stack-depth -S | FileCheck %s ; 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 +; RUN: -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -14,13 +14,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: [[lowest:%[^ \t]+]] = load [[$intType]], [[$intType]]* @__sancov_lowest_stack -; CHECK: [[cmp:%[^ \t]+]] = icmp ult [[$intType]] [[frameInt]], [[lowest]] -; CHECK: br i1 [[cmp]], label %[[ifLabel:[^ \t]+]], label -; CHECK: