xref: /openbsd-src/gnu/llvm/compiler-rt/lib/tsan/tests/unit/tsan_stack_test.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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