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 18 namespace __tsan { 19 20 template <typename StackTraceTy> 21 static 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 49 template<typename StackTraceTy> 50 static 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 75 TEST(StackTrace, BasicVarSize) { 76 VarSizeStackTrace trace; 77 TestStackTrace(&trace); 78 } 79 80 TEST(StackTrace, BasicBuffered) { 81 BufferedStackTrace trace; 82 TestStackTrace(&trace); 83 } 84 85 TEST(StackTrace, TrimVarSize) { 86 VarSizeStackTrace trace; 87 TestTrim(&trace); 88 } 89 90 TEST(StackTrace, TrimBuffered) { 91 BufferedStackTrace trace; 92 TestTrim(&trace); 93 } 94 95 } // namespace __tsan 96