blob: c07a9a3842e3dde3e4f930ab02f1c1b40edd1132 [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
Brian Carlstrom9004cb62013-07-26 15:48:31 -070021#include "gtest/gtest.h"
22
23namespace art {
24
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -070025class MemMapTest : public testing::Test {
26 public:
Ian Rogersef7d42f2014-01-06 12:55:46 -080027 static byte* BaseBegin(MemMap* mem_map) {
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -070028 return reinterpret_cast<byte*>(mem_map->base_begin_);
29 }
Ian Rogersef7d42f2014-01-06 12:55:46 -080030 static size_t BaseSize(MemMap* mem_map) {
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -070031 return mem_map->base_size_;
32 }
Ian Rogersef7d42f2014-01-06 12:55:46 -080033
34 static void RemapAtEndTest(bool low_4gb) {
35 std::string error_msg;
36 // Cast the page size to size_t.
37 const size_t page_size = static_cast<size_t>(kPageSize);
38 // Map a two-page memory region.
39 MemMap* m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0",
40 nullptr,
41 2 * page_size,
42 PROT_READ | PROT_WRITE,
43 low_4gb,
44 &error_msg);
45 // Check its state and write to it.
46 byte* base0 = m0->Begin();
47 ASSERT_TRUE(base0 != nullptr) << error_msg;
48 size_t size0 = m0->Size();
49 EXPECT_EQ(m0->Size(), 2 * page_size);
50 EXPECT_EQ(BaseBegin(m0), base0);
51 EXPECT_EQ(BaseSize(m0), size0);
52 memset(base0, 42, 2 * page_size);
53 // Remap the latter half into a second MemMap.
54 MemMap* m1 = m0->RemapAtEnd(base0 + page_size,
55 "MemMapTest_RemapAtEndTest_map1",
56 PROT_READ | PROT_WRITE,
57 &error_msg);
58 // Check the states of the two maps.
59 EXPECT_EQ(m0->Begin(), base0) << error_msg;
60 EXPECT_EQ(m0->Size(), page_size);
61 EXPECT_EQ(BaseBegin(m0), base0);
62 EXPECT_EQ(BaseSize(m0), page_size);
63 byte* base1 = m1->Begin();
64 size_t size1 = m1->Size();
65 EXPECT_EQ(base1, base0 + page_size);
66 EXPECT_EQ(size1, page_size);
67 EXPECT_EQ(BaseBegin(m1), base1);
68 EXPECT_EQ(BaseSize(m1), size1);
69 // Write to the second region.
70 memset(base1, 43, page_size);
71 // Check the contents of the two regions.
72 for (size_t i = 0; i < page_size; ++i) {
73 EXPECT_EQ(base0[i], 42);
74 }
75 for (size_t i = 0; i < page_size; ++i) {
76 EXPECT_EQ(base1[i], 43);
77 }
78 // Unmap the first region.
79 delete m0;
80 // Make sure the second region is still accessible after the first
81 // region is unmapped.
82 for (size_t i = 0; i < page_size; ++i) {
83 EXPECT_EQ(base1[i], 43);
84 }
85 delete m1;
86 }
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -070087};
Brian Carlstrom9004cb62013-07-26 15:48:31 -070088
89TEST_F(MemMapTest, MapAnonymousEmpty) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -070090 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -070091 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
Ian Rogersef7d42f2014-01-06 12:55:46 -080092 nullptr,
Brian Carlstrom9004cb62013-07-26 15:48:31 -070093 0,
Ian Rogers8d31bbd2013-10-13 10:44:14 -070094 PROT_READ,
Ian Rogersef7d42f2014-01-06 12:55:46 -080095 false,
Ian Rogers8d31bbd2013-10-13 10:44:14 -070096 &error_msg));
Ian Rogersef7d42f2014-01-06 12:55:46 -080097 ASSERT_TRUE(map.get() != nullptr) << error_msg;
98 ASSERT_TRUE(error_msg.empty());
99 map.reset(MemMap::MapAnonymous("MapAnonymousEmpty",
100 nullptr,
101 kPageSize,
102 PROT_READ | PROT_WRITE,
103 false,
104 &error_msg));
105 ASSERT_TRUE(map.get() != nullptr) << error_msg;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700106 ASSERT_TRUE(error_msg.empty());
Brian Carlstrom9004cb62013-07-26 15:48:31 -0700107}
108
Ian Rogersef7d42f2014-01-06 12:55:46 -0800109#ifdef __LP64__
110TEST_F(MemMapTest, MapAnonymousEmpty32bit) {
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700111 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -0700112 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
Ian Rogersef7d42f2014-01-06 12:55:46 -0800113 nullptr,
114 kPageSize,
115 PROT_READ | PROT_WRITE,
116 true,
117 &error_msg));
118 ASSERT_TRUE(map.get() != nullptr) << error_msg;
119 ASSERT_TRUE(error_msg.empty());
120 ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32);
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700121}
Ian Rogersef7d42f2014-01-06 12:55:46 -0800122#endif
123
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -0700124TEST_F(MemMapTest, MapAnonymousExactAddr) {
125 std::string error_msg;
126 // Map at an address that should work, which should succeed.
Ian Rogers700a4022014-05-19 16:49:03 -0700127 std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0",
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -0700128 reinterpret_cast<byte*>(ART_BASE_ADDRESS),
129 kPageSize,
130 PROT_READ | PROT_WRITE,
131 false,
132 &error_msg));
133 ASSERT_TRUE(map0.get() != nullptr) << error_msg;
134 ASSERT_TRUE(error_msg.empty());
135 ASSERT_TRUE(map0->BaseBegin() == reinterpret_cast<void*>(ART_BASE_ADDRESS));
136 // Map at an unspecified address, which should succeed.
Ian Rogers700a4022014-05-19 16:49:03 -0700137 std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1",
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -0700138 nullptr,
139 kPageSize,
140 PROT_READ | PROT_WRITE,
141 false,
142 &error_msg));
143 ASSERT_TRUE(map1.get() != nullptr) << error_msg;
144 ASSERT_TRUE(error_msg.empty());
145 ASSERT_TRUE(map1->BaseBegin() != nullptr);
146 // Attempt to map at the same address, which should fail.
Ian Rogers700a4022014-05-19 16:49:03 -0700147 std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2",
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -0700148 reinterpret_cast<byte*>(map1->BaseBegin()),
149 kPageSize,
150 PROT_READ | PROT_WRITE,
151 false,
152 &error_msg));
153 ASSERT_TRUE(map2.get() == nullptr) << error_msg;
154 ASSERT_TRUE(!error_msg.empty());
155}
156
Ian Rogersef7d42f2014-01-06 12:55:46 -0800157TEST_F(MemMapTest, RemapAtEnd) {
158 RemapAtEndTest(false);
159}
160
161#ifdef __LP64__
162TEST_F(MemMapTest, RemapAtEnd32bit) {
163 RemapAtEndTest(true);
164}
165#endif
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700166
Qiming Shi84d49cc2014-04-24 15:38:41 +0800167TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) {
168 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -0700169 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousExactAddr32bitHighAddr",
Qiming Shi84d49cc2014-04-24 15:38:41 +0800170 reinterpret_cast<byte*>(0x71000000),
171 0x21000000,
172 PROT_READ | PROT_WRITE,
173 true,
174 &error_msg));
175 ASSERT_TRUE(map.get() != nullptr) << error_msg;
176 ASSERT_TRUE(error_msg.empty());
177 ASSERT_EQ(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 0x71000000U);
178}
179
180TEST_F(MemMapTest, MapAnonymousOverflow) {
181 std::string error_msg;
182 uintptr_t ptr = 0;
183 ptr -= kPageSize; // Now it's close to the top.
Ian Rogers700a4022014-05-19 16:49:03 -0700184 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousOverflow",
Qiming Shi84d49cc2014-04-24 15:38:41 +0800185 reinterpret_cast<byte*>(ptr),
186 2 * kPageSize, // brings it over the top.
187 PROT_READ | PROT_WRITE,
188 false,
189 &error_msg));
190 ASSERT_EQ(nullptr, map.get());
191 ASSERT_FALSE(error_msg.empty());
192}
193
194#ifdef __LP64__
195TEST_F(MemMapTest, MapAnonymousLow4GBExpectedTooHigh) {
196 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -0700197 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBExpectedTooHigh",
Qiming Shi84d49cc2014-04-24 15:38:41 +0800198 reinterpret_cast<byte*>(UINT64_C(0x100000000)),
199 kPageSize,
200 PROT_READ | PROT_WRITE,
201 true,
202 &error_msg));
203 ASSERT_EQ(nullptr, map.get());
204 ASSERT_FALSE(error_msg.empty());
205}
206
207TEST_F(MemMapTest, MapAnonymousLow4GBRangeTooHigh) {
208 std::string error_msg;
Ian Rogers700a4022014-05-19 16:49:03 -0700209 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBRangeTooHigh",
Qiming Shi84d49cc2014-04-24 15:38:41 +0800210 reinterpret_cast<byte*>(0xF0000000),
211 0x20000000,
212 PROT_READ | PROT_WRITE,
213 true,
214 &error_msg));
215 ASSERT_EQ(nullptr, map.get());
216 ASSERT_FALSE(error_msg.empty());
217}
218#endif
219
Brian Carlstrom9004cb62013-07-26 15:48:31 -0700220} // namespace art