| Brian Carlstrom | 9004cb6 | 2013-07-26 15:48:31 -0700 | [diff] [blame] | 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 |  | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 19 | #include <memory> | 
 | 20 |  | 
| Mathieu Chartier | 42bddce | 2015-11-09 15:16:56 -0800 | [diff] [blame] | 21 | #include "common_runtime_test.h" | 
| Evgenii Stepanov | 1e13374 | 2015-05-20 12:30:59 -0700 | [diff] [blame] | 22 | #include "base/memory_tool.h" | 
| Mathieu Chartier | 42bddce | 2015-11-09 15:16:56 -0800 | [diff] [blame] | 23 | #include "base/unix_file/fd_file.h" | 
| Brian Carlstrom | 9004cb6 | 2013-07-26 15:48:31 -0700 | [diff] [blame] | 24 |  | 
 | 25 | namespace art { | 
 | 26 |  | 
| Mathieu Chartier | 42bddce | 2015-11-09 15:16:56 -0800 | [diff] [blame] | 27 | class MemMapTest : public CommonRuntimeTest { | 
| Hiroshi Yamauchi | fd7e7f1 | 2013-10-22 14:17:48 -0700 | [diff] [blame] | 28 |  public: | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 29 |   static uint8_t* BaseBegin(MemMap* mem_map) { | 
 | 30 |     return reinterpret_cast<uint8_t*>(mem_map->base_begin_); | 
| Hiroshi Yamauchi | fd7e7f1 | 2013-10-22 14:17:48 -0700 | [diff] [blame] | 31 |   } | 
| Mathieu Chartier | 16d29f8 | 2015-11-10 10:32:52 -0800 | [diff] [blame] | 32 |  | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 33 |   static size_t BaseSize(MemMap* mem_map) { | 
| Hiroshi Yamauchi | fd7e7f1 | 2013-10-22 14:17:48 -0700 | [diff] [blame] | 34 |     return mem_map->base_size_; | 
 | 35 |   } | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 36 |  | 
| Mathieu Chartier | 16d29f8 | 2015-11-10 10:32:52 -0800 | [diff] [blame] | 37 |   static uint8_t* GetValidMapAddress(size_t size, bool low_4gb) { | 
 | 38 |     // Find a valid map address and unmap it before returning. | 
 | 39 |     std::string error_msg; | 
 | 40 |     std::unique_ptr<MemMap> map(MemMap::MapAnonymous("temp", | 
 | 41 |                                                      nullptr, | 
 | 42 |                                                      size, | 
 | 43 |                                                      PROT_READ, | 
 | 44 |                                                      low_4gb, | 
 | 45 |                                                      false, | 
 | 46 |                                                      &error_msg)); | 
 | 47 |     CHECK(map != nullptr); | 
 | 48 |     return map->Begin(); | 
 | 49 |   } | 
 | 50 |  | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 51 |   static void RemapAtEndTest(bool low_4gb) { | 
 | 52 |     std::string error_msg; | 
 | 53 |     // Cast the page size to size_t. | 
 | 54 |     const size_t page_size = static_cast<size_t>(kPageSize); | 
 | 55 |     // Map a two-page memory region. | 
 | 56 |     MemMap* m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0", | 
 | 57 |                                       nullptr, | 
 | 58 |                                       2 * page_size, | 
 | 59 |                                       PROT_READ | PROT_WRITE, | 
 | 60 |                                       low_4gb, | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 61 |                                       false, | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 62 |                                       &error_msg); | 
 | 63 |     // Check its state and write to it. | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 64 |     uint8_t* base0 = m0->Begin(); | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 65 |     ASSERT_TRUE(base0 != nullptr) << error_msg; | 
 | 66 |     size_t size0 = m0->Size(); | 
 | 67 |     EXPECT_EQ(m0->Size(), 2 * page_size); | 
 | 68 |     EXPECT_EQ(BaseBegin(m0), base0); | 
 | 69 |     EXPECT_EQ(BaseSize(m0), size0); | 
 | 70 |     memset(base0, 42, 2 * page_size); | 
 | 71 |     // Remap the latter half into a second MemMap. | 
 | 72 |     MemMap* m1 = m0->RemapAtEnd(base0 + page_size, | 
 | 73 |                                 "MemMapTest_RemapAtEndTest_map1", | 
 | 74 |                                 PROT_READ | PROT_WRITE, | 
 | 75 |                                 &error_msg); | 
 | 76 |     // Check the states of the two maps. | 
 | 77 |     EXPECT_EQ(m0->Begin(), base0) << error_msg; | 
 | 78 |     EXPECT_EQ(m0->Size(), page_size); | 
 | 79 |     EXPECT_EQ(BaseBegin(m0), base0); | 
 | 80 |     EXPECT_EQ(BaseSize(m0), page_size); | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 81 |     uint8_t* base1 = m1->Begin(); | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 82 |     size_t size1 = m1->Size(); | 
 | 83 |     EXPECT_EQ(base1, base0 + page_size); | 
 | 84 |     EXPECT_EQ(size1, page_size); | 
 | 85 |     EXPECT_EQ(BaseBegin(m1), base1); | 
 | 86 |     EXPECT_EQ(BaseSize(m1), size1); | 
 | 87 |     // Write to the second region. | 
 | 88 |     memset(base1, 43, page_size); | 
 | 89 |     // Check the contents of the two regions. | 
 | 90 |     for (size_t i = 0; i < page_size; ++i) { | 
 | 91 |       EXPECT_EQ(base0[i], 42); | 
 | 92 |     } | 
 | 93 |     for (size_t i = 0; i < page_size; ++i) { | 
 | 94 |       EXPECT_EQ(base1[i], 43); | 
 | 95 |     } | 
 | 96 |     // Unmap the first region. | 
 | 97 |     delete m0; | 
 | 98 |     // Make sure the second region is still accessible after the first | 
 | 99 |     // region is unmapped. | 
 | 100 |     for (size_t i = 0; i < page_size; ++i) { | 
 | 101 |       EXPECT_EQ(base1[i], 43); | 
 | 102 |     } | 
 | 103 |     delete m1; | 
 | 104 |   } | 
| Andreas Gampe | d8f26db | 2014-05-19 17:01:13 -0700 | [diff] [blame] | 105 |  | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 106 |   void CommonInit() { | 
 | 107 |     MemMap::Init(); | 
 | 108 |   } | 
 | 109 |  | 
| Andreas Gampe | d8f26db | 2014-05-19 17:01:13 -0700 | [diff] [blame] | 110 | #if defined(__LP64__) && !defined(__x86_64__) | 
 | 111 |   static uintptr_t GetLinearScanPos() { | 
 | 112 |     return MemMap::next_mem_pos_; | 
 | 113 |   } | 
 | 114 | #endif | 
| Hiroshi Yamauchi | fd7e7f1 | 2013-10-22 14:17:48 -0700 | [diff] [blame] | 115 | }; | 
| Brian Carlstrom | 9004cb6 | 2013-07-26 15:48:31 -0700 | [diff] [blame] | 116 |  | 
| Andreas Gampe | d8f26db | 2014-05-19 17:01:13 -0700 | [diff] [blame] | 117 | #if defined(__LP64__) && !defined(__x86_64__) | 
 | 118 |  | 
 | 119 | #ifdef __BIONIC__ | 
 | 120 | extern uintptr_t CreateStartPos(uint64_t input); | 
 | 121 | #endif | 
 | 122 |  | 
 | 123 | TEST_F(MemMapTest, Start) { | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 124 |   CommonInit(); | 
| Andreas Gampe | d8f26db | 2014-05-19 17:01:13 -0700 | [diff] [blame] | 125 |   uintptr_t start = GetLinearScanPos(); | 
 | 126 |   EXPECT_LE(64 * KB, start); | 
 | 127 |   EXPECT_LT(start, static_cast<uintptr_t>(ART_BASE_ADDRESS)); | 
| Andreas Gampe | d8f26db | 2014-05-19 17:01:13 -0700 | [diff] [blame] | 128 | #ifdef __BIONIC__ | 
 | 129 |   // Test a couple of values. Make sure they are different. | 
 | 130 |   uintptr_t last = 0; | 
 | 131 |   for (size_t i = 0; i < 100; ++i) { | 
 | 132 |     uintptr_t random_start = CreateStartPos(i * kPageSize); | 
 | 133 |     EXPECT_NE(last, random_start); | 
 | 134 |     last = random_start; | 
 | 135 |   } | 
 | 136 |  | 
 | 137 |   // Even on max, should be below ART_BASE_ADDRESS. | 
 | 138 |   EXPECT_LT(CreateStartPos(~0), static_cast<uintptr_t>(ART_BASE_ADDRESS)); | 
 | 139 | #endif | 
 | 140 |   // End of test. | 
 | 141 | } | 
 | 142 | #endif | 
 | 143 |  | 
