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 <valgrind.h> 22 23 #include "gtest/gtest.h" 24 25 namespace art { 26 27 class MemMapTest : public testing::Test { 28 public: 29 static uint8_t* BaseBegin(MemMap* mem_map) { 30 return reinterpret_cast<uint8_t*>(mem_map->base_begin_); 31 } 32 static size_t BaseSize(MemMap* mem_map) { 33 return mem_map->base_size_; 34 } 35 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 false, 47 &error_msg); 48 // Check its state and write to it. 49 uint8_t* base0 = m0->Begin(); 50 ASSERT_TRUE(base0 != nullptr) << error_msg; 51 size_t size0 = m0->Size(); 52 EXPECT_EQ(m0->Size(), 2 * page_size); 53 EXPECT_EQ(BaseBegin(m0), base0); 54 EXPECT_EQ(BaseSize(m0), size0); 55 memset(base0, 42, 2 * page_size); 56 // Remap the latter half into a second MemMap. 57 MemMap* m1 = m0->RemapAtEnd(base0 + page_size, 58 "MemMapTest_RemapAtEndTest_map1", 59 PROT_READ | PROT_WRITE, 60 &error_msg); 61 // Check the states of the two maps. 62 EXPECT_EQ(m0->Begin(), base0) << error_msg; 63 EXPECT_EQ(m0->Size(), page_size); 64 EXPECT_EQ(BaseBegin(m0), base0); 65 EXPECT_EQ(BaseSize(m0), page_size); 66 uint8_t* base1 = m1->Begin(); 67 size_t size1 = m1->Size(); 68 EXPECT_EQ(base1, base0 + page_size); 69 EXPECT_EQ(size1, page_size); 70 EXPECT_EQ(BaseBegin(m1), base1); 71 EXPECT_EQ(BaseSize(m1), size1); 72 // Write to the second region. 73 memset(base1, 43, page_size); 74 // Check the contents of the two regions. 75 for (size_t i = 0; i < page_size; ++i) { 76 EXPECT_EQ(base0[i], 42); 77 } 78 for (size_t i = 0; i < page_size; ++i) { 79 EXPECT_EQ(base1[i], 43); 80 } 81 // Unmap the first region. 82 delete m0; 83 // Make sure the second region is still accessible after the first 84 // region is unmapped. 85 for (size_t i = 0; i < page_size; ++i) { 86 EXPECT_EQ(base1[i], 43); 87 } 88 delete m1; 89 } 90 91 void CommonInit() { 92 MemMap::Init(); 93 } 94 95 #if defined(__LP64__) && !defined(__x86_64__) 96 static uintptr_t GetLinearScanPos() { 97 return MemMap::next_mem_pos_; 98 } 99 #endif 100 }; 101 102 #if defined(__LP64__) && !defined(__x86_64__) 103 104 #ifdef __BIONIC__ 105 extern uintptr_t CreateStartPos(uint64_t input); 106 #endif 107 108 TEST_F(MemMapTest, Start) { 109 CommonInit(); 110 uintptr_t start = GetLinearScanPos(); 111 EXPECT_LE(64 * KB, start); 112 EXPECT_LT(start, static_cast<uintptr_t>(ART_BASE_ADDRESS)); 113 #ifdef __BIONIC__ 114 // Test a couple of values. Make sure they are different. 115 uintptr_t last = 0; 116 for (size_t i = 0; i < 100; ++i) { 117 uintptr_t random_start = CreateStartPos(i * kPageSize); 118 EXPECT_NE(last, random_start); 119 last = random_start; 120 } 121 122 // Even on max, should be below ART_BASE_ADDRESS. 123 EXPECT_LT(CreateStartPos(~0), static_cast<uintptr_t>(ART_BASE_ADDRESS)); 124 #endif 125 // End of test. 126 } 127 #endif 128 129 TEST_F(MemMapTest, MapAnonymousEmpty) { 130 CommonInit(); 131 std::string error_msg; 132 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty", 133 nullptr, 134 0, 135 PROT_READ, 136 false, 137 false, 138 &error_msg)); 139 ASSERT_TRUE(map.get() != nullptr) << error_msg; 140 ASSERT_TRUE(error_msg.empty()); 141 map.reset(MemMap::MapAnonymous("MapAnonymousEmpty", 142 nullptr, 143 kPageSize, 144 PROT_READ | PROT_WRITE, 145 false, 146 false, 147 &error_msg)); 148 ASSERT_TRUE(map.get() != nullptr) << error_msg; 149 ASSERT_TRUE(error_msg.empty()); 150 } 151 152 #ifdef __LP64__ 153 TEST_F(MemMapTest, MapAnonymousEmpty32bit) { 154 CommonInit(); 155 std::string error_msg; 156 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty", 157 nullptr, 158 kPageSize, 159 PROT_READ | PROT_WRITE, 160 true, 161 false, 162 &error_msg)); 163 ASSERT_TRUE(map.get() != nullptr) << error_msg; 164 ASSERT_TRUE(error_msg.empty()); 165 ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32); 166 } 167 #endif 168 169 TEST_F(MemMapTest, MapAnonymousExactAddr) { 170 CommonInit(); 171 std::string error_msg; 172 // Map at an address that should work, which should succeed. 173 std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0", 174 reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS), 175 kPageSize, 176 PROT_READ | PROT_WRITE, 177 false, 178 false, 179 &error_msg)); 180 ASSERT_TRUE(map0.get() != nullptr) << error_msg; 181 ASSERT_TRUE(error_msg.empty()); 182 ASSERT_TRUE(map0->BaseBegin() == reinterpret_cast<void*>(ART_BASE_ADDRESS)); 183 // Map at an unspecified address, which should succeed. 184 std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1", 185 nullptr, 186 kPageSize, 187 PROT_READ | PROT_WRITE, 188 false, 189 false, 190 &error_msg)); 191 ASSERT_TRUE(map1.get() != nullptr) << error_msg; 192 ASSERT_TRUE(error_msg.empty()); 193 ASSERT_TRUE(map1->BaseBegin() != nullptr); 194 // Attempt to map at the same address, which should fail. 195 std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2", 196 reinterpret_cast<uint8_t*>(map1->BaseBegin()), 197 kPageSize, 198 PROT_READ | PROT_WRITE, 199 false, 200 false, 201 &error_msg)); 202 ASSERT_TRUE(map2.get() == nullptr) << error_msg; 203 ASSERT_TRUE(!error_msg.empty()); 204 } 205 206 TEST_F(MemMapTest, RemapAtEnd) { 207 RemapAtEndTest(false); 208 } 209 210 #ifdef __LP64__ 211 TEST_F(MemMapTest, RemapAtEnd32bit) { 212 RemapAtEndTest(true); 213 } 214 #endif 215 216 TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) { 217 CommonInit(); 218 // This test may not work under valgrind. 219 if (RUNNING_ON_VALGRIND == 0) { 220 uintptr_t start_addr = ART_BASE_ADDRESS + 0x1000000; 221 std::string error_msg; 222 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousExactAddr32bitHighAddr", 223 reinterpret_cast<uint8_t*>(start_addr), 224 0x21000000, 225 PROT_READ | PROT_WRITE, 226 true, 227 false, 228 &error_msg)); 229 ASSERT_TRUE(map.get() != nullptr) << error_msg; 230 ASSERT_TRUE(error_msg.empty()); 231 ASSERT_EQ(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), start_addr); 232 } 233 } 234 235 TEST_F(MemMapTest, MapAnonymousOverflow) { 236 CommonInit(); 237 std::string error_msg; 238 uintptr_t ptr = 0; 239 ptr -= kPageSize; // Now it's close to the top. 240 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousOverflow", 241 reinterpret_cast<uint8_t*>(ptr), 242 2 * kPageSize, // brings it over the top. 243 PROT_READ | PROT_WRITE, 244 false, 245 false, 246 &error_msg)); 247 ASSERT_EQ(nullptr, map.get()); 248 ASSERT_FALSE(error_msg.empty()); 249 } 250 251 #ifdef __LP64__ 252 TEST_F(MemMapTest, MapAnonymousLow4GBExpectedTooHigh) { 253 CommonInit(); 254 std::string error_msg; 255 std::unique_ptr<MemMap> map( 256 MemMap::MapAnonymous("MapAnonymousLow4GBExpectedTooHigh", 257 reinterpret_cast<uint8_t*>(UINT64_C(0x100000000)), 258 kPageSize, 259 PROT_READ | PROT_WRITE, 260 true, 261 false, 262 &error_msg)); 263 ASSERT_EQ(nullptr, map.get()); 264 ASSERT_FALSE(error_msg.empty()); 265 } 266 267 TEST_F(MemMapTest, MapAnonymousLow4GBRangeTooHigh) { 268 CommonInit(); 269 std::string error_msg; 270 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBRangeTooHigh", 271 reinterpret_cast<uint8_t*>(0xF0000000), 272 0x20000000, 273 PROT_READ | PROT_WRITE, 274 true, 275 false, 276 &error_msg)); 277 ASSERT_EQ(nullptr, map.get()); 278 ASSERT_FALSE(error_msg.empty()); 279 } 280 #endif 281 282 TEST_F(MemMapTest, MapAnonymousReuse) { 283 CommonInit(); 284 std::string error_msg; 285 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousReserve", 286 nullptr, 287 0x20000, 288 PROT_READ | PROT_WRITE, 289 false, 290 false, 291 &error_msg)); 292 ASSERT_NE(nullptr, map.get()); 293 ASSERT_TRUE(error_msg.empty()); 294 std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymousReused", 295 reinterpret_cast<uint8_t*>(map->BaseBegin()), 296 0x10000, 297 PROT_READ | PROT_WRITE, 298 false, 299 true, 300 &error_msg)); 301 ASSERT_NE(nullptr, map2.get()); 302 ASSERT_TRUE(error_msg.empty()); 303 } 304 305 TEST_F(MemMapTest, CheckNoGaps) { 306 CommonInit(); 307 std::string error_msg; 308 constexpr size_t kNumPages = 3; 309 // Map a 3-page mem map. 310 std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymous0", 311 nullptr, 312 kPageSize * kNumPages, 313 PROT_READ | PROT_WRITE, 314 false, 315 false, 316 &error_msg)); 317 ASSERT_TRUE(map.get() != nullptr) << error_msg; 318 ASSERT_TRUE(error_msg.empty()); 319 // Record the base address. 320 uint8_t* map_base = reinterpret_cast<uint8_t*>(map->BaseBegin()); 321 // Unmap it. 322 map.reset(); 323 324 // Map at the same address, but in page-sized separate mem maps, 325 // assuming the space at the address is still available. 326 std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0", 327 map_base, 328 kPageSize, 329 PROT_READ | PROT_WRITE, 330 false, 331 false, 332 &error_msg)); 333 ASSERT_TRUE(map0.get() != nullptr) << error_msg; 334 ASSERT_TRUE(error_msg.empty()); 335 std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1", 336 map_base + kPageSize, 337 kPageSize, 338 PROT_READ | PROT_WRITE, 339 false, 340 false, 341 &error_msg)); 342 ASSERT_TRUE(map1.get() != nullptr) << error_msg; 343 ASSERT_TRUE(error_msg.empty()); 344 std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2", 345 map_base + kPageSize * 2, 346 kPageSize, 347 PROT_READ | PROT_WRITE, 348 false, 349 false, 350 &error_msg)); 351 ASSERT_TRUE(map2.get() != nullptr) << error_msg; 352 ASSERT_TRUE(error_msg.empty()); 353 354 // One-map cases. 355 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map0.get())); 356 ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map1.get())); 357 ASSERT_TRUE(MemMap::CheckNoGaps(map2.get(), map2.get())); 358 359 // Two or three-map cases. 360 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map1.get())); 361 ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map2.get())); 362 ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map2.get())); 363 364 // Unmap the middle one. 365 map1.reset(); 366 367 // Should return false now that there's a gap in the middle. 368 ASSERT_FALSE(MemMap::CheckNoGaps(map0.get(), map2.get())); 369 } 370 371 } // namespace art 372