1//===-- tsan_stack_test.cc ------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of ThreadSanitizer (TSan), a race detector. 11// 12//===----------------------------------------------------------------------===// 13#include "tsan_sync.h" 14#include "tsan_rtl.h" 15#include "gtest/gtest.h" 16#include <string.h> 17 18namespace __tsan { 19 20template <typename StackTraceTy> 21static void TestStackTrace(StackTraceTy *trace) { 22 ThreadState thr(0, 0, 0, 0, 0, 0, 0, 0, 0); 23 uptr stack[128]; 24 thr.shadow_stack = &stack[0]; 25 thr.shadow_stack_pos = &stack[0]; 26 thr.shadow_stack_end = &stack[128]; 27 28 ObtainCurrentStack(&thr, 0, trace); 29 EXPECT_EQ(0U, trace->size); 30 31 ObtainCurrentStack(&thr, 42, trace); 32 EXPECT_EQ(1U, trace->size); 33 EXPECT_EQ(42U, trace->trace[0]); 34 35 *thr.shadow_stack_pos++ = 100; 36 *thr.shadow_stack_pos++ = 101; 37 ObtainCurrentStack(&thr, 0, trace); 38 EXPECT_EQ(2U, trace->size); 39 EXPECT_EQ(100U, trace->trace[0]); 40 EXPECT_EQ(101U, trace->trace[1]); 41 42 ObtainCurrentStack(&thr, 42, trace); 43 EXPECT_EQ(3U, trace->size); 44 EXPECT_EQ(100U, trace->trace[0]); 45 EXPECT_EQ(101U, trace->trace[1]); 46 EXPECT_EQ(42U, trace->trace[2]); 47} 48 49template<typename StackTraceTy> 50static void TestTrim(StackTraceTy *trace) { 51 ThreadState thr(0, 0, 0, 0, 0, 0, 0, 0, 0); 52 const uptr kShadowStackSize = 2 * kStackTraceMax; 53 uptr stack[kShadowStackSize]; 54 thr.shadow_stack = &stack[0]; 55 thr.shadow_stack_pos = &stack[0]; 56 thr.shadow_stack_end = &stack[kShadowStackSize]; 57 58 for (uptr i = 0; i < kShadowStackSize; ++i) 59 *thr.shadow_stack_pos++ = 100 + i; 60 61 ObtainCurrentStack(&thr, 0, trace); 62 EXPECT_EQ(kStackTraceMax, trace->size); 63 for (uptr i = 0; i < kStackTraceMax; i++) { 64 EXPECT_EQ(100 + kStackTraceMax + i, trace->trace[i]); 65 } 66 67 ObtainCurrentStack(&thr, 42, trace); 68 EXPECT_EQ(kStackTraceMax, trace->size); 69 for (uptr i = 0; i < kStackTraceMax - 1; i++) { 70 EXPECT_EQ(101 + kStackTraceMax + i, trace->trace[i]); 71 } 72 EXPECT_EQ(42U, trace->trace[kStackTraceMax - 1]); 73} 74 75TEST(StackTrace, BasicVarSize) { 76 VarSizeStackTrace trace; 77 TestStackTrace(&trace); 78} 79 80TEST(StackTrace, BasicBuffered) { 81 BufferedStackTrace trace; 82 TestStackTrace(&trace); 83} 84 85TEST(StackTrace, TrimVarSize) { 86 VarSizeStackTrace trace; 87 TestTrim(&trace); 88} 89 90TEST(StackTrace, TrimBuffered) { 91 BufferedStackTrace trace; 92 TestTrim(&trace); 93} 94 95} // namespace __tsan 96