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(kMainTid); 22 23 ObtainCurrentStack(&thr, 0, trace); 24 EXPECT_EQ(0U, trace->size); 25 26 ObtainCurrentStack(&thr, 42, trace); 27 EXPECT_EQ(1U, trace->size); 28 EXPECT_EQ(42U, trace->trace[0]); 29 30 *thr.shadow_stack_pos++ = 100; 31 *thr.shadow_stack_pos++ = 101; 32 ObtainCurrentStack(&thr, 0, trace); 33 EXPECT_EQ(2U, trace->size); 34 EXPECT_EQ(100U, trace->trace[0]); 35 EXPECT_EQ(101U, trace->trace[1]); 36 37 ObtainCurrentStack(&thr, 42, trace); 38 EXPECT_EQ(3U, trace->size); 39 EXPECT_EQ(100U, trace->trace[0]); 40 EXPECT_EQ(101U, trace->trace[1]); 41 EXPECT_EQ(42U, trace->trace[2]); 42 } 43 44 template<typename StackTraceTy> 45 static void TestTrim(StackTraceTy *trace) { 46 ThreadState thr(kMainTid); 47 48 for (uptr i = 0; i < 2 * kStackTraceMax; ++i) 49 *thr.shadow_stack_pos++ = 100 + i; 50 51 ObtainCurrentStack(&thr, 0, trace); 52 EXPECT_EQ(kStackTraceMax, trace->size); 53 for (uptr i = 0; i < kStackTraceMax; i++) { 54 EXPECT_EQ(100 + kStackTraceMax + i, trace->trace[i]); 55 } 56 57 ObtainCurrentStack(&thr, 42, trace); 58 EXPECT_EQ(kStackTraceMax, trace->size); 59 for (uptr i = 0; i < kStackTraceMax - 1; i++) { 60 EXPECT_EQ(101 + kStackTraceMax + i, trace->trace[i]); 61 } 62 EXPECT_EQ(42U, trace->trace[kStackTraceMax - 1]); 63 } 64 65 TEST(StackTrace, BasicVarSize) { 66 VarSizeStackTrace trace; 67 TestStackTrace(&trace); 68 } 69 70 TEST(StackTrace, BasicBuffered) { 71 BufferedStackTrace trace; 72 TestStackTrace(&trace); 73 } 74 75 TEST(StackTrace, TrimVarSize) { 76 VarSizeStackTrace trace; 77 TestTrim(&trace); 78 } 79 80 TEST(StackTrace, TrimBuffered) { 81 BufferedStackTrace trace; 82 TestTrim(&trace); 83 } 84 85 } // namespace __tsan 86