| Brian Carlstrom | 9004cb6 | 2013-07-26 15:48:31 -0700 | [diff] [blame] | 144 | TEST_F(MemMapTest, MapAnonymousEmpty) { | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 145 |   CommonInit(); | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 146 |   std::string error_msg; | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 147 |   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty", | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 148 |                                                    nullptr, | 
 | 149 |                                                    0, | 
 | 150 |                                                    PROT_READ, | 
 | 151 |                                                    false, | 
 | 152 |                                                    false, | 
 | 153 |                                                    &error_msg)); | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 154 |   ASSERT_TRUE(map.get() != nullptr) << error_msg; | 
 | 155 |   ASSERT_TRUE(error_msg.empty()); | 
 | 156 |   map.reset(MemMap::MapAnonymous("MapAnonymousEmpty", | 
 | 157 |                                  nullptr, | 
 | 158 |                                  kPageSize, | 
 | 159 |                                  PROT_READ | PROT_WRITE, | 
 | 160 |                                  false, | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 161 |                                  false, | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 162 |                                  &error_msg)); | 
 | 163 |   ASSERT_TRUE(map.get() != nullptr) << error_msg; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 164 |   ASSERT_TRUE(error_msg.empty()); | 
| Brian Carlstrom | 9004cb6 | 2013-07-26 15:48:31 -0700 | [diff] [blame] | 165 | } | 
 | 166 |  | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 167 | #ifdef __LP64__ | 
 | 168 | TEST_F(MemMapTest, MapAnonymousEmpty32bit) { | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 169 |   CommonInit(); | 
| Hiroshi Yamauchi | fd7e7f1 | 2013-10-22 14:17:48 -0700 | [diff] [blame] | 170 |   std::string error_msg; | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 171 |   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty", | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 172 |                                                    nullptr, | 
 | 173 |                                                    kPageSize, | 
 | 174 |                                                    PROT_READ | PROT_WRITE, | 
 | 175 |                                                    true, | 
 | 176 |                                                    false, | 
 | 177 |                                                    &error_msg)); | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 178 |   ASSERT_TRUE(map.get() != nullptr) << error_msg; | 
 | 179 |   ASSERT_TRUE(error_msg.empty()); | 
 | 180 |   ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32); | 
