1 /* 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 19 #include <memory> 20 21 #include "gtest/gtest.h" 22 23 namespace art { 24 25 class MemMapTest : public testing::Test { 26 public: 27 static byte* BaseBegin(MemMap* mem_map) { 28 return reinterpret_cast<byte*>(mem_map->base_begin_); 29 } 30 static size_t BaseSize(MemMap* mem_map) { 31 return mem_map->base_size_; 32 } 33 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 } 87 88 void CommonInit() { 89 MemMap::Init(); 90 } 91 92 #if defined(__LP64__) && !defined(__x86_64__) 93 static uintptr_t GetLinearScanPos() { 94 return MemMap::next_mem_pos_; 95 } 96 #endif 97 }; 98 99 #if defined(__LP64__) && !defined(__x86_64__) 100 101 #ifdef __BIONIC__ 102 extern uintptr_t CreateStartPos(uint64_t input); 103 #endif 104 105 TEST_F(MemMapTest, Start) { 106 CommonInit(); 107 uintptr_t start = GetLinearScanPos(); 108 EXPECT_LE(64 * KB, start); 109 EXPECT_LT(start, static_cast<uintptr_t>(ART_BASE_ADDRESS)); 110 #ifdef __BIONIC__ 111 // Test a couple of values. Make sure they are different. 112 uintptr_t last = 0; 113 for (size_t i = 0; i < 100; ++i) { 114 uintptr_t random_start = CreateStartPos(i * kPageSize); 115 EXPECT_NE(last, random_start); 116 last = random_start; 117 } 118 119 // Even on max, should be below ART_BASE_ADDRESS. 120 EXPECT_LT(CreateStartPos(~0), static_cast<uintptr_t>(ART_BASE_ADDRESS)); 121 #endif 122 // End of test. 123 } 124 #endif 125 126 TEST_F(MemMapTest, MapAnonymousEmpty) { 127 CommonInit(); 128 std::string error_msg; 129 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty", 130 nullptr, 131 0, 132 PROT_READ, 133 false, 134 &error_msg)); 135 ASSERT_TRUE(map.get() != nullptr) << error_msg; 136 ASSERT_TRUE(error_msg.empty()); 137 map.reset(MemMap::MapAnonymous("MapAnonymousEmpty", 138 nullptr, 139 kPageSize, 140 PROT_READ | PROT_WRITE, 141 false, 142 &error_msg)); 143 ASSERT_TRUE(map.get() != nullptr) << error_msg; 144 ASSERT_TRUE(error_msg.empty()); 145 } 146 147 #ifdef __LP64__ 148 TEST_F(MemMapTest, MapAnonymousEmpty32bit) { 149 CommonInit(); 150 std::string error_msg; 151 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty", 152 nullptr, 153 kPageSize, 154 PROT_READ | PROT_WRITE, 155 true, 156 &error_msg)); 157 ASSERT_TRUE(map.get() != nullptr) << error_msg; 158 ASSERT_TRUE(error_msg.empty()); 159 ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32); 160 } 161 #endif 162 163 TEST_F(MemMapTest, MapAnonymousExactAddr) { 164 CommonInit(); 165 std::string error_msg; 166 // Map at an address that should work, which should succeed. 167 std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0", 168 reinterpret_cast<byte*>(ART_BASE_ADDRESS), 169 kPageSize, 170 PROT_READ | PROT_WRITE, 171 false, 172 &error_msg)); 173 ASSERT_TRUE(map0.get() != nullptr) << error_msg; 174 ASSERT_TRUE(error_msg.empty()); 175 ASSERT_TRUE(map0->BaseBegin() == reinterpret_cast<void*>(ART_BASE_ADDRESS)); 176 // Map at an unspecified address, which should succeed. 177 std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1", 178 nullptr, 179 kPageSize, 180 PROT_READ | PROT_WRITE, 181 false, 182 &error_msg)); 183 ASSERT_TRUE(map1.get() != nullptr) << error_msg; 184 ASSERT_TRUE(error_msg.empty()); 185 ASSERT_TRUE(map1->BaseBegin() != nullptr); 186 // Attempt to map at the same address, which should fail. 187 std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2", 188 reinterpret_cast<byte*>(map1->BaseBegin()), 189 kPageSize, 190 PROT_READ | PROT_WRITE, 191 false, 192 &error_msg)); 193 ASSERT_TRUE(map2.get() == nullptr) << error_msg; 194 ASSERT_TRUE(!error_msg.empty()); 195 } 196 197 TEST_F(MemMapTest, RemapAtEnd) { 198 RemapAtEndTest(false); 199 } 200 201 #ifdef __LP64__ 202 TEST_F(MemMapTest, RemapAtEnd32bit) { 203 RemapAtEndTest(true); 204 } 205 #endif 206 207 TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) { 208 uintptr_t start_addr = ART_BASE_ADDRESS + 0x1000000; 209 std::string error_msg; 210 CommonInit(); 211 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousExactAddr32bitHighAddr", 212 reinterpret_cast<byte*>(start_addr), 213 0x21000000, 214 PROT_READ | PROT_WRITE, 215 true, 216 &error_msg)); 217 ASSERT_TRUE(map.get() != nullptr) << error_msg; 218 ASSERT_TRUE(error_msg.empty()); 219 ASSERT_EQ(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), start_addr); 220 } 221 222 TEST_F(MemMapTest, MapAnonymousOverflow) { 223 CommonInit(); 224 std::string error_msg; 225 uintptr_t ptr = 0; 226 ptr -= kPageSize; // Now it's close to the top. 227 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousOverflow", 228 reinterpret_cast<byte*>(ptr), 229 2 * kPageSize, // brings it over the top. 230 PROT_READ | PROT_WRITE, 231 false, 232 &error_msg)); 233 ASSERT_EQ(nullptr, map.get()); 234 ASSERT_FALSE(error_msg.empty()); 235 } 236 237 #ifdef __LP64__ 238 TEST_F(MemMapTest, MapAnonymousLow4GBExpectedTooHigh) { 239 CommonInit(); 240 std::string error_msg; 241 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBExpectedTooHigh", 242 reinterpret_cast<byte*>(UINT64_C(0x100000000)), 243 kPageSize, 244 PROT_READ | PROT_WRITE, 245 true, 246 &error_msg)); 247 ASSERT_EQ(nullptr, map.get()); 248 ASSERT_FALSE(error_msg.empty()); 249 } 250 251 TEST_F(MemMapTest, MapAnonymousLow4GBRangeTooHigh) { 252 CommonInit(); 253 std::string error_msg; 254 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBRangeTooHigh", 255 reinterpret_cast<byte*>(0xF0000000), 256 0x20000000, 257 PROT_READ | PROT_WRITE, 258 true, 259 &error_msg)); 260 ASSERT_EQ(nullptr, map.get()); 261 ASSERT_FALSE(error_msg.empty()); 262 } 263 #endif 264 265 TEST_F(MemMapTest, CheckNoGaps) { 266 CommonInit(); 267 std::string error_msg; 268 constexpr size_t kNumPages = 3; 269 // Map a 3-page mem map. 270 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymous0", 271 nullptr, 272 kPageSize * kNumPages, 273 PROT_READ | PROT_WRITE, 274 false, 275 &error_msg)); 276 ASSERT_TRUE(map.get() != nullptr) << error_msg; 277 ASSERT_TRUE(error_msg.empty()); 278 // Record the base address. 279 byte* map_base = reinterpret_cast<byte*>(map->BaseBegin()); 280 // Unmap it. 281 map.reset(); 282 283 // Map at the same address, but in page-sized separate mem maps, 284 // assuming the space at the address is still available. 285 std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0", 286 map_base, 287 kPageSize, 288 PROT_READ | PROT_WRITE, 289 false, 290 &error_msg)); 291 ASSERT_TRUE(map0.get() != nullptr) << error_msg; 292 ASSERT_TRUE(error_msg.empty()); 293 std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1", 294 map_base + kPageSize, 295 kPageSize, 296 PROT_READ | PROT_WRITE, 297 false, 298 &error_msg)); 299 ASSERT_TRUE(map1.get() != nullptr) << error_msg; 300 ASSERT_TRUE(error_msg.empty()); 301 std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2", 302 map_base + kPageSize * 2, 303 kPageSize, 304 PROT_READ | PROT_WRITE, 305 false, 306 &error_msg)); 307 ASSERT_TRUE(map2.get() != nullptr) << error_msg; 308 ASSERT_TRUE(error_msg.empty()); 309 310 // One-map cases. 311 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map0.get())); 312 ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map1.get())); 313 ASSERT_TRUE(MemMap::CheckNoGaps(map2.get(), map2.get())); 314 315 // Two or three-map cases. 316 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map1.get())); 317 ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map2.get())); 318 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map2.get())); 319 320 // Unmap the middle one. 321 map1.reset(); 322 323 // Should return false now that there's a gap in the middle. 324 ASSERT_FALSE(MemMap::CheckNoGaps(map0.get(), map2.get())); 325 } 326 327 } // namespace art 328