xref: /aosp_15_r20/art/libartbase/base/mem_map_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "mem_map.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <memory>
20*795d594fSAndroid Build Coastguard Worker #include <random>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "bit_utils.h"
23*795d594fSAndroid Build Coastguard Worker #include "common_art_test.h"
24*795d594fSAndroid Build Coastguard Worker #include "logging.h"
25*795d594fSAndroid Build Coastguard Worker #include "memory_tool.h"
26*795d594fSAndroid Build Coastguard Worker #include "mman.h"
27*795d594fSAndroid Build Coastguard Worker #include "unix_file/fd_file.h"
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker namespace art {
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker class MemMapTest : public CommonArtTest {
32*795d594fSAndroid Build Coastguard Worker  public:
IsAddressMapped(void * addr)33*795d594fSAndroid Build Coastguard Worker   static bool IsAddressMapped(void* addr) {
34*795d594fSAndroid Build Coastguard Worker     bool res = msync(addr, 1, MS_SYNC) == 0;
35*795d594fSAndroid Build Coastguard Worker     if (!res && errno != ENOMEM) {
36*795d594fSAndroid Build Coastguard Worker       PLOG(FATAL) << "Unexpected error occurred on msync";
37*795d594fSAndroid Build Coastguard Worker     }
38*795d594fSAndroid Build Coastguard Worker     return res;
39*795d594fSAndroid Build Coastguard Worker   }
40*795d594fSAndroid Build Coastguard Worker 
RandomData(size_t size)41*795d594fSAndroid Build Coastguard Worker   static std::vector<uint8_t> RandomData(size_t size) {
42*795d594fSAndroid Build Coastguard Worker     std::random_device rd;
43*795d594fSAndroid Build Coastguard Worker     std::uniform_int_distribution<uint8_t> dist;
44*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> res;
45*795d594fSAndroid Build Coastguard Worker     res.resize(size);
46*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < size; i++) {
47*795d594fSAndroid Build Coastguard Worker       res[i] = dist(rd);
48*795d594fSAndroid Build Coastguard Worker     }
49*795d594fSAndroid Build Coastguard Worker     return res;
50*795d594fSAndroid Build Coastguard Worker   }
51*795d594fSAndroid Build Coastguard Worker 
GetValidMapAddress(size_t size,bool low_4gb)52*795d594fSAndroid Build Coastguard Worker   static uint8_t* GetValidMapAddress(size_t size, bool low_4gb) {
53*795d594fSAndroid Build Coastguard Worker     // Find a valid map address and unmap it before returning.
54*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
55*795d594fSAndroid Build Coastguard Worker     MemMap map = MemMap::MapAnonymous("temp",
56*795d594fSAndroid Build Coastguard Worker                                       size,
57*795d594fSAndroid Build Coastguard Worker                                       PROT_READ,
58*795d594fSAndroid Build Coastguard Worker                                       low_4gb,
59*795d594fSAndroid Build Coastguard Worker                                       &error_msg);
60*795d594fSAndroid Build Coastguard Worker     CHECK(map.IsValid());
61*795d594fSAndroid Build Coastguard Worker     return map.Begin();
62*795d594fSAndroid Build Coastguard Worker   }
63*795d594fSAndroid Build Coastguard Worker 
RemapAtEndTest(bool low_4gb)64*795d594fSAndroid Build Coastguard Worker   static void RemapAtEndTest(bool low_4gb) {
65*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
66*795d594fSAndroid Build Coastguard Worker     // Cast the page size to size_t.
67*795d594fSAndroid Build Coastguard Worker     const size_t page_size = MemMap::GetPageSize();
68*795d594fSAndroid Build Coastguard Worker     // Map a two-page memory region.
69*795d594fSAndroid Build Coastguard Worker     MemMap m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0",
70*795d594fSAndroid Build Coastguard Worker                                      2 * page_size,
71*795d594fSAndroid Build Coastguard Worker                                      PROT_READ | PROT_WRITE,
72*795d594fSAndroid Build Coastguard Worker                                      low_4gb,
73*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
74*795d594fSAndroid Build Coastguard Worker     // Check its state and write to it.
75*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(m0.IsValid());
76*795d594fSAndroid Build Coastguard Worker     uint8_t* base0 = m0.Begin();
77*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(base0 != nullptr) << error_msg;
78*795d594fSAndroid Build Coastguard Worker     size_t size0 = m0.Size();
79*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.Size(), 2 * page_size);
80*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.BaseBegin(), base0);
81*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.BaseSize(), size0);
82*795d594fSAndroid Build Coastguard Worker     memset(base0, 42, 2 * page_size);
83*795d594fSAndroid Build Coastguard Worker     // Remap the latter half into a second MemMap.
84*795d594fSAndroid Build Coastguard Worker     MemMap m1 = m0.RemapAtEnd(base0 + page_size,
85*795d594fSAndroid Build Coastguard Worker                               "MemMapTest_RemapAtEndTest_map1",
86*795d594fSAndroid Build Coastguard Worker                               PROT_READ | PROT_WRITE,
87*795d594fSAndroid Build Coastguard Worker                               &error_msg);
88*795d594fSAndroid Build Coastguard Worker     // Check the states of the two maps.
89*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.Begin(), base0) << error_msg;
90*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.Size(), page_size);
91*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.BaseBegin(), base0);
92*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.BaseSize(), page_size);
93*795d594fSAndroid Build Coastguard Worker     uint8_t* base1 = m1.Begin();
94*795d594fSAndroid Build Coastguard Worker     size_t size1 = m1.Size();
95*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(base1, base0 + page_size);
96*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(size1, page_size);
97*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m1.BaseBegin(), base1);
98*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m1.BaseSize(), size1);
99*795d594fSAndroid Build Coastguard Worker     // Write to the second region.
100*795d594fSAndroid Build Coastguard Worker     memset(base1, 43, page_size);
101*795d594fSAndroid Build Coastguard Worker     // Check the contents of the two regions.
102*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < page_size; ++i) {
103*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(base0[i], 42);
104*795d594fSAndroid Build Coastguard Worker     }
105*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < page_size; ++i) {
106*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(base1[i], 43);
107*795d594fSAndroid Build Coastguard Worker     }
108*795d594fSAndroid Build Coastguard Worker     // Unmap the first region.
109*795d594fSAndroid Build Coastguard Worker     m0.Reset();
110*795d594fSAndroid Build Coastguard Worker     // Make sure the second region is still accessible after the first
111*795d594fSAndroid Build Coastguard Worker     // region is unmapped.
112*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < page_size; ++i) {
113*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(base1[i], 43);
114*795d594fSAndroid Build Coastguard Worker     }
115*795d594fSAndroid Build Coastguard Worker     MemMap m2 = m1.RemapAtEnd(m1.Begin(),
116*795d594fSAndroid Build Coastguard Worker                               "MemMapTest_RemapAtEndTest_map1",
117*795d594fSAndroid Build Coastguard Worker                               PROT_READ | PROT_WRITE,
118*795d594fSAndroid Build Coastguard Worker                               &error_msg);
119*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(m2.IsValid()) << error_msg;
120*795d594fSAndroid Build Coastguard Worker     ASSERT_FALSE(m1.IsValid());
121*795d594fSAndroid Build Coastguard Worker   }
122*795d594fSAndroid Build Coastguard Worker 
CommonInit()123*795d594fSAndroid Build Coastguard Worker   void CommonInit() {
124*795d594fSAndroid Build Coastguard Worker     MemMap::Init();
125*795d594fSAndroid Build Coastguard Worker   }
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker #if defined(__LP64__) && !defined(__x86_64__)
GetLinearScanPos()128*795d594fSAndroid Build Coastguard Worker   static uintptr_t GetLinearScanPos() {
129*795d594fSAndroid Build Coastguard Worker     return MemMap::next_mem_pos_;
130*795d594fSAndroid Build Coastguard Worker   }
131*795d594fSAndroid Build Coastguard Worker #endif
132*795d594fSAndroid Build Coastguard Worker };
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker #if defined(__LP64__) && !defined(__x86_64__)
135*795d594fSAndroid Build Coastguard Worker 
136*795d594fSAndroid Build Coastguard Worker #ifdef __BIONIC__
137*795d594fSAndroid Build Coastguard Worker extern uintptr_t CreateStartPos(uint64_t input, uint64_t page_size);
138*795d594fSAndroid Build Coastguard Worker #endif
139*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,PageSize)140*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, PageSize) {
141*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
142*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(page_size, GetPageSizeSlow());
143*795d594fSAndroid Build Coastguard Worker }
144*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,Start)145*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, Start) {
146*795d594fSAndroid Build Coastguard Worker   CommonInit();
147*795d594fSAndroid Build Coastguard Worker   uintptr_t start = GetLinearScanPos();
148*795d594fSAndroid Build Coastguard Worker   EXPECT_LE(64 * KB, start);
149*795d594fSAndroid Build Coastguard Worker   EXPECT_LT(start, static_cast<uintptr_t>(ART_BASE_ADDRESS));
150*795d594fSAndroid Build Coastguard Worker #ifdef __BIONIC__
151*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
152*795d594fSAndroid Build Coastguard Worker   // Test a couple of values. Make sure they are different.
153*795d594fSAndroid Build Coastguard Worker   uintptr_t last = 0;
154*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < 100; ++i) {
155*795d594fSAndroid Build Coastguard Worker     uintptr_t random_start = CreateStartPos(i * page_size, page_size);
156*795d594fSAndroid Build Coastguard Worker     EXPECT_NE(last, random_start);
157*795d594fSAndroid Build Coastguard Worker     last = random_start;
158*795d594fSAndroid Build Coastguard Worker   }
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker   // Even on max, should be below ART_BASE_ADDRESS.
161*795d594fSAndroid Build Coastguard Worker   EXPECT_LT(CreateStartPos(~0, page_size), static_cast<uintptr_t>(ART_BASE_ADDRESS));
162*795d594fSAndroid Build Coastguard Worker #endif
163*795d594fSAndroid Build Coastguard Worker   // End of test.
164*795d594fSAndroid Build Coastguard Worker }
165*795d594fSAndroid Build Coastguard Worker #endif
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker // We need mremap to be able to test ReplaceMapping at all
168*795d594fSAndroid Build Coastguard Worker #if HAVE_MREMAP_SYSCALL
TEST_F(MemMapTest,ReplaceMapping_SameSize)169*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, ReplaceMapping_SameSize) {
170*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
171*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
172*795d594fSAndroid Build Coastguard Worker   MemMap dest = MemMap::MapAnonymous("MapAnonymousEmpty-atomic-replace-dest",
173*795d594fSAndroid Build Coastguard Worker                                      page_size,
174*795d594fSAndroid Build Coastguard Worker                                      PROT_READ,
175*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
176*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
177*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(dest.IsValid());
178*795d594fSAndroid Build Coastguard Worker   MemMap source = MemMap::MapAnonymous("MapAnonymous-atomic-replace-source",
179*795d594fSAndroid Build Coastguard Worker                                        page_size,
180*795d594fSAndroid Build Coastguard Worker                                        PROT_WRITE | PROT_READ,
181*795d594fSAndroid Build Coastguard Worker                                        /*low_4gb=*/ false,
182*795d594fSAndroid Build Coastguard Worker                                        &error_msg);
183*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(source.IsValid());
184*795d594fSAndroid Build Coastguard Worker   void* source_addr = source.Begin();
185*795d594fSAndroid Build Coastguard Worker   void* dest_addr = dest.Begin();
186*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(source_addr));
187*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr));
188*795d594fSAndroid Build Coastguard Worker 
189*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> data = RandomData(page_size);
190*795d594fSAndroid Build Coastguard Worker   memcpy(source.Begin(), data.data(), data.size());
191*795d594fSAndroid Build Coastguard Worker 
192*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(dest.ReplaceWith(&source, &error_msg)) << error_msg;
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(IsAddressMapped(source_addr));
195*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr));
196*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(source.IsValid());
197*795d594fSAndroid Build Coastguard Worker 
198*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(dest.Size(), static_cast<size_t>(page_size));
199*795d594fSAndroid Build Coastguard Worker 
200*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(memcmp(dest.Begin(), data.data(), dest.Size()), 0);
201*795d594fSAndroid Build Coastguard Worker }
202*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,ReplaceMapping_MakeLarger)203*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, ReplaceMapping_MakeLarger) {
204*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
205*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
206*795d594fSAndroid Build Coastguard Worker   MemMap dest = MemMap::MapAnonymous("MapAnonymousEmpty-atomic-replace-dest",
207*795d594fSAndroid Build Coastguard Worker                                      5 * page_size,  // Need to make it larger
208*795d594fSAndroid Build Coastguard Worker                                                      // initially so we know
209*795d594fSAndroid Build Coastguard Worker                                                      // there won't be mappings
210*795d594fSAndroid Build Coastguard Worker                                                      // in the way when we move
211*795d594fSAndroid Build Coastguard Worker                                                      // source.
212*795d594fSAndroid Build Coastguard Worker                                      PROT_READ,
213*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
214*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
215*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(dest.IsValid());
216*795d594fSAndroid Build Coastguard Worker   MemMap source = MemMap::MapAnonymous("MapAnonymous-atomic-replace-source",
217*795d594fSAndroid Build Coastguard Worker                                        3 * page_size,
218*795d594fSAndroid Build Coastguard Worker                                        PROT_WRITE | PROT_READ,
219*795d594fSAndroid Build Coastguard Worker                                        /*low_4gb=*/ false,
220*795d594fSAndroid Build Coastguard Worker                                        &error_msg);
221*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(source.IsValid());
222*795d594fSAndroid Build Coastguard Worker   uint8_t* source_addr = source.Begin();
223*795d594fSAndroid Build Coastguard Worker   uint8_t* dest_addr = dest.Begin();
224*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(source_addr));
225*795d594fSAndroid Build Coastguard Worker 
226*795d594fSAndroid Build Coastguard Worker   // Fill the source with random data.
227*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> data = RandomData(3 * page_size);
228*795d594fSAndroid Build Coastguard Worker   memcpy(source.Begin(), data.data(), data.size());
229*795d594fSAndroid Build Coastguard Worker 
230*795d594fSAndroid Build Coastguard Worker   // Make the dest smaller so that we know we'll have space.
231*795d594fSAndroid Build Coastguard Worker   dest.SetSize(page_size);
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr));
234*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(IsAddressMapped(dest_addr + 2 * page_size));
235*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(dest.Size(), static_cast<size_t>(page_size));
236*795d594fSAndroid Build Coastguard Worker 
237*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(dest.ReplaceWith(&source, &error_msg)) << error_msg;
238*795d594fSAndroid Build Coastguard Worker 
239*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(IsAddressMapped(source_addr));
240*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(dest.Size(), static_cast<size_t>(3 * page_size));
241*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr));
242*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr + 2 * page_size));
243*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(source.IsValid());
244*795d594fSAndroid Build Coastguard Worker 
245*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(memcmp(dest.Begin(), data.data(), dest.Size()), 0);
246*795d594fSAndroid Build Coastguard Worker }
247*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,ReplaceMapping_MakeSmaller)248*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, ReplaceMapping_MakeSmaller) {
249*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
250*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
251*795d594fSAndroid Build Coastguard Worker   MemMap dest = MemMap::MapAnonymous("MapAnonymousEmpty-atomic-replace-dest",
252*795d594fSAndroid Build Coastguard Worker                                      3 * page_size,
253*795d594fSAndroid Build Coastguard Worker                                      PROT_READ,
254*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
255*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
256*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(dest.IsValid());
257*795d594fSAndroid Build Coastguard Worker   MemMap source = MemMap::MapAnonymous("MapAnonymous-atomic-replace-source",
258*795d594fSAndroid Build Coastguard Worker                                        page_size,
259*795d594fSAndroid Build Coastguard Worker                                        PROT_WRITE | PROT_READ,
260*795d594fSAndroid Build Coastguard Worker                                        /*low_4gb=*/ false,
261*795d594fSAndroid Build Coastguard Worker                                        &error_msg);
262*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(source.IsValid());
263*795d594fSAndroid Build Coastguard Worker   uint8_t* source_addr = source.Begin();
264*795d594fSAndroid Build Coastguard Worker   uint8_t* dest_addr = dest.Begin();
265*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(source_addr));
266*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr));
267*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr + 2 * page_size));
268*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(dest.Size(), static_cast<size_t>(3 * page_size));
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> data = RandomData(page_size);
271*795d594fSAndroid Build Coastguard Worker   memcpy(source.Begin(), data.data(), page_size);
272*795d594fSAndroid Build Coastguard Worker 
273*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(dest.ReplaceWith(&source, &error_msg)) << error_msg;
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(IsAddressMapped(source_addr));
276*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(dest.Size(), static_cast<size_t>(page_size));
277*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr));
278*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(IsAddressMapped(dest_addr + 2 * page_size));
279*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(source.IsValid());
280*795d594fSAndroid Build Coastguard Worker 
281*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(memcmp(dest.Begin(), data.data(), dest.Size()), 0);
282*795d594fSAndroid Build Coastguard Worker }
283*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,ReplaceMapping_FailureOverlap)284*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, ReplaceMapping_FailureOverlap) {
285*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
286*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
287*795d594fSAndroid Build Coastguard Worker   MemMap dest =
288*795d594fSAndroid Build Coastguard Worker       MemMap::MapAnonymous(
289*795d594fSAndroid Build Coastguard Worker           "MapAnonymousEmpty-atomic-replace-dest",
290*795d594fSAndroid Build Coastguard Worker           3 * page_size,  // Need to make it larger initially so we know there won't be mappings in
291*795d594fSAndroid Build Coastguard Worker                           // the way when we move source.
292*795d594fSAndroid Build Coastguard Worker           PROT_READ | PROT_WRITE,
293*795d594fSAndroid Build Coastguard Worker           /*low_4gb=*/ false,
294*795d594fSAndroid Build Coastguard Worker           &error_msg);
295*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(dest.IsValid());
296*795d594fSAndroid Build Coastguard Worker   // Resize down to 1 page so we can remap the rest.
297*795d594fSAndroid Build Coastguard Worker   dest.SetSize(page_size);
298*795d594fSAndroid Build Coastguard Worker   // Create source from the last 2 pages
299*795d594fSAndroid Build Coastguard Worker   MemMap source = MemMap::MapAnonymous("MapAnonymous-atomic-replace-source",
300*795d594fSAndroid Build Coastguard Worker                                        dest.Begin() + page_size,
301*795d594fSAndroid Build Coastguard Worker                                        2 * page_size,
302*795d594fSAndroid Build Coastguard Worker                                        PROT_WRITE | PROT_READ,
303*795d594fSAndroid Build Coastguard Worker                                        /*low_4gb=*/ false,
304*795d594fSAndroid Build Coastguard Worker                                        /*reuse=*/ false,
305*795d594fSAndroid Build Coastguard Worker                                        /*reservation=*/ nullptr,
306*795d594fSAndroid Build Coastguard Worker                                        &error_msg);
307*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(source.IsValid());
308*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(dest.Begin() + page_size, source.Begin());
309*795d594fSAndroid Build Coastguard Worker   uint8_t* source_addr = source.Begin();
310*795d594fSAndroid Build Coastguard Worker   uint8_t* dest_addr = dest.Begin();
311*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(source_addr));
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker   // Fill the source and dest with random data.
314*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> data = RandomData(2 * page_size);
315*795d594fSAndroid Build Coastguard Worker   memcpy(source.Begin(), data.data(), data.size());
316*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> dest_data = RandomData(page_size);
317*795d594fSAndroid Build Coastguard Worker   memcpy(dest.Begin(), dest_data.data(), dest_data.size());
318*795d594fSAndroid Build Coastguard Worker 
319*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr));
320*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(dest.Size(), static_cast<size_t>(page_size));
321*795d594fSAndroid Build Coastguard Worker 
322*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(dest.ReplaceWith(&source, &error_msg)) << error_msg;
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(source_addr));
325*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(IsAddressMapped(dest_addr));
326*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(source.Size(), data.size());
327*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(dest.Size(), dest_data.size());
328*795d594fSAndroid Build Coastguard Worker 
329*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(memcmp(source.Begin(), data.data(), data.size()), 0);
330*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(memcmp(dest.Begin(), dest_data.data(), dest_data.size()), 0);
331*795d594fSAndroid Build Coastguard Worker }
332*795d594fSAndroid Build Coastguard Worker #endif  // HAVE_MREMAP_SYSCALL
333*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,MapAnonymousEmpty)334*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousEmpty) {
335*795d594fSAndroid Build Coastguard Worker   CommonInit();
336*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
337*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
338*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapAnonymous("MapAnonymousEmpty",
339*795d594fSAndroid Build Coastguard Worker                                     /*byte_count=*/ 0,
340*795d594fSAndroid Build Coastguard Worker                                     PROT_READ,
341*795d594fSAndroid Build Coastguard Worker                                     /*low_4gb=*/ false,
342*795d594fSAndroid Build Coastguard Worker                                     &error_msg);
343*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(map.IsValid()) << error_msg;
344*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(error_msg.empty());
345*795d594fSAndroid Build Coastguard Worker 
346*795d594fSAndroid Build Coastguard Worker   error_msg.clear();
347*795d594fSAndroid Build Coastguard Worker   map = MemMap::MapAnonymous("MapAnonymousNonEmpty",
348*795d594fSAndroid Build Coastguard Worker                              page_size,
349*795d594fSAndroid Build Coastguard Worker                              PROT_READ | PROT_WRITE,
350*795d594fSAndroid Build Coastguard Worker                              /*low_4gb=*/ false,
351*795d594fSAndroid Build Coastguard Worker                              &error_msg);
352*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map.IsValid()) << error_msg;
353*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
354*795d594fSAndroid Build Coastguard Worker }
355*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,MapAnonymousFailNullError)356*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousFailNullError) {
357*795d594fSAndroid Build Coastguard Worker   CommonInit();
358*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
359*795d594fSAndroid Build Coastguard Worker   // Test that we don't crash with a null error_str when mapping at an invalid location.
360*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapAnonymous("MapAnonymousInvalid",
361*795d594fSAndroid Build Coastguard Worker                                     reinterpret_cast<uint8_t*>(static_cast<size_t>(page_size)),
362*795d594fSAndroid Build Coastguard Worker                                     0x20000,
363*795d594fSAndroid Build Coastguard Worker                                     PROT_READ | PROT_WRITE,
364*795d594fSAndroid Build Coastguard Worker                                     /*low_4gb=*/ false,
365*795d594fSAndroid Build Coastguard Worker                                     /*reuse=*/ false,
366*795d594fSAndroid Build Coastguard Worker                                     /*reservation=*/ nullptr,
367*795d594fSAndroid Build Coastguard Worker                                     nullptr);
368*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(map.IsValid());
369*795d594fSAndroid Build Coastguard Worker }
370*795d594fSAndroid Build Coastguard Worker 
371*795d594fSAndroid Build Coastguard Worker #ifdef __LP64__
TEST_F(MemMapTest,MapAnonymousEmpty32bit)372*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousEmpty32bit) {
373*795d594fSAndroid Build Coastguard Worker   CommonInit();
374*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
375*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
376*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapAnonymous("MapAnonymousEmpty",
377*795d594fSAndroid Build Coastguard Worker                                     /*byte_count=*/ 0,
378*795d594fSAndroid Build Coastguard Worker                                     PROT_READ,
379*795d594fSAndroid Build Coastguard Worker                                     /*low_4gb=*/ true,
380*795d594fSAndroid Build Coastguard Worker                                     &error_msg);
381*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(map.IsValid()) << error_msg;
382*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(error_msg.empty());
383*795d594fSAndroid Build Coastguard Worker 
384*795d594fSAndroid Build Coastguard Worker   error_msg.clear();
385*795d594fSAndroid Build Coastguard Worker   map = MemMap::MapAnonymous("MapAnonymousNonEmpty",
386*795d594fSAndroid Build Coastguard Worker                              page_size,
387*795d594fSAndroid Build Coastguard Worker                              PROT_READ | PROT_WRITE,
388*795d594fSAndroid Build Coastguard Worker                              /*low_4gb=*/ true,
389*795d594fSAndroid Build Coastguard Worker                              &error_msg);
390*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map.IsValid()) << error_msg;
391*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
392*795d594fSAndroid Build Coastguard Worker   ASSERT_LT(reinterpret_cast<uintptr_t>(map.BaseBegin()), 1ULL << 32);
393*795d594fSAndroid Build Coastguard Worker }
TEST_F(MemMapTest,MapFile32Bit)394*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapFile32Bit) {
395*795d594fSAndroid Build Coastguard Worker   CommonInit();
396*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
397*795d594fSAndroid Build Coastguard Worker   ScratchFile scratch_file;
398*795d594fSAndroid Build Coastguard Worker   const size_t map_size = MemMap::GetPageSize();
399*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<uint8_t[]> data(new uint8_t[map_size]());
400*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(scratch_file.GetFile()->WriteFully(&data[0], map_size));
401*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapFile(/*byte_count=*/map_size,
402*795d594fSAndroid Build Coastguard Worker                                PROT_READ,
403*795d594fSAndroid Build Coastguard Worker                                MAP_PRIVATE,
404*795d594fSAndroid Build Coastguard Worker                                scratch_file.GetFd(),
405*795d594fSAndroid Build Coastguard Worker                                /*start=*/0,
406*795d594fSAndroid Build Coastguard Worker                                /*low_4gb=*/true,
407*795d594fSAndroid Build Coastguard Worker                                scratch_file.GetFilename().c_str(),
408*795d594fSAndroid Build Coastguard Worker                                &error_msg);
409*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map.IsValid()) << error_msg;
410*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
411*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map.Size(), map_size);
412*795d594fSAndroid Build Coastguard Worker   ASSERT_LT(reinterpret_cast<uintptr_t>(map.BaseBegin()), 1ULL << 32);
413*795d594fSAndroid Build Coastguard Worker }
414*795d594fSAndroid Build Coastguard Worker #endif
415*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,MapAnonymousExactAddr)416*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousExactAddr) {
417*795d594fSAndroid Build Coastguard Worker   // TODO: The semantics of the MemMap::MapAnonymous() with a given address but without
418*795d594fSAndroid Build Coastguard Worker   // `reuse == true` or `reservation != nullptr` is weird. We should either drop support
419*795d594fSAndroid Build Coastguard Worker   // for it, or take it only as a hint and allow the result to be mapped elsewhere.
420*795d594fSAndroid Build Coastguard Worker   // Currently we're seeing failures with ASAN. b/118408378
421*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_MEMORY_TOOL();
422*795d594fSAndroid Build Coastguard Worker 
423*795d594fSAndroid Build Coastguard Worker   CommonInit();
424*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
425*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
426*795d594fSAndroid Build Coastguard Worker   // Find a valid address.
427*795d594fSAndroid Build Coastguard Worker   uint8_t* valid_address = GetValidMapAddress(page_size, /*low_4gb=*/false);
428*795d594fSAndroid Build Coastguard Worker   // Map at an address that should work, which should succeed.
429*795d594fSAndroid Build Coastguard Worker   MemMap map0 = MemMap::MapAnonymous("MapAnonymous0",
430*795d594fSAndroid Build Coastguard Worker                                      valid_address,
431*795d594fSAndroid Build Coastguard Worker                                      page_size,
432*795d594fSAndroid Build Coastguard Worker                                      PROT_READ | PROT_WRITE,
433*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
434*795d594fSAndroid Build Coastguard Worker                                      /*reuse=*/ false,
435*795d594fSAndroid Build Coastguard Worker                                      /*reservation=*/ nullptr,
436*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
437*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map0.IsValid()) << error_msg;
438*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
439*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map0.BaseBegin() == valid_address);
440*795d594fSAndroid Build Coastguard Worker   // Map at an unspecified address, which should succeed.
441*795d594fSAndroid Build Coastguard Worker   MemMap map1 = MemMap::MapAnonymous("MapAnonymous1",
442*795d594fSAndroid Build Coastguard Worker                                      page_size,
443*795d594fSAndroid Build Coastguard Worker                                      PROT_READ | PROT_WRITE,
444*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
445*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
446*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map1.IsValid()) << error_msg;
447*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
448*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map1.BaseBegin() != nullptr);
449*795d594fSAndroid Build Coastguard Worker   // Attempt to map at the same address, which should fail.
450*795d594fSAndroid Build Coastguard Worker   MemMap map2 = MemMap::MapAnonymous("MapAnonymous2",
451*795d594fSAndroid Build Coastguard Worker                                      reinterpret_cast<uint8_t*>(map1.BaseBegin()),
452*795d594fSAndroid Build Coastguard Worker                                      page_size,
453*795d594fSAndroid Build Coastguard Worker                                      PROT_READ | PROT_WRITE,
454*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
455*795d594fSAndroid Build Coastguard Worker                                      /*reuse=*/ false,
456*795d594fSAndroid Build Coastguard Worker                                      /*reservation=*/ nullptr,
457*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
458*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(map2.IsValid()) << error_msg;
459*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(!error_msg.empty());
460*795d594fSAndroid Build Coastguard Worker }
461*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,RemapAtEnd)462*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, RemapAtEnd) {
463*795d594fSAndroid Build Coastguard Worker   RemapAtEndTest(false);
464*795d594fSAndroid Build Coastguard Worker }
465*795d594fSAndroid Build Coastguard Worker 
466*795d594fSAndroid Build Coastguard Worker #ifdef __LP64__
TEST_F(MemMapTest,RemapAtEnd32bit)467*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, RemapAtEnd32bit) {
468*795d594fSAndroid Build Coastguard Worker   RemapAtEndTest(true);
469*795d594fSAndroid Build Coastguard Worker }
470*795d594fSAndroid Build Coastguard Worker #endif
471*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,RemapFileViewAtEnd)472*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, RemapFileViewAtEnd) {
473*795d594fSAndroid Build Coastguard Worker   CommonInit();
474*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
475*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
476*795d594fSAndroid Build Coastguard Worker   ScratchFile scratch_file;
477*795d594fSAndroid Build Coastguard Worker 
478*795d594fSAndroid Build Coastguard Worker   // Create a scratch file 3 pages large.
479*795d594fSAndroid Build Coastguard Worker   const size_t map_size = 3 * page_size;
480*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<uint8_t[]> data(new uint8_t[map_size]());
481*795d594fSAndroid Build Coastguard Worker   memset(data.get(), 1, page_size);
482*795d594fSAndroid Build Coastguard Worker   memset(&data[0], 0x55, page_size);
483*795d594fSAndroid Build Coastguard Worker   memset(&data[page_size], 0x5a, page_size);
484*795d594fSAndroid Build Coastguard Worker   memset(&data[2 * page_size], 0xaa, page_size);
485*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(scratch_file.GetFile()->WriteFully(&data[0], map_size));
486*795d594fSAndroid Build Coastguard Worker 
487*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapFile(/*byte_count=*/map_size,
488*795d594fSAndroid Build Coastguard Worker                                PROT_READ,
489*795d594fSAndroid Build Coastguard Worker                                MAP_PRIVATE,
490*795d594fSAndroid Build Coastguard Worker                                scratch_file.GetFd(),
491*795d594fSAndroid Build Coastguard Worker                                /*start=*/0,
492*795d594fSAndroid Build Coastguard Worker                                /*low_4gb=*/true,
493*795d594fSAndroid Build Coastguard Worker                                scratch_file.GetFilename().c_str(),
494*795d594fSAndroid Build Coastguard Worker                                &error_msg);
495*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map.IsValid()) << error_msg;
496*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
497*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map.Size(), map_size);
498*795d594fSAndroid Build Coastguard Worker   ASSERT_LT(reinterpret_cast<uintptr_t>(map.BaseBegin()), 1ULL << 32);
499*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(data[0], *map.Begin());
500*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(data[page_size], *(map.Begin() + page_size));
501*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(data[2 * page_size], *(map.Begin() + 2 * page_size));
502*795d594fSAndroid Build Coastguard Worker 
503*795d594fSAndroid Build Coastguard Worker   for (size_t offset = 2 * page_size; offset > 0; offset -= page_size) {
504*795d594fSAndroid Build Coastguard Worker     MemMap tail = map.RemapAtEnd(map.Begin() + offset,
505*795d594fSAndroid Build Coastguard Worker                                  "bad_offset_map",
506*795d594fSAndroid Build Coastguard Worker                                  PROT_READ,
507*795d594fSAndroid Build Coastguard Worker                                  MAP_PRIVATE | MAP_FIXED,
508*795d594fSAndroid Build Coastguard Worker                                  scratch_file.GetFd(),
509*795d594fSAndroid Build Coastguard Worker                                  offset,
510*795d594fSAndroid Build Coastguard Worker                                  &error_msg);
511*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(tail.IsValid()) << error_msg;
512*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(error_msg.empty());
513*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(offset, map.Size());
514*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(static_cast<size_t>(page_size), tail.Size());
515*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(tail.Begin(), map.Begin() + map.Size());
516*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(data[offset], *tail.Begin());
517*795d594fSAndroid Build Coastguard Worker   }
518*795d594fSAndroid Build Coastguard Worker }
519*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,MapAnonymousExactAddr32bitHighAddr)520*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) {
521*795d594fSAndroid Build Coastguard Worker   // This test does not work under AddressSanitizer.
522*795d594fSAndroid Build Coastguard Worker   // Historical note: This test did not work under Valgrind either.
523*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_MEMORY_TOOL();
524*795d594fSAndroid Build Coastguard Worker 
525*795d594fSAndroid Build Coastguard Worker   CommonInit();
526*795d594fSAndroid Build Coastguard Worker   constexpr size_t size = 0x100000;
527*795d594fSAndroid Build Coastguard Worker   // Try all addresses starting from 2GB to 4GB.
528*795d594fSAndroid Build Coastguard Worker   size_t start_addr = 2 * GB;
529*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
530*795d594fSAndroid Build Coastguard Worker   MemMap map;
531*795d594fSAndroid Build Coastguard Worker   for (; start_addr <= std::numeric_limits<uint32_t>::max() - size; start_addr += size) {
532*795d594fSAndroid Build Coastguard Worker     map = MemMap::MapAnonymous("MapAnonymousExactAddr32bitHighAddr",
533*795d594fSAndroid Build Coastguard Worker                                reinterpret_cast<uint8_t*>(start_addr),
534*795d594fSAndroid Build Coastguard Worker                                size,
535*795d594fSAndroid Build Coastguard Worker                                PROT_READ | PROT_WRITE,
536*795d594fSAndroid Build Coastguard Worker                                /*low_4gb=*/ true,
537*795d594fSAndroid Build Coastguard Worker                                /*reuse=*/ false,
538*795d594fSAndroid Build Coastguard Worker                                /*reservation=*/ nullptr,
539*795d594fSAndroid Build Coastguard Worker                                &error_msg);
540*795d594fSAndroid Build Coastguard Worker     if (map.IsValid()) {
541*795d594fSAndroid Build Coastguard Worker       break;
542*795d594fSAndroid Build Coastguard Worker     }
543*795d594fSAndroid Build Coastguard Worker   }
544*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map.IsValid()) << error_msg;
545*795d594fSAndroid Build Coastguard Worker   ASSERT_GE(reinterpret_cast<uintptr_t>(map.End()), 2u * GB);
546*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
547*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map.BaseBegin(), reinterpret_cast<void*>(start_addr));
548*795d594fSAndroid Build Coastguard Worker }
549*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,MapAnonymousOverflow)550*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousOverflow) {
551*795d594fSAndroid Build Coastguard Worker   CommonInit();
552*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
553*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
554*795d594fSAndroid Build Coastguard Worker   uintptr_t ptr = 0;
555*795d594fSAndroid Build Coastguard Worker   ptr -= page_size;  // Now it's close to the top.
556*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapAnonymous("MapAnonymousOverflow",
557*795d594fSAndroid Build Coastguard Worker                                     reinterpret_cast<uint8_t*>(ptr),
558*795d594fSAndroid Build Coastguard Worker                                     2 * page_size,  // brings it over the top.
559*795d594fSAndroid Build Coastguard Worker                                     PROT_READ | PROT_WRITE,
560*795d594fSAndroid Build Coastguard Worker                                     /*low_4gb=*/ false,
561*795d594fSAndroid Build Coastguard Worker                                     /*reuse=*/ false,
562*795d594fSAndroid Build Coastguard Worker                                     /*reservation=*/ nullptr,
563*795d594fSAndroid Build Coastguard Worker                                     &error_msg);
564*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(map.IsValid());
565*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(error_msg.empty());
566*795d594fSAndroid Build Coastguard Worker }
567*795d594fSAndroid Build Coastguard Worker 
568*795d594fSAndroid Build Coastguard Worker #ifdef __LP64__
TEST_F(MemMapTest,MapAnonymousLow4GBExpectedTooHigh)569*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousLow4GBExpectedTooHigh) {
570*795d594fSAndroid Build Coastguard Worker   CommonInit();
571*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
572*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
573*795d594fSAndroid Build Coastguard Worker   MemMap map =
574*795d594fSAndroid Build Coastguard Worker       MemMap::MapAnonymous("MapAnonymousLow4GBExpectedTooHigh",
575*795d594fSAndroid Build Coastguard Worker                            reinterpret_cast<uint8_t*>(UINT64_C(0x100000000)),
576*795d594fSAndroid Build Coastguard Worker                            page_size,
577*795d594fSAndroid Build Coastguard Worker                            PROT_READ | PROT_WRITE,
578*795d594fSAndroid Build Coastguard Worker                            /*low_4gb=*/ true,
579*795d594fSAndroid Build Coastguard Worker                            /*reuse=*/ false,
580*795d594fSAndroid Build Coastguard Worker                            /*reservation=*/ nullptr,
581*795d594fSAndroid Build Coastguard Worker                            &error_msg);
582*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(map.IsValid());
583*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(error_msg.empty());
584*795d594fSAndroid Build Coastguard Worker }
585*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,MapAnonymousLow4GBRangeTooHigh)586*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousLow4GBRangeTooHigh) {
587*795d594fSAndroid Build Coastguard Worker   CommonInit();
588*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
589*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapAnonymous("MapAnonymousLow4GBRangeTooHigh",
590*795d594fSAndroid Build Coastguard Worker                                     /*addr=*/ reinterpret_cast<uint8_t*>(0xF0000000),
591*795d594fSAndroid Build Coastguard Worker                                     /*byte_count=*/ 0x20000000,
592*795d594fSAndroid Build Coastguard Worker                                     PROT_READ | PROT_WRITE,
593*795d594fSAndroid Build Coastguard Worker                                     /*low_4gb=*/ true,
594*795d594fSAndroid Build Coastguard Worker                                     /*reuse=*/ false,
595*795d594fSAndroid Build Coastguard Worker                                     /*reservation=*/ nullptr,
596*795d594fSAndroid Build Coastguard Worker                                     &error_msg);
597*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(map.IsValid());
598*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(error_msg.empty());
599*795d594fSAndroid Build Coastguard Worker }
600*795d594fSAndroid Build Coastguard Worker #endif
601*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,MapAnonymousReuse)602*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, MapAnonymousReuse) {
603*795d594fSAndroid Build Coastguard Worker   CommonInit();
604*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
605*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapAnonymous("MapAnonymousReserve",
606*795d594fSAndroid Build Coastguard Worker                                     /*byte_count=*/ 0x20000,
607*795d594fSAndroid Build Coastguard Worker                                     PROT_READ | PROT_WRITE,
608*795d594fSAndroid Build Coastguard Worker                                     /*low_4gb=*/ false,
609*795d594fSAndroid Build Coastguard Worker                                     &error_msg);
610*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map.IsValid());
611*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
612*795d594fSAndroid Build Coastguard Worker   MemMap map2 = MemMap::MapAnonymous("MapAnonymousReused",
613*795d594fSAndroid Build Coastguard Worker                                      /*addr=*/ reinterpret_cast<uint8_t*>(map.BaseBegin()),
614*795d594fSAndroid Build Coastguard Worker                                      /*byte_count=*/ 0x10000,
615*795d594fSAndroid Build Coastguard Worker                                      PROT_READ | PROT_WRITE,
616*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
617*795d594fSAndroid Build Coastguard Worker                                      /*reuse=*/ true,
618*795d594fSAndroid Build Coastguard Worker                                      /*reservation=*/ nullptr,
619*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
620*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map2.IsValid());
621*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
622*795d594fSAndroid Build Coastguard Worker }
623*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,CheckNoGaps)624*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, CheckNoGaps) {
625*795d594fSAndroid Build Coastguard Worker   CommonInit();
626*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
627*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
628*795d594fSAndroid Build Coastguard Worker   constexpr size_t kNumPages = 3;
629*795d594fSAndroid Build Coastguard Worker   // Map a 3-page mem map.
630*795d594fSAndroid Build Coastguard Worker   MemMap reservation = MemMap::MapAnonymous("MapAnonymous0",
631*795d594fSAndroid Build Coastguard Worker                                             page_size * kNumPages,
632*795d594fSAndroid Build Coastguard Worker                                             PROT_READ | PROT_WRITE,
633*795d594fSAndroid Build Coastguard Worker                                             /*low_4gb=*/ false,
634*795d594fSAndroid Build Coastguard Worker                                             &error_msg);
635*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(reservation.IsValid()) << error_msg;
636*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
637*795d594fSAndroid Build Coastguard Worker   // Record the base address.
638*795d594fSAndroid Build Coastguard Worker   uint8_t* map_base = reinterpret_cast<uint8_t*>(reservation.BaseBegin());
639*795d594fSAndroid Build Coastguard Worker 
640*795d594fSAndroid Build Coastguard Worker   // Map at the same address, taking from the `map` reservation.
641*795d594fSAndroid Build Coastguard Worker   MemMap map0 = MemMap::MapAnonymous("MapAnonymous0",
642*795d594fSAndroid Build Coastguard Worker                                      page_size,
643*795d594fSAndroid Build Coastguard Worker                                      PROT_READ | PROT_WRITE,
644*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
645*795d594fSAndroid Build Coastguard Worker                                      &reservation,
646*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
647*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map0.IsValid()) << error_msg;
648*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
649*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map_base, map0.Begin());
650*795d594fSAndroid Build Coastguard Worker   MemMap map1 = MemMap::MapAnonymous("MapAnonymous1",
651*795d594fSAndroid Build Coastguard Worker                                      page_size,
652*795d594fSAndroid Build Coastguard Worker                                      PROT_READ | PROT_WRITE,
653*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
654*795d594fSAndroid Build Coastguard Worker                                      &reservation,
655*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
656*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map1.IsValid()) << error_msg;
657*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
658*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map_base + page_size, map1.Begin());
659*795d594fSAndroid Build Coastguard Worker   MemMap map2 = MemMap::MapAnonymous("MapAnonymous2",
660*795d594fSAndroid Build Coastguard Worker                                      page_size,
661*795d594fSAndroid Build Coastguard Worker                                      PROT_READ | PROT_WRITE,
662*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
663*795d594fSAndroid Build Coastguard Worker                                      &reservation,
664*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
665*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map2.IsValid()) << error_msg;
666*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
667*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map_base + 2 * page_size, map2.Begin());
668*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(reservation.IsValid());  // The entire reservation was used.
669*795d594fSAndroid Build Coastguard Worker 
670*795d594fSAndroid Build Coastguard Worker   // One-map cases.
671*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(MemMap::CheckNoGaps(map0, map0));
672*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(MemMap::CheckNoGaps(map1, map1));
673*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(MemMap::CheckNoGaps(map2, map2));
674*795d594fSAndroid Build Coastguard Worker 
675*795d594fSAndroid Build Coastguard Worker   // Two or three-map cases.
676*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(MemMap::CheckNoGaps(map0, map1));
677*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(MemMap::CheckNoGaps(map1, map2));
678*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(MemMap::CheckNoGaps(map0, map2));
679*795d594fSAndroid Build Coastguard Worker 
680*795d594fSAndroid Build Coastguard Worker   // Unmap the middle one.
681*795d594fSAndroid Build Coastguard Worker   map1.Reset();
682*795d594fSAndroid Build Coastguard Worker 
683*795d594fSAndroid Build Coastguard Worker   // Should return false now that there's a gap in the middle.
684*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(MemMap::CheckNoGaps(map0, map2));
685*795d594fSAndroid Build Coastguard Worker }
686*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,AlignBy)687*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, AlignBy) {
688*795d594fSAndroid Build Coastguard Worker   CommonInit();
689*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
690*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
691*795d594fSAndroid Build Coastguard Worker   // Map a region.
692*795d594fSAndroid Build Coastguard Worker   MemMap m0 = MemMap::MapAnonymous("MemMapTest_AlignByTest_map0",
693*795d594fSAndroid Build Coastguard Worker                                    14 * page_size,
694*795d594fSAndroid Build Coastguard Worker                                    PROT_READ | PROT_WRITE,
695*795d594fSAndroid Build Coastguard Worker                                    /*low_4gb=*/ false,
696*795d594fSAndroid Build Coastguard Worker                                    &error_msg);
697*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(m0.IsValid());
698*795d594fSAndroid Build Coastguard Worker   uint8_t* base0 = m0.Begin();
699*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(base0 != nullptr) << error_msg;
700*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(m0.Size(), 14 * page_size);
701*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(m0.BaseBegin(), base0);
702*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(m0.BaseSize(), m0.Size());
703*795d594fSAndroid Build Coastguard Worker 
704*795d594fSAndroid Build Coastguard Worker   // Break it into several regions by using RemapAtEnd.
705*795d594fSAndroid Build Coastguard Worker   MemMap m1 = m0.RemapAtEnd(base0 + 3 * page_size,
706*795d594fSAndroid Build Coastguard Worker                             "MemMapTest_AlignByTest_map1",
707*795d594fSAndroid Build Coastguard Worker                             PROT_READ | PROT_WRITE,
708*795d594fSAndroid Build Coastguard Worker                             &error_msg);
709*795d594fSAndroid Build Coastguard Worker   uint8_t* base1 = m1.Begin();
710*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(base1 != nullptr) << error_msg;
711*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(base1, base0 + 3 * page_size);
712*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(m0.Size(), 3 * page_size);
713*795d594fSAndroid Build Coastguard Worker 
714*795d594fSAndroid Build Coastguard Worker   MemMap m2 = m1.RemapAtEnd(base1 + 4 * page_size,
715*795d594fSAndroid Build Coastguard Worker                             "MemMapTest_AlignByTest_map2",
716*795d594fSAndroid Build Coastguard Worker                             PROT_READ | PROT_WRITE,
717*795d594fSAndroid Build Coastguard Worker                             &error_msg);
718*795d594fSAndroid Build Coastguard Worker   uint8_t* base2 = m2.Begin();
719*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(base2 != nullptr) << error_msg;
720*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(base2, base1 + 4 * page_size);
721*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(m1.Size(), 4 * page_size);
722*795d594fSAndroid Build Coastguard Worker 
723*795d594fSAndroid Build Coastguard Worker   MemMap m3 = m2.RemapAtEnd(base2 + 3 * page_size,
724*795d594fSAndroid Build Coastguard Worker                             "MemMapTest_AlignByTest_map1",
725*795d594fSAndroid Build Coastguard Worker                             PROT_READ | PROT_WRITE,
726*795d594fSAndroid Build Coastguard Worker                             &error_msg);
727*795d594fSAndroid Build Coastguard Worker   uint8_t* base3 = m3.Begin();
728*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(base3 != nullptr) << error_msg;
729*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(base3, base2 + 3 * page_size);
730*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(m2.Size(), 3 * page_size);
731*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(m3.Size(), 4 * page_size);
732*795d594fSAndroid Build Coastguard Worker 
733*795d594fSAndroid Build Coastguard Worker   uint8_t* end0 = base0 + m0.Size();
734*795d594fSAndroid Build Coastguard Worker   uint8_t* end1 = base1 + m1.Size();
735*795d594fSAndroid Build Coastguard Worker   uint8_t* end2 = base2 + m2.Size();
736*795d594fSAndroid Build Coastguard Worker   uint8_t* end3 = base3 + m3.Size();
737*795d594fSAndroid Build Coastguard Worker 
738*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(end3 - base0), 14 * page_size);
739*795d594fSAndroid Build Coastguard Worker 
740*795d594fSAndroid Build Coastguard Worker   if (IsAlignedParam(base0, 2 * page_size)) {
741*795d594fSAndroid Build Coastguard Worker     ASSERT_FALSE(IsAlignedParam(base1, 2 * page_size));
742*795d594fSAndroid Build Coastguard Worker     ASSERT_FALSE(IsAlignedParam(base2, 2 * page_size));
743*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(IsAlignedParam(base3, 2 * page_size));
744*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(IsAlignedParam(end3, 2 * page_size));
745*795d594fSAndroid Build Coastguard Worker   } else {
746*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(IsAlignedParam(base1, 2 * page_size));
747*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(IsAlignedParam(base2, 2 * page_size));
748*795d594fSAndroid Build Coastguard Worker     ASSERT_FALSE(IsAlignedParam(base3, 2 * page_size));
749*795d594fSAndroid Build Coastguard Worker     ASSERT_FALSE(IsAlignedParam(end3, 2 * page_size));
750*795d594fSAndroid Build Coastguard Worker   }
751*795d594fSAndroid Build Coastguard Worker 
752*795d594fSAndroid Build Coastguard Worker   // Align by 2 * page_size;
753*795d594fSAndroid Build Coastguard Worker   m0.AlignBy(2 * page_size);
754*795d594fSAndroid Build Coastguard Worker   m1.AlignBy(2 * page_size);
755*795d594fSAndroid Build Coastguard Worker   m2.AlignBy(2 * page_size);
756*795d594fSAndroid Build Coastguard Worker   m3.AlignBy(2 * page_size);
757*795d594fSAndroid Build Coastguard Worker 
758*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(IsAlignedParam(m0.Begin(), 2 * page_size));
759*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(IsAlignedParam(m1.Begin(), 2 * page_size));
760*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(IsAlignedParam(m2.Begin(), 2 * page_size));
761*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(IsAlignedParam(m3.Begin(), 2 * page_size));
762*795d594fSAndroid Build Coastguard Worker 
763*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(IsAlignedParam(m0.Begin() + m0.Size(), 2 * page_size));
764*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(IsAlignedParam(m1.Begin() + m1.Size(), 2 * page_size));
765*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(IsAlignedParam(m2.Begin() + m2.Size(), 2 * page_size));
766*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(IsAlignedParam(m3.Begin() + m3.Size(), 2 * page_size));
767*795d594fSAndroid Build Coastguard Worker 
768*795d594fSAndroid Build Coastguard Worker   if (IsAlignedParam(base0, 2 * page_size)) {
769*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.Begin(), base0);
770*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.Begin() + m0.Size(), end0 - page_size);
771*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m1.Begin(), base1 + page_size);
772*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m1.Begin() + m1.Size(), end1 - page_size);
773*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m2.Begin(), base2 + page_size);
774*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m2.Begin() + m2.Size(), end2);
775*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m3.Begin(), base3);
776*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m3.Begin() + m3.Size(), end3);
777*795d594fSAndroid Build Coastguard Worker   } else {
778*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.Begin(), base0 + page_size);
779*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m0.Begin() + m0.Size(), end0);
780*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m1.Begin(), base1);
781*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m1.Begin() + m1.Size(), end1);
782*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m2.Begin(), base2);
783*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m2.Begin() + m2.Size(), end2 - page_size);
784*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m3.Begin(), base3 + page_size);
785*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(m3.Begin() + m3.Size(), end3 - page_size);
786*795d594fSAndroid Build Coastguard Worker   }
787*795d594fSAndroid Build Coastguard Worker }
788*795d594fSAndroid Build Coastguard Worker 
TEST_F(MemMapTest,Reservation)789*795d594fSAndroid Build Coastguard Worker TEST_F(MemMapTest, Reservation) {
790*795d594fSAndroid Build Coastguard Worker   CommonInit();
791*795d594fSAndroid Build Coastguard Worker   const size_t page_size = MemMap::GetPageSize();
792*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
793*795d594fSAndroid Build Coastguard Worker   ScratchFile scratch_file;
794*795d594fSAndroid Build Coastguard Worker   const size_t map_size = 5 * page_size;
795*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<uint8_t[]> data(new uint8_t[map_size]());
796*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(scratch_file.GetFile()->WriteFully(&data[0], map_size));
797*795d594fSAndroid Build Coastguard Worker 
798*795d594fSAndroid Build Coastguard Worker   MemMap reservation = MemMap::MapAnonymous("Test reservation",
799*795d594fSAndroid Build Coastguard Worker                                             map_size,
800*795d594fSAndroid Build Coastguard Worker                                             PROT_NONE,
801*795d594fSAndroid Build Coastguard Worker                                             /*low_4gb=*/ false,
802*795d594fSAndroid Build Coastguard Worker                                             &error_msg);
803*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(reservation.IsValid());
804*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
805*795d594fSAndroid Build Coastguard Worker 
806*795d594fSAndroid Build Coastguard Worker   // Map first part of the reservation.
807*795d594fSAndroid Build Coastguard Worker   const size_t chunk1_size = page_size - 1u;
808*795d594fSAndroid Build Coastguard Worker   ASSERT_LT(chunk1_size, map_size) << "We want to split the reservation.";
809*795d594fSAndroid Build Coastguard Worker   uint8_t* addr1 = reservation.Begin();
810*795d594fSAndroid Build Coastguard Worker   MemMap map1 = MemMap::MapFileAtAddress(addr1,
811*795d594fSAndroid Build Coastguard Worker                                          /*byte_count=*/ chunk1_size,
812*795d594fSAndroid Build Coastguard Worker                                          PROT_READ,
813*795d594fSAndroid Build Coastguard Worker                                          MAP_PRIVATE,
814*795d594fSAndroid Build Coastguard Worker                                          scratch_file.GetFd(),
815*795d594fSAndroid Build Coastguard Worker                                          /*start=*/ 0,
816*795d594fSAndroid Build Coastguard Worker                                          /*low_4gb=*/ false,
817*795d594fSAndroid Build Coastguard Worker                                          scratch_file.GetFilename().c_str(),
818*795d594fSAndroid Build Coastguard Worker                                          /*reuse=*/ false,
819*795d594fSAndroid Build Coastguard Worker                                          &reservation,
820*795d594fSAndroid Build Coastguard Worker                                          &error_msg);
821*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map1.IsValid()) << error_msg;
822*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
823*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map1.Size(), chunk1_size);
824*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(addr1, map1.Begin());
825*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(reservation.IsValid());
826*795d594fSAndroid Build Coastguard Worker   // Entire pages are taken from the `reservation`.
827*795d594fSAndroid Build Coastguard Worker   ASSERT_LT(map1.End(), map1.BaseEnd());
828*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map1.BaseEnd(), reservation.Begin());
829*795d594fSAndroid Build Coastguard Worker 
830*795d594fSAndroid Build Coastguard Worker   // Map second part as an anonymous mapping.
831*795d594fSAndroid Build Coastguard Worker   const size_t chunk2_size = 2 * page_size;
832*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(chunk2_size, reservation.Size());  // We want to split the reservation.
833*795d594fSAndroid Build Coastguard Worker   uint8_t* addr2 = reservation.Begin();
834*795d594fSAndroid Build Coastguard Worker   MemMap map2 = MemMap::MapAnonymous("MiddleReservation",
835*795d594fSAndroid Build Coastguard Worker                                      addr2,
836*795d594fSAndroid Build Coastguard Worker                                      /*byte_count=*/ chunk2_size,
837*795d594fSAndroid Build Coastguard Worker                                      PROT_READ,
838*795d594fSAndroid Build Coastguard Worker                                      /*low_4gb=*/ false,
839*795d594fSAndroid Build Coastguard Worker                                      /*reuse=*/ false,
840*795d594fSAndroid Build Coastguard Worker                                      &reservation,
841*795d594fSAndroid Build Coastguard Worker                                      &error_msg);
842*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map2.IsValid()) << error_msg;
843*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
844*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map2.Size(), chunk2_size);
845*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(addr2, map2.Begin());
846*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map2.End(), map2.BaseEnd());  // chunk2_size is page aligned.
847*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map2.BaseEnd(), reservation.Begin());
848*795d594fSAndroid Build Coastguard Worker 
849*795d594fSAndroid Build Coastguard Worker   // Map the rest of the reservation except the last byte.
850*795d594fSAndroid Build Coastguard Worker   const size_t chunk3_size = reservation.Size() - 1u;
851*795d594fSAndroid Build Coastguard Worker   uint8_t* addr3 = reservation.Begin();
852*795d594fSAndroid Build Coastguard Worker   MemMap map3 = MemMap::MapFileAtAddress(addr3,
853*795d594fSAndroid Build Coastguard Worker                                          /*byte_count=*/ chunk3_size,
854*795d594fSAndroid Build Coastguard Worker                                          PROT_READ,
855*795d594fSAndroid Build Coastguard Worker                                          MAP_PRIVATE,
856*795d594fSAndroid Build Coastguard Worker                                          scratch_file.GetFd(),
857*795d594fSAndroid Build Coastguard Worker                                          /*start=*/ dchecked_integral_cast<size_t>(addr3 - addr1),
858*795d594fSAndroid Build Coastguard Worker                                          /*low_4gb=*/ false,
859*795d594fSAndroid Build Coastguard Worker                                          scratch_file.GetFilename().c_str(),
860*795d594fSAndroid Build Coastguard Worker                                          /*reuse=*/ false,
861*795d594fSAndroid Build Coastguard Worker                                          &reservation,
862*795d594fSAndroid Build Coastguard Worker                                          &error_msg);
863*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map3.IsValid()) << error_msg;
864*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
865*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map3.Size(), chunk3_size);
866*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(addr3, map3.Begin());
867*795d594fSAndroid Build Coastguard Worker   // Entire pages are taken from the `reservation`, so it's now exhausted.
868*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(reservation.IsValid());
869*795d594fSAndroid Build Coastguard Worker 
870*795d594fSAndroid Build Coastguard Worker   // Now split the MiddleReservation.
871*795d594fSAndroid Build Coastguard Worker   const size_t chunk2a_size = page_size - 1u;
872*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(chunk2a_size, map2.Size());  // We want to split the reservation.
873*795d594fSAndroid Build Coastguard Worker   MemMap map2a = map2.TakeReservedMemory(chunk2a_size);
874*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map2a.IsValid()) << error_msg;
875*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
876*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map2a.Size(), chunk2a_size);
877*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(addr2, map2a.Begin());
878*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map2.IsValid());
879*795d594fSAndroid Build Coastguard Worker   ASSERT_LT(map2a.End(), map2a.BaseEnd());
880*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map2a.BaseEnd(), map2.Begin());
881*795d594fSAndroid Build Coastguard Worker 
882*795d594fSAndroid Build Coastguard Worker   // And take the rest of the middle reservation.
883*795d594fSAndroid Build Coastguard Worker   const size_t chunk2b_size = map2.Size() - 1u;
884*795d594fSAndroid Build Coastguard Worker   uint8_t* addr2b = map2.Begin();
885*795d594fSAndroid Build Coastguard Worker   MemMap map2b = map2.TakeReservedMemory(chunk2b_size);
886*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(map2b.IsValid()) << error_msg;
887*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(error_msg.empty());
888*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(map2b.Size(), chunk2a_size);
889*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(addr2b, map2b.Begin());
890*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(map2.IsValid());
891*795d594fSAndroid Build Coastguard Worker }
892*795d594fSAndroid Build Coastguard Worker 
893*795d594fSAndroid Build Coastguard Worker }  // namespace art
894*795d594fSAndroid Build Coastguard Worker 
895*795d594fSAndroid Build Coastguard Worker namespace {
896*795d594fSAndroid Build Coastguard Worker 
897*795d594fSAndroid Build Coastguard Worker class DumpMapsOnFailListener : public testing::EmptyTestEventListener {
OnTestPartResult(const testing::TestPartResult & result)898*795d594fSAndroid Build Coastguard Worker   void OnTestPartResult(const testing::TestPartResult& result) override {
899*795d594fSAndroid Build Coastguard Worker     switch (result.type()) {
900*795d594fSAndroid Build Coastguard Worker       case testing::TestPartResult::kFatalFailure:
901*795d594fSAndroid Build Coastguard Worker         art::PrintFileToLog("/proc/self/maps", android::base::LogSeverity::ERROR);
902*795d594fSAndroid Build Coastguard Worker         break;
903*795d594fSAndroid Build Coastguard Worker 
904*795d594fSAndroid Build Coastguard Worker       // TODO: Could consider logging on EXPECT failures.
905*795d594fSAndroid Build Coastguard Worker       case testing::TestPartResult::kNonFatalFailure:
906*795d594fSAndroid Build Coastguard Worker       case testing::TestPartResult::kSkip:
907*795d594fSAndroid Build Coastguard Worker       case testing::TestPartResult::kSuccess:
908*795d594fSAndroid Build Coastguard Worker         break;
909*795d594fSAndroid Build Coastguard Worker     }
910*795d594fSAndroid Build Coastguard Worker   }
911*795d594fSAndroid Build Coastguard Worker };
912*795d594fSAndroid Build Coastguard Worker 
913*795d594fSAndroid Build Coastguard Worker }  // namespace
914*795d594fSAndroid Build Coastguard Worker 
915*795d594fSAndroid Build Coastguard Worker // Inject our listener into the test runner.
916*795d594fSAndroid Build Coastguard Worker extern "C"
917*795d594fSAndroid Build Coastguard Worker __attribute__((visibility("default"))) __attribute__((used))
ArtTestGlobalInit()918*795d594fSAndroid Build Coastguard Worker void ArtTestGlobalInit() {
919*795d594fSAndroid Build Coastguard Worker   testing::UnitTest::GetInstance()->listeners().Append(new DumpMapsOnFailListener());
920*795d594fSAndroid Build Coastguard Worker }
921