| Hiroshi Yamauchi | fd7e7f1 | 2013-10-22 14:17:48 -0700 | [diff] [blame] | 181 | } | 
| Mathieu Chartier | 42bddce | 2015-11-09 15:16:56 -0800 | [diff] [blame] | 182 | TEST_F(MemMapTest, MapFile32Bit) { | 
 | 183 |   CommonInit(); | 
 | 184 |   std::string error_msg; | 
 | 185 |   ScratchFile scratch_file; | 
 | 186 |   constexpr size_t kMapSize = kPageSize; | 
 | 187 |   std::unique_ptr<uint8_t[]> data(new uint8_t[kMapSize]()); | 
 | 188 |   ASSERT_TRUE(scratch_file.GetFile()->WriteFully(&data[0], kMapSize)); | 
 | 189 |   std::unique_ptr<MemMap> map(MemMap::MapFile(/*byte_count*/kMapSize, | 
 | 190 |                                               PROT_READ, | 
 | 191 |                                               MAP_PRIVATE, | 
 | 192 |                                               scratch_file.GetFd(), | 
 | 193 |                                               /*start*/0, | 
 | 194 |                                               /*low_4gb*/true, | 
 | 195 |                                               scratch_file.GetFilename().c_str(), | 
 | 196 |                                               &error_msg)); | 
 | 197 |   ASSERT_TRUE(map != nullptr) << error_msg; | 
 | 198 |   ASSERT_TRUE(error_msg.empty()); | 
 | 199 |   ASSERT_EQ(map->Size(), kMapSize); | 
 | 200 |   ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32); | 
 | 201 | } | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 202 | #endif | 
 | 203 |  | 
