blob: a78f4631f78e6ff3f1042adefb569a9c608cf1a8 [file] [log] [blame]
Brian Carlstrom9004cb62013-07-26 15:48:31 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "mem_map.h"
18
Ian Rogers700a4022014-05-19 16:49:03 -070019#include <memory>
20
Andreas Gampe928f72b2014-09-09 19:53:48 -070021#include <valgrind.h>
22
Brian Carlstrom9004cb62013-07-26 15:48:31 -070023#include "gtest/gtest.h"
24
25namespace art {
26
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -070027class MemMapTest : public testing::Test {
28 public:
Ian Rogers13735952014-10-08 12:43:28 -070029 static uint8_t* BaseBegin(MemMap* mem_map) {
30 return reinterpret_cast<uint8_t*>(mem_map->base_begin_);
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -070031 }
Ian Rogersef7d42f2014-01-06 12:55:46 -080032 static size_t BaseSize(MemMap* mem_map) {
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -070033 return mem_map->base_size_;
34 }
Ian Rogersef7d42f2014-01-06 12:55:46 -080035
36 static void RemapAtEndTest(bool low_4gb) {
37 std::string error_msg;
38 // Cast the page size to size_t.
39 const size_t page_size = static_cast<size_t>(kPageSize);
40 // Map a two-page memory region.
41 MemMap* m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0",
42 nullptr,
43 2 * page_size,
44 PROT_READ | PROT_WRITE,
45 low_4gb,
46 &error_msg);
47 // Check its state and write to it.
Ian Rogers13735952014-10-08 12:43:28 -070048 uint8_t* base0 = m0->Begin();
Ian Rogersef7d42f2014-01-06 12:55:46 -080049 ASSERT_TRUE(base0 != nullptr) << error_msg;
50 size_t size0 = m0->Size();
51 EXPECT_EQ(m0->Size(), 2 * page_size);
52 EXPECT_EQ(BaseBegin(m0), base0);
53 EXPECT_EQ(BaseSize(m0), size0);
54 memset(base0, 42, 2 * page_size);
55 // Remap the latter half into a second MemMap.
56 MemMap* m1 = m0->RemapAtEnd(base0 + page_size,
57 "MemMapTest_RemapAtEndTest_map1",
58 PROT_READ | PROT_WRITE,
59 &error_msg);
60 // Check the states of the two maps.
61 EXPECT_EQ(m0->Begin(), base0) << error_msg;
62 EXPECT_EQ(m0->Size(), page_size);
63 EXPECT_EQ(BaseBegin(m0), base0);
64 EXPECT_EQ(BaseSize(m0), page_size);
Ian Rogers13735952014-10-08 12:43:28 -070065 uint8_t* base1 = m1->Begin();
Ian Rogersef7d42f2014-01-06 12:55:46 -080066 size_t size1 = m1->Size();
67 EXPECT_EQ(base1, base0 + page_size);
68 EXPECT_EQ(size1, page_size);
69 EXPECT_EQ(BaseBegin(m1), base1);
70 EXPECT_EQ(BaseSize(m1), size1);
71 // Write to the second region.
72 memset(base1, 43, page_size);
73 // Check the contents of the two regions.
74 for (size_t i = 0; i < page_size; ++i) {
75 EXPECT_EQ(base0[i], 42);
76 }
77 for (size_t i = 0; i < page_size; ++i) {
78 EXPECT_EQ(base1[i], 43);
79 }
80 // Unmap the first region.
81 delete m0;
82 // Make sure the second region is still accessible after the first
83 // region is unmapped.
84 for (size_t i = 0; i < page_size; ++i) {
85 EXPECT_EQ(base1[i], 43);
86 }
87 delete m1;
88 }
Andreas Gamped8f26db2014-05-19 17:01:13 -070089
90#if defined(__LP64__) && !defined(__x86_64__)
91 static uintptr_t GetLinearScanPos() {
92 return MemMap::next_mem_pos_;
93 }
94#endif
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -070095};
Brian Carlstrom9004cb62013-07-26 15:48:31 -070096
Andreas Gamped8f26db2014-05-19 17:01:13 -070097#if defined(__LP64__) && !defined(__x86_64__)
98
99#ifdef __BIONIC__
100extern uintptr_t CreateStartPos(uint64_t input);
101#endif
102
103TEST_F(MemMapTest, Start) {
104 uintptr_t start = GetLinearScanPos();
105 EXPECT_LE(64 * KB, start);
106 EXPECT_LT(start, static_cast<uintptr_t>(ART_BASE_ADDRESS));
107
108#ifdef __BIONIC__
109 // Test a couple of values. Make sure they are different.
110 uintptr_t last = 0;
111 for (size_t i = 0; i < 100; ++i) {
112 uintptr_t random_start = CreateStartPos(i * kPageSize);
113 EXPECT_NE(last, random_start);
114 last = random_start;
115 }
116
117 // Even on max, should be below ART_BASE_ADDRESS.
118 EXPECT_LT(CreateStartPos(~0), static_cast<uintptr_t>(ART_BASE_ADDRESS));
119#endif
120 // End of test.
121}
122#endif
123
Brian Carlstrom9004cb62013-07-26 15:48:31 -0700124TEST_F(MemMapTest, MapAnonymousEmpty) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700125 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -0700126 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
Ian Rogersef7d42f2014-01-06 12:55:46 -0800127 nullptr,
Brian Carlstrom9004cb62013-07-26 15:48:31 -0700128 0,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700129 PROT_READ,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800130 false,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700131 &error_msg));
Ian Rogersef7d42f2014-01-06 12:55:46 -0800132 ASSERT_TRUE(map.get() != nullptr) << error_msg;
133 ASSERT_TRUE(error_msg.empty());
134 map.reset(MemMap::MapAnonymous("MapAnonymousEmpty",
135 nullptr,
136 kPageSize,
137 PROT_READ | PROT_WRITE,
138 false,
139 &error_msg));
140 ASSERT_TRUE(map.get() != nullptr) << error_msg;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700141 ASSERT_TRUE(error_msg.empty());
Brian Carlstrom9004cb62013-07-26 15:48:31 -0700142}
143
Ian Rogersef7d42f2014-01-06 12:55:46 -0800144#ifdef __LP64__
145TEST_F(MemMapTest, MapAnonymousEmpty32bit) {
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700146 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -0700147 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
Ian Rogersef7d42f2014-01-06 12:55:46 -0800148 nullptr,
149 kPageSize,
150 PROT_READ | PROT_WRITE,
151 true,
152 &error_msg));
153 ASSERT_TRUE(map.get() != nullptr) << error_msg;
154 ASSERT_TRUE(error_msg.empty());
155 ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32);
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700156}
Ian Rogersef7d42f2014-01-06 12:55:46 -0800157#endif
158
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -0700159TEST_F(MemMapTest, MapAnonymousExactAddr) {
160 std::string error_msg;
161 // Map at an address that should work, which should succeed.
Ian Rogers700a4022014-05-19 16:49:03 -0700162 std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0",
Ian Rogers13735952014-10-08 12:43:28 -0700163 reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS),
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -0700164 kPageSize,
165 PROT_READ | PROT_WRITE,
166 false,
167 &error_msg));
168 ASSERT_TRUE(map0.get() != nullptr) << error_msg;
169 ASSERT_TRUE(error_msg.empty());
170 ASSERT_TRUE(map0->BaseBegin() == reinterpret_cast<void*>(ART_BASE_ADDRESS));
171 // Map at an unspecified address, which should succeed.
Ian Rogers700a4022014-05-19 16:49:03 -0700172 std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1",
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -0700173 nullptr,
174 kPageSize,
175 PROT_READ | PROT_WRITE,
176 false,
177 &error_msg));
178 ASSERT_TRUE(map1.get() != nullptr) << error_msg;
179 ASSERT_TRUE(error_msg.empty());
180 ASSERT_TRUE(map1->BaseBegin() != nullptr);
181 // Attempt to map at the same address, which should fail.
Ian Rogers700a4022014-05-19 16:49:03 -0700182 std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2",
Ian Rogers13735952014-10-08 12:43:28 -0700183 reinterpret_cast<uint8_t*>(map1->BaseBegin()),
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -0700184 kPageSize,
185 PROT_READ | PROT_WRITE,
186 false,
187 &error_msg));
188 ASSERT_TRUE(map2.get() == nullptr) << error_msg;
189 ASSERT_TRUE(!error_msg.empty());
190}
191
Ian Rogersef7d42f2014-01-06 12:55:46 -0800192TEST_F(MemMapTest, RemapAtEnd) {
193 RemapAtEndTest(false);
194}
195
196#ifdef __LP64__
197TEST_F(MemMapTest, RemapAtEnd32bit) {
198 RemapAtEndTest(true);
199}
200#endif
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700201
Qiming Shi84d49cc2014-04-24 15:38:41 +0800202TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) {
Andreas Gampe928f72b2014-09-09 19:53:48 -0700203 // This test may not work under valgrind.
204 if (RUNNING_ON_VALGRIND == 0) {
205 uintptr_t start_addr = ART_BASE_ADDRESS + 0x1000000;
206 std::string error_msg;
207 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousExactAddr32bitHighAddr",
Ian Rogers13735952014-10-08 12:43:28 -0700208 reinterpret_cast<uint8_t*>(start_addr),
Andreas Gampe928f72b2014-09-09 19:53:48 -0700209 0x21000000,
210 PROT_READ | PROT_WRITE,
211 true,
212 &error_msg));
213 ASSERT_TRUE(map.get() != nullptr) << error_msg;
214 ASSERT_TRUE(error_msg.empty());
215 ASSERT_EQ(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), start_addr);
216 }
Qiming Shi84d49cc2014-04-24 15:38:41 +0800217}
218
219TEST_F(MemMapTest, MapAnonymousOverflow) {
220 std::string error_msg;
221 uintptr_t ptr = 0;
222 ptr -= kPageSize; // Now it's close to the top.
Ian Rogers700a4022014-05-19 16:49:03 -0700223 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousOverflow",
Ian Rogers13735952014-10-08 12:43:28 -0700224 reinterpret_cast<uint8_t*>(ptr),
Qiming Shi84d49cc2014-04-24 15:38:41 +0800225 2 * kPageSize, // brings it over the top.
226 PROT_READ | PROT_WRITE,
227 false,
228 &error_msg));
229 ASSERT_EQ(nullptr, map.get());
230 ASSERT_FALSE(error_msg.empty());
231}
232
233#ifdef __LP64__
234TEST_F(MemMapTest, MapAnonymousLow4GBExpectedTooHigh) {
235 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -0700236 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBExpectedTooHigh",
Ian Rogers13735952014-10-08 12:43:28 -0700237 reinterpret_cast<uint8_t*>(UINT64_C(0x100000000)),
Qiming Shi84d49cc2014-04-24 15:38:41 +0800238 kPageSize,
239 PROT_READ | PROT_WRITE,
240 true,
241 &error_msg));
242 ASSERT_EQ(nullptr, map.get());
243 ASSERT_FALSE(error_msg.empty());
244}
245
246TEST_F(MemMapTest, MapAnonymousLow4GBRangeTooHigh) {
247 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -0700248 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBRangeTooHigh",
Ian Rogers13735952014-10-08 12:43:28 -0700249 reinterpret_cast<uint8_t*>(0xF0000000),
Qiming Shi84d49cc2014-04-24 15:38:41 +0800250 0x20000000,
251 PROT_READ | PROT_WRITE,
252 true,
253 &error_msg));
254 ASSERT_EQ(nullptr, map.get());
255 ASSERT_FALSE(error_msg.empty());
256}
257#endif
258
Hiroshi Yamauchi3eed93d2014-06-04 11:43:59 -0700259TEST_F(MemMapTest, CheckNoGaps) {
260 std::string error_msg;
261 constexpr size_t kNumPages = 3;
262 // Map a 3-page mem map.
263 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymous0",
264 nullptr,
265 kPageSize * kNumPages,
266 PROT_READ | PROT_WRITE,
267 false,
268 &error_msg));
269 ASSERT_TRUE(map.get() != nullptr) << error_msg;
270 ASSERT_TRUE(error_msg.empty());
271 // Record the base address.
Ian Rogers13735952014-10-08 12:43:28 -0700272 uint8_t* map_base = reinterpret_cast<uint8_t*>(map->BaseBegin());
Hiroshi Yamauchi3eed93d2014-06-04 11:43:59 -0700273 // Unmap it.
274 map.reset();
275
276 // Map at the same address, but in page-sized separate mem maps,
277 // assuming the space at the address is still available.
278 std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0",
279 map_base,
280 kPageSize,
281 PROT_READ | PROT_WRITE,
282 false,
283 &error_msg));
284 ASSERT_TRUE(map0.get() != nullptr) << error_msg;
285 ASSERT_TRUE(error_msg.empty());
286 std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1",
287 map_base + kPageSize,
288 kPageSize,
289 PROT_READ | PROT_WRITE,
290 false,
291 &error_msg));
292 ASSERT_TRUE(map1.get() != nullptr) << error_msg;
293 ASSERT_TRUE(error_msg.empty());
294 std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2",
295 map_base + kPageSize * 2,
296 kPageSize,
297 PROT_READ | PROT_WRITE,
298 false,
299 &error_msg));
300 ASSERT_TRUE(map2.get() != nullptr) << error_msg;
301 ASSERT_TRUE(error_msg.empty());
302
303 // One-map cases.
304 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map0.get()));
305 ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map1.get()));
306 ASSERT_TRUE(MemMap::CheckNoGaps(map2.get(), map2.get()));
307
308 // Two or three-map cases.
309 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map1.get()));
310 ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map2.get()));
311 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map2.get()));
312
313 // Unmap the middle one.
314 map1.reset();
315
316 // Should return false now that there's a gap in the middle.
317 ASSERT_FALSE(MemMap::CheckNoGaps(map0.get(), map2.get()));
318}
319
Brian Carlstrom9004cb62013-07-26 15:48:31 -0700320} // namespace art