Home | History | Annotate | Download | only in runtime
      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