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