| Hiroshi Yamauchi | 4fb5df8 | 2014-03-13 15:10:27 -0700 | [diff] [blame] | 204 | TEST_F(MemMapTest, MapAnonymousExactAddr) { | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 205 |   CommonInit(); | 
| Hiroshi Yamauchi | 4fb5df8 | 2014-03-13 15:10:27 -0700 | [diff] [blame] | 206 |   std::string error_msg; | 
| Mathieu Chartier | 16d29f8 | 2015-11-10 10:32:52 -0800 | [diff] [blame] | 207 |   // Find a valid address. | 
 | 208 |   uint8_t* valid_address = GetValidMapAddress(kPageSize, /*low_4gb*/false); | 
| Hiroshi Yamauchi | 4fb5df8 | 2014-03-13 15:10:27 -0700 | [diff] [blame] | 209 |   // Map at an address that should work, which should succeed. | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 210 |   std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0", | 
| Mathieu Chartier | 16d29f8 | 2015-11-10 10:32:52 -0800 | [diff] [blame] | 211 |                                                     valid_address, | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 212 |                                                     kPageSize, | 
 | 213 |                                                     PROT_READ | PROT_WRITE, | 
 | 214 |                                                     false, | 
 | 215 |                                                     false, | 
 | 216 |                                                     &error_msg)); | 
| Hiroshi Yamauchi | 4fb5df8 | 2014-03-13 15:10:27 -0700 | [diff] [blame] | 217 |   ASSERT_TRUE(map0.get() != nullptr) << error_msg; | 
 | 218 |   ASSERT_TRUE(error_msg.empty()); | 
| Mathieu Chartier | 16d29f8 | 2015-11-10 10:32:52 -0800 | [diff] [blame] | 219 |   ASSERT_TRUE(map0->BaseBegin() == valid_address); | 
| Hiroshi Yamauchi | 4fb5df8 | 2014-03-13 15:10:27 -0700 | [diff] [blame] | 220 |   // Map at an unspecified address, which should succeed. | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 221 |   std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1", | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 222 |                                                     nullptr, | 
 | 223 |                                                     kPageSize, | 
 | 224 |                                                     PROT_READ | PROT_WRITE, | 
 | 225 |                                                     false, | 
 | 226 |                                                     false, | 
 | 227 |                                                     &error_msg)); | 
| Hiroshi Yamauchi | 4fb5df8 | 2014-03-13 15:10:27 -0700 | [diff] [blame] | 228 |   ASSERT_TRUE(map1.get() != nullptr) << error_msg; | 
 | 229 |   ASSERT_TRUE(error_msg.empty()); | 
 | 230 |   ASSERT_TRUE(map1->BaseBegin() != nullptr); | 
 | 231 |   // Attempt to map at the same address, which should fail. | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 232 |   std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2", | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 233 |                                                     reinterpret_cast<uint8_t*>(map1->BaseBegin()), | 
 | 234 |                                                     kPageSize, | 
 | 235 |                                                     PROT_READ | PROT_WRITE, | 
 | 236 |                                                     false, | 
 | 237 |                                                     false, | 
 | 238 |                                                     &error_msg)); | 
| Hiroshi Yamauchi | 4fb5df8 | 2014-03-13 15:10:27 -0700 | [diff] [blame] | 239 |   ASSERT_TRUE(map2.get() == nullptr) << error_msg; | 
 | 240 |   ASSERT_TRUE(!error_msg.empty()); | 
 | 241 | } | 
 | 242 |  | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 243 | TEST_F(MemMapTest, RemapAtEnd) { | 
 | 244 |   RemapAtEndTest(false); | 
 | 245 | } | 
 | 246 |  | 
 | 247 | #ifdef __LP64__ | 
 | 248 | TEST_F(MemMapTest, RemapAtEnd32bit) { | 
 | 249 |   RemapAtEndTest(true); | 
 | 250 | } | 
 | 251 | #endif | 
