]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- asan_fake_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 AddressSanitizer, an address sanity checker. | |
11 | // | |
12 | // Tests for FakeStack. | |
13 | // This test file should be compiled w/o asan instrumentation. | |
14 | //===----------------------------------------------------------------------===// | |
15 | ||
16 | #include "asan_fake_stack.h" | |
17 | #include "asan_test_utils.h" | |
18 | #include "sanitizer_common/sanitizer_common.h" | |
19 | ||
20 | #include <assert.h> | |
21 | #include <stdlib.h> | |
22 | #include <stdio.h> | |
23 | ||
24 | #include <map> | |
25 | ||
26 | namespace __asan { | |
27 | ||
28 | TEST(FakeStack, FlagsSize) { | |
29 | EXPECT_EQ(FakeStack::SizeRequiredForFlags(10), 1U << 5); | |
30 | EXPECT_EQ(FakeStack::SizeRequiredForFlags(11), 1U << 6); | |
31 | EXPECT_EQ(FakeStack::SizeRequiredForFlags(20), 1U << 15); | |
32 | } | |
33 | ||
34 | TEST(FakeStack, RequiredSize) { | |
35 | // for (int i = 15; i < 20; i++) { | |
36 | // uptr alloc_size = FakeStack::RequiredSize(i); | |
37 | // printf("%zdK ==> %zd\n", 1 << (i - 10), alloc_size); | |
38 | // } | |
39 | EXPECT_EQ(FakeStack::RequiredSize(15), 365568U); | |
40 | EXPECT_EQ(FakeStack::RequiredSize(16), 727040U); | |
41 | EXPECT_EQ(FakeStack::RequiredSize(17), 1449984U); | |
42 | EXPECT_EQ(FakeStack::RequiredSize(18), 2895872U); | |
43 | EXPECT_EQ(FakeStack::RequiredSize(19), 5787648U); | |
44 | } | |
45 | ||
46 | TEST(FakeStack, FlagsOffset) { | |
47 | for (uptr stack_size_log = 15; stack_size_log <= 20; stack_size_log++) { | |
48 | uptr stack_size = 1UL << stack_size_log; | |
49 | uptr offset = 0; | |
50 | for (uptr class_id = 0; class_id < FakeStack::kNumberOfSizeClasses; | |
51 | class_id++) { | |
52 | uptr frame_size = FakeStack::BytesInSizeClass(class_id); | |
53 | uptr num_flags = stack_size / frame_size; | |
54 | EXPECT_EQ(offset, FakeStack::FlagsOffset(stack_size_log, class_id)); | |
55 | // printf("%zd: %zd => %zd %zd\n", stack_size_log, class_id, offset, | |
56 | // FakeStack::FlagsOffset(stack_size_log, class_id)); | |
57 | offset += num_flags; | |
58 | } | |
59 | } | |
60 | } | |
61 | ||
92a42be0 | 62 | #if !defined(_WIN32) // FIXME: Fails due to OOM on Windows. |
1a4d82fc JJ |
63 | TEST(FakeStack, CreateDestroy) { |
64 | for (int i = 0; i < 1000; i++) { | |
65 | for (uptr stack_size_log = 20; stack_size_log <= 22; stack_size_log++) { | |
66 | FakeStack *fake_stack = FakeStack::Create(stack_size_log); | |
67 | fake_stack->Destroy(0); | |
68 | } | |
69 | } | |
70 | } | |
92a42be0 | 71 | #endif |
1a4d82fc JJ |
72 | |
73 | TEST(FakeStack, ModuloNumberOfFrames) { | |
74 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, 0), 0U); | |
75 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<15)), 0U); | |
76 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<10)), 0U); | |
77 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<9)), 0U); | |
78 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<8)), 1U<<8); | |
79 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<15) + 1), 1U); | |
80 | ||
81 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 0), 0U); | |
82 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<9), 0U); | |
83 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<8), 0U); | |
84 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<7), 1U<<7); | |
85 | ||
86 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 0), 0U); | |
87 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 1), 1U); | |
88 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 15), 15U); | |
89 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 16), 0U); | |
90 | EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 17), 1U); | |
91 | } | |
92 | ||
93 | TEST(FakeStack, GetFrame) { | |
94 | const uptr stack_size_log = 20; | |
95 | const uptr stack_size = 1 << stack_size_log; | |
96 | FakeStack *fs = FakeStack::Create(stack_size_log); | |
97 | u8 *base = fs->GetFrame(stack_size_log, 0, 0); | |
98 | EXPECT_EQ(base, reinterpret_cast<u8 *>(fs) + | |
99 | fs->SizeRequiredForFlags(stack_size_log) + 4096); | |
100 | EXPECT_EQ(base + 0*stack_size + 64 * 7, fs->GetFrame(stack_size_log, 0, 7U)); | |
101 | EXPECT_EQ(base + 1*stack_size + 128 * 3, fs->GetFrame(stack_size_log, 1, 3U)); | |
102 | EXPECT_EQ(base + 2*stack_size + 256 * 5, fs->GetFrame(stack_size_log, 2, 5U)); | |
103 | fs->Destroy(0); | |
104 | } | |
105 | ||
106 | TEST(FakeStack, Allocate) { | |
107 | const uptr stack_size_log = 19; | |
108 | FakeStack *fs = FakeStack::Create(stack_size_log); | |
109 | std::map<FakeFrame *, uptr> s; | |
110 | for (int iter = 0; iter < 2; iter++) { | |
111 | s.clear(); | |
112 | for (uptr cid = 0; cid < FakeStack::kNumberOfSizeClasses; cid++) { | |
113 | uptr n = FakeStack::NumberOfFrames(stack_size_log, cid); | |
114 | uptr bytes_in_class = FakeStack::BytesInSizeClass(cid); | |
115 | for (uptr j = 0; j < n; j++) { | |
116 | FakeFrame *ff = fs->Allocate(stack_size_log, cid, 0); | |
117 | uptr x = reinterpret_cast<uptr>(ff); | |
118 | EXPECT_TRUE(s.insert(std::make_pair(ff, cid)).second); | |
119 | EXPECT_EQ(x, fs->AddrIsInFakeStack(x)); | |
120 | EXPECT_EQ(x, fs->AddrIsInFakeStack(x + 1)); | |
121 | EXPECT_EQ(x, fs->AddrIsInFakeStack(x + bytes_in_class - 1)); | |
122 | EXPECT_NE(x, fs->AddrIsInFakeStack(x + bytes_in_class)); | |
123 | } | |
124 | // We are out of fake stack, so Allocate should return 0. | |
125 | EXPECT_EQ(0UL, fs->Allocate(stack_size_log, cid, 0)); | |
126 | } | |
127 | for (std::map<FakeFrame *, uptr>::iterator it = s.begin(); it != s.end(); | |
128 | ++it) { | |
129 | fs->Deallocate(reinterpret_cast<uptr>(it->first), it->second); | |
130 | } | |
131 | } | |
132 | fs->Destroy(0); | |
133 | } | |
134 | ||
135 | static void RecursiveFunction(FakeStack *fs, int depth) { | |
136 | uptr class_id = depth / 3; | |
137 | FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, 0); | |
138 | if (depth) { | |
139 | RecursiveFunction(fs, depth - 1); | |
140 | RecursiveFunction(fs, depth - 1); | |
141 | } | |
142 | fs->Deallocate(reinterpret_cast<uptr>(ff), class_id); | |
143 | } | |
144 | ||
145 | TEST(FakeStack, RecursiveStressTest) { | |
146 | const uptr stack_size_log = 16; | |
147 | FakeStack *fs = FakeStack::Create(stack_size_log); | |
148 | RecursiveFunction(fs, 22); // with 26 runs for 2-3 seconds. | |
149 | fs->Destroy(0); | |
150 | } | |
151 | ||
152 | } // namespace __asan |