1 //===-- tsan_shadow_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_platform.h" 13 #include "tsan_rtl.h" 14 #include "gtest/gtest.h" 15 16 namespace __tsan { 17 18 TEST(Shadow, FastState) { 19 Shadow s(FastState(11, 22)); 20 EXPECT_EQ(s.tid(), (u64)11); 21 EXPECT_EQ(s.epoch(), (u64)22); 22 EXPECT_EQ(s.GetIgnoreBit(), false); 23 EXPECT_EQ(s.GetFreedAndReset(), false); 24 EXPECT_EQ(s.GetHistorySize(), 0); 25 EXPECT_EQ(s.addr0(), (u64)0); 26 EXPECT_EQ(s.size(), (u64)1); 27 EXPECT_EQ(s.IsWrite(), true); 28 29 s.IncrementEpoch(); 30 EXPECT_EQ(s.epoch(), (u64)23); 31 s.IncrementEpoch(); 32 EXPECT_EQ(s.epoch(), (u64)24); 33 34 s.SetIgnoreBit(); 35 EXPECT_EQ(s.GetIgnoreBit(), true); 36 s.ClearIgnoreBit(); 37 EXPECT_EQ(s.GetIgnoreBit(), false); 38 39 for (int i = 0; i < 8; i++) { 40 s.SetHistorySize(i); 41 EXPECT_EQ(s.GetHistorySize(), i); 42 } 43 s.SetHistorySize(2); 44 s.ClearHistorySize(); 45 EXPECT_EQ(s.GetHistorySize(), 0); 46 } 47 48 TEST(Shadow, Mapping) { 49 static int global; 50 int stack; 51 void *heap = malloc(0); 52 free(heap); 53 54 CHECK(IsAppMem((uptr)&global)); 55 CHECK(IsAppMem((uptr)&stack)); 56 CHECK(IsAppMem((uptr)heap)); 57 58 CHECK(IsShadowMem(MemToShadow((uptr)&global))); 59 CHECK(IsShadowMem(MemToShadow((uptr)&stack))); 60 CHECK(IsShadowMem(MemToShadow((uptr)heap))); 61 } 62 63 TEST(Shadow, Celling) { 64 u64 aligned_data[4]; 65 char *data = (char*)aligned_data; 66 CHECK(IsAligned(reinterpret_cast<uptr>(data), kShadowSize)); 67 RawShadow *s0 = MemToShadow((uptr)&data[0]); 68 CHECK(IsAligned(reinterpret_cast<uptr>(s0), kShadowSize)); 69 for (unsigned i = 1; i < kShadowCell; i++) 70 CHECK_EQ(s0, MemToShadow((uptr)&data[i])); 71 for (unsigned i = kShadowCell; i < 2*kShadowCell; i++) 72 CHECK_EQ(s0 + kShadowCnt, MemToShadow((uptr)&data[i])); 73 for (unsigned i = 2*kShadowCell; i < 3*kShadowCell; i++) 74 CHECK_EQ(s0 + 2 * kShadowCnt, MemToShadow((uptr)&data[i])); 75 } 76 77 // Detect is the Mapping has kBroken field. 78 template <uptr> 79 struct Has { 80 typedef bool Result; 81 }; 82 83 template <typename Mapping> 84 bool broken(...) { 85 return false; 86 } 87 88 template <typename Mapping> 89 bool broken(uptr what, typename Has<Mapping::kBroken>::Result = false) { 90 return Mapping::kBroken & what; 91 } 92 93 struct MappingTest { 94 template <typename Mapping> 95 static void Apply() { 96 // Easy (but ugly) way to print the mapping name. 97 Printf("%s\n", __PRETTY_FUNCTION__); 98 TestRegion<Mapping>(Mapping::kLoAppMemBeg, Mapping::kLoAppMemEnd); 99 TestRegion<Mapping>(Mapping::kMidAppMemBeg, Mapping::kMidAppMemEnd); 100 TestRegion<Mapping>(Mapping::kHiAppMemBeg, Mapping::kHiAppMemEnd); 101 TestRegion<Mapping>(Mapping::kHeapMemBeg, Mapping::kHeapMemEnd); 102 } 103 104 template <typename Mapping> 105 static void TestRegion(uptr beg, uptr end) { 106 if (beg == end) 107 return; 108 Printf("checking region [%p-%p)\n", beg, end); 109 uptr prev = 0; 110 for (uptr p0 = beg; p0 <= end; p0 += (end - beg) / 256) { 111 for (int x = -(int)kShadowCell; x <= (int)kShadowCell; x += kShadowCell) { 112 const uptr p = RoundDown(p0 + x, kShadowCell); 113 if (p < beg || p >= end) 114 continue; 115 const uptr s = MemToShadowImpl::Apply<Mapping>(p); 116 u32 *const m = MemToMetaImpl::Apply<Mapping>(p); 117 const uptr r = ShadowToMemImpl::Apply<Mapping>(s); 118 Printf(" addr=%p: shadow=%p meta=%p reverse=%p\n", p, s, m, r); 119 CHECK(IsAppMemImpl::Apply<Mapping>(p)); 120 if (!broken<Mapping>(kBrokenMapping)) 121 CHECK(IsShadowMemImpl::Apply<Mapping>(s)); 122 CHECK(IsMetaMemImpl::Apply<Mapping>(reinterpret_cast<uptr>(m))); 123 if (!broken<Mapping>(kBrokenReverseMapping)) 124 CHECK_EQ(p, r); 125 if (prev && !broken<Mapping>(kBrokenLinearity)) { 126 // Ensure that shadow and meta mappings are linear within a single 127 // user range. Lots of code that processes memory ranges assumes it. 128 const uptr prev_s = MemToShadowImpl::Apply<Mapping>(prev); 129 u32 *const prev_m = MemToMetaImpl::Apply<Mapping>(prev); 130 CHECK_EQ(s - prev_s, (p - prev) * kShadowMultiplier); 131 CHECK_EQ(m - prev_m, (p - prev) / kMetaShadowCell); 132 } 133 prev = p; 134 } 135 } 136 } 137 }; 138 139 TEST(Shadow, AllMappings) { ForEachMapping<MappingTest>(); } 140 141 } // namespace __tsan 142