| Hiroshi Yamauchi | fd7e7f1 | 2013-10-22 14:17:48 -0700 | [diff] [blame] | 252 |  | 
| Qiming Shi | 84d49cc | 2014-04-24 15:38:41 +0800 | [diff] [blame] | 253 | TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) { | 
| Roland Levillain | 14306b8 | 2016-01-20 12:13:57 +0000 | [diff] [blame^] | 254 |   // Some MIPS32 hardware (namely the Creator Ci20 development board) | 
 | 255 |   // cannot allocate in the 2GB-4GB region. | 
 | 256 |   TEST_DISABLED_FOR_MIPS(); | 
 | 257 |  | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 258 |   CommonInit(); | 
| Andreas Gampe | 928f72b | 2014-09-09 19:53:48 -0700 | [diff] [blame] | 259 |   // This test may not work under valgrind. | 
| Evgenii Stepanov | 1e13374 | 2015-05-20 12:30:59 -0700 | [diff] [blame] | 260 |   if (RUNNING_ON_MEMORY_TOOL == 0) { | 
| Mathieu Chartier | 16d29f8 | 2015-11-10 10:32:52 -0800 | [diff] [blame] | 261 |     constexpr size_t size = 0x100000; | 
 | 262 |     // Try all addresses starting from 2GB to 4GB. | 
 | 263 |     size_t start_addr = 2 * GB; | 
| Andreas Gampe | 928f72b | 2014-09-09 19:53:48 -0700 | [diff] [blame] | 264 |     std::string error_msg; | 
| Mathieu Chartier | 16d29f8 | 2015-11-10 10:32:52 -0800 | [diff] [blame] | 265 |     std::unique_ptr<MemMap> map; | 
 | 266 |     for (; start_addr <= std::numeric_limits<uint32_t>::max() - size; start_addr += size) { | 
 | 267 |       map.reset(MemMap::MapAnonymous("MapAnonymousExactAddr32bitHighAddr", | 
 | 268 |                                      reinterpret_cast<uint8_t*>(start_addr), | 
 | 269 |                                      size, | 
 | 270 |                                      PROT_READ | PROT_WRITE, | 
 | 271 |                                      /*low_4gb*/true, | 
 | 272 |                                      false, | 
 | 273 |                                      &error_msg)); | 
 | 274 |       if (map != nullptr) { | 
 | 275 |         break; | 
 | 276 |       } | 
 | 277 |     } | 
| Andreas Gampe | 928f72b | 2014-09-09 19:53:48 -0700 | [diff] [blame] | 278 |     ASSERT_TRUE(map.get() != nullptr) << error_msg; | 
| Roland Levillain | 8d02644 | 2016-01-19 17:30:33 +0000 | [diff] [blame] | 279 |     ASSERT_GE(reinterpret_cast<uintptr_t>(map->End()), 2u * GB); | 
| Andreas Gampe | 928f72b | 2014-09-09 19:53:48 -0700 | [diff] [blame] | 280 |     ASSERT_TRUE(error_msg.empty()); | 
| Mathieu Chartier | 16d29f8 | 2015-11-10 10:32:52 -0800 | [diff] [blame] | 281 |     ASSERT_EQ(BaseBegin(map.get()), reinterpret_cast<void*>(start_addr)); | 
| Andreas Gampe | 928f72b | 2014-09-09 19:53:48 -0700 | [diff] [blame] | 282 |   } | 
| Qiming Shi | 84d49cc | 2014-04-24 15:38:41 +0800 | [diff] [blame] | 283 | } | 
 | 284 |  | 
 | 285 | TEST_F(MemMapTest, MapAnonymousOverflow) { | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 286 |   CommonInit(); | 
| Qiming Shi | 84d49cc | 2014-04-24 15:38:41 +0800 | [diff] [blame] | 287 |   std::string error_msg; | 
 | 288 |   uintptr_t ptr = 0; | 
 | 289 |   ptr -= kPageSize;  // Now it's close to the top. | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 290 |   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousOverflow", | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 291 |                                                    reinterpret_cast<uint8_t*>(ptr), | 
 | 292 |                                                    2 * kPageSize,  // brings it over the top. | 
 | 293 |                                                    PROT_READ | PROT_WRITE, | 
 | 294 |                                                    false, | 
 | 295 |                                                    false, | 
 | 296 |                                                    &error_msg)); | 
| Qiming Shi | 84d49cc | 2014-04-24 15:38:41 +0800 | [diff] [blame] | 297 |   ASSERT_EQ(nullptr, map.get()); | 
 | 298 |   ASSERT_FALSE(error_msg.empty()); | 
 | 299 | } | 
 | 300 |  | 
 | 301 | #ifdef __LP64__ | 
 | 302 | TEST_F(MemMapTest, MapAnonymousLow4GBExpectedTooHigh) { | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 303 |   CommonInit(); | 
| Qiming Shi | 84d49cc | 2014-04-24 15:38:41 +0800 | [diff] [blame] | 304 |   std::string error_msg; | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 305 |   std::unique_ptr<MemMap> map( | 
 | 306 |       MemMap::MapAnonymous("MapAnonymousLow4GBExpectedTooHigh", | 
 | 307 |                            reinterpret_cast<uint8_t*>(UINT64_C(0x100000000)), | 
 | 308 |                            kPageSize, | 
 | 309 |                            PROT_READ | PROT_WRITE, | 
 | 310 |                            true, | 
 | 311 |                            false, | 
 | 312 |                            &error_msg)); | 
| Qiming Shi | 84d49cc | 2014-04-24 15:38:41 +0800 | [diff] [blame] | 313 |   ASSERT_EQ(nullptr, map.get()); | 
 | 314 |   ASSERT_FALSE(error_msg.empty()); | 
 | 315 | } | 
 | 316 |  | 
 | 317 | TEST_F(MemMapTest, MapAnonymousLow4GBRangeTooHigh) { | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 318 |   CommonInit(); | 
| Qiming Shi | 84d49cc | 2014-04-24 15:38:41 +0800 | [diff] [blame] | 319 |   std::string error_msg; | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 320 |   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousLow4GBRangeTooHigh", | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 321 |                                                    reinterpret_cast<uint8_t*>(0xF0000000), | 
 | 322 |                                                    0x20000000, | 
 | 323 |                                                    PROT_READ | PROT_WRITE, | 
 | 324 |                                                    true, | 
 | 325 |                                                    false, | 
 | 326 |                                                    &error_msg)); | 
| Qiming Shi | 84d49cc | 2014-04-24 15:38:41 +0800 | [diff] [blame] | 327 |   ASSERT_EQ(nullptr, map.get()); | 
 | 328 |   ASSERT_FALSE(error_msg.empty()); | 
 | 329 | } | 
 | 330 | #endif | 
 | 331 |  | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 332 | TEST_F(MemMapTest, MapAnonymousReuse) { | 
 | 333 |   CommonInit(); | 
 | 334 |   std::string error_msg; | 
 | 335 |   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymousReserve", | 
 | 336 |                                                    nullptr, | 
 | 337 |                                                    0x20000, | 
 | 338 |                                                    PROT_READ | PROT_WRITE, | 
 | 339 |                                                    false, | 
 | 340 |                                                    false, | 
 | 341 |                                                    &error_msg)); | 
 | 342 |   ASSERT_NE(nullptr, map.get()); | 
 | 343 |   ASSERT_TRUE(error_msg.empty()); | 
 | 344 |   std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymousReused", | 
 | 345 |                                                     reinterpret_cast<uint8_t*>(map->BaseBegin()), | 
 | 346 |                                                     0x10000, | 
 | 347 |                                                     PROT_READ | PROT_WRITE, | 
 | 348 |                                                     false, | 
 | 349 |                                                     true, | 
 | 350 |                                                     &error_msg)); | 
 | 351 |   ASSERT_NE(nullptr, map2.get()); | 
 | 352 |   ASSERT_TRUE(error_msg.empty()); | 
 | 353 | } | 
 | 354 |  | 
| Hiroshi Yamauchi | 3eed93d | 2014-06-04 11:43:59 -0700 | [diff] [blame] | 355 | TEST_F(MemMapTest, CheckNoGaps) { | 
| Mathieu Chartier | 6e88ef6 | 2014-10-14 15:01:24 -0700 | [diff] [blame] | 356 |   CommonInit(); | 
| Hiroshi Yamauchi | 3eed93d | 2014-06-04 11:43:59 -0700 | [diff] [blame] | 357 |   std::string error_msg; | 
 | 358 |   constexpr size_t kNumPages = 3; | 
 | 359 |   // Map a 3-page mem map. | 
 | 360 |   std::unique_ptr<MemMap> map(MemMap::MapAnonymous("MapAnonymous0", | 
 | 361 |                                                    nullptr, | 
 | 362 |                                                    kPageSize * kNumPages, | 
 | 363 |                                                    PROT_READ | PROT_WRITE, | 
 | 364 |                                                    false, | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 365 |                                                    false, | 
| Hiroshi Yamauchi | 3eed93d | 2014-06-04 11:43:59 -0700 | [diff] [blame] | 366 |                                                    &error_msg)); | 
 | 367 |   ASSERT_TRUE(map.get() != nullptr) << error_msg; | 
 | 368 |   ASSERT_TRUE(error_msg.empty()); | 
 | 369 |   // Record the base address. | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 370 |   uint8_t* map_base = reinterpret_cast<uint8_t*>(map->BaseBegin()); | 
| Hiroshi Yamauchi | 3eed93d | 2014-06-04 11:43:59 -0700 | [diff] [blame] | 371 |   // Unmap it. | 
 | 372 |   map.reset(); | 
 | 373 |  | 
 | 374 |   // Map at the same address, but in page-sized separate mem maps, | 
 | 375 |   // assuming the space at the address is still available. | 
 | 376 |   std::unique_ptr<MemMap> map0(MemMap::MapAnonymous("MapAnonymous0", | 
 | 377 |                                                     map_base, | 
 | 378 |                                                     kPageSize, | 
 | 379 |                                                     PROT_READ | PROT_WRITE, | 
 | 380 |                                                     false, | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 381 |                                                     false, | 
| Hiroshi Yamauchi | 3eed93d | 2014-06-04 11:43:59 -0700 | [diff] [blame] | 382 |                                                     &error_msg)); | 
 | 383 |   ASSERT_TRUE(map0.get() != nullptr) << error_msg; | 
 | 384 |   ASSERT_TRUE(error_msg.empty()); | 
 | 385 |   std::unique_ptr<MemMap> map1(MemMap::MapAnonymous("MapAnonymous1", | 
 | 386 |                                                     map_base + kPageSize, | 
 | 387 |                                                     kPageSize, | 
 | 388 |                                                     PROT_READ | PROT_WRITE, | 
 | 389 |                                                     false, | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 390 |                                                     false, | 
| Hiroshi Yamauchi | 3eed93d | 2014-06-04 11:43:59 -0700 | [diff] [blame] | 391 |                                                     &error_msg)); | 
 | 392 |   ASSERT_TRUE(map1.get() != nullptr) << error_msg; | 
 | 393 |   ASSERT_TRUE(error_msg.empty()); | 
 | 394 |   std::unique_ptr<MemMap> map2(MemMap::MapAnonymous("MapAnonymous2", | 
 | 395 |                                                     map_base + kPageSize * 2, | 
 | 396 |                                                     kPageSize, | 
 | 397 |                                                     PROT_READ | PROT_WRITE, | 
 | 398 |                                                     false, | 
| Vladimir Marko | 5c42c29 | 2015-02-25 12:02:49 +0000 | [diff] [blame] | 399 |                                                     false, | 
| Hiroshi Yamauchi | 3eed93d | 2014-06-04 11:43:59 -0700 | [diff] [blame] | 400 |                                                     &error_msg)); | 
 | 401 |   ASSERT_TRUE(map2.get() != nullptr) << error_msg; | 
 | 402 |   ASSERT_TRUE(error_msg.empty()); | 
 | 403 |  | 
 | 404 |   // One-map cases. | 
 | 405 |   ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map0.get())); | 
 | 406 |   ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map1.get())); | 
 | 407 |   ASSERT_TRUE(MemMap::CheckNoGaps(map2.get(), map2.get())); | 
 | 408 |  | 
 | 409 |   // Two or three-map cases. | 
 | 410 |   ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map1.get())); | 
 | 411 |   ASSERT_TRUE(MemMap::CheckNoGaps(map1.get(), map2.get())); | 
 | 412 |   ASSERT_TRUE(MemMap::CheckNoGaps(map0.get(), map2.get())); | 
 | 413 |  | 
 | 414 |   // Unmap the middle one. | 
 | 415 |   map1.reset(); | 
 | 416 |  | 
 | 417 |   // Should return false now that there's a gap in the middle. | 
 | 418 |   ASSERT_FALSE(MemMap::CheckNoGaps(map0.get(), map2.get())); | 
 | 419 | } | 
 | 420 |  | 
| Brian Carlstrom | 9004cb6 | 2013-07-26 15:48:31 -0700 | [diff] [blame] | 421 | }  // namespace art |