127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom/* 227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * Copyright (C) 2008 The Android Open Source Project 327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * 427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * you may not use this file except in compliance with the License. 627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * You may obtain a copy of the License at 727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * 827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * 1027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * Unless required by applicable law or agreed to in writing, software 1127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 1227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * See the License for the specific language governing permissions and 1427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom * limitations under the License. 1527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom */ 1627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 1727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include "mem_map.h" 1827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 191e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov#include "base/memory_tool.h" 20943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris#include <backtrace/BacktraceMap.h> 21c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include <inttypes.h> 220389cd57de8faedb85b749656b8e1735a7bce002Josh Gao#include <stdlib.h> 23c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers 24700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory> 25c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include <sstream> 26e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes 27e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 28277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 29277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic push 30277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic ignored "-Wshadow" 316c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "ScopedFd.h" 32277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic pop 33277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 34c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include "thread-inl.h" 356c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "utils.h" 366c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 376c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include <cutils/ashmem.h> 38a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray 39997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#ifndef ANDROID_OS 40997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#include <sys/resource.h> 41997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#endif 426c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 43d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#ifndef MAP_ANONYMOUS 44d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#define MAP_ANONYMOUS MAP_ANON 45d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#endif 46d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers 4727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstromnamespace art { 4827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 49943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferrisstatic std::ostream& operator<<( 50943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::ostream& os, 51943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::pair<BacktraceMap::const_iterator, BacktraceMap::const_iterator> iters) { 52943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris for (BacktraceMap::const_iterator it = iters.first; it != iters.second; ++it) { 53943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris os << StringPrintf("0x%08x-0x%08x %c%c%c %s\n", 54943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->start), 55943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->end), 56943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_READ) ? 'r' : '-', 57943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_WRITE) ? 'w' : '-', 58943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_EXEC) ? 'x' : '-', it->name.c_str()); 59ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes } 60ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes return os; 6196970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes} 6296970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 63bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierstd::ostream& operator<<(std::ostream& os, const MemMap::Maps& mem_maps) { 643eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << "MemMap:" << std::endl; 653eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi for (auto it = mem_maps.begin(); it != mem_maps.end(); ++it) { 663eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi void* base = it->first; 673eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = it->second; 683eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK_EQ(base, map->BaseBegin()); 693eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << *map << std::endl; 703eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 713eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return os; 723eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 733eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 746e88ef6b604a7a945a466784580c42e6554c1289Mathieu ChartierMemMap::Maps* MemMap::maps_ = nullptr; 753eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 76c3ccc1039e0bbc0744f958cb8719cf96bce5b853Ian Rogers#if USE_ART_LOW_4G_ALLOCATOR 77d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Handling mem_map in 32b address range for 64b architectures that do not support MAP_32BIT. 78d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 79d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// The regular start of memory allocations. The first 64KB is protected by SELinux. 806bd621aa31aa94ed42a2a35256d219630bf0b687Andreas Gampestatic constexpr uintptr_t LOW_MEM_START = 64 * KB; 817104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 82d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Generate random starting position. 83d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// To not interfere with image position, take the image's address and only place it below. Current 84d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// formula (sketch): 85d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// 86d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ART_BASE_ADDR = 0001XXXXXXXXXXXXXXX 87d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ---------------------------------------- 88d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// = 0000111111111111111 89d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// & ~(kPageSize - 1) =~0000000000000001111 90d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ---------------------------------------- 91d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// mask = 0000111111111110000 92d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// & random data = YYYYYYYYYYYYYYYYYYY 93d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ----------------------------------- 94d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// tmp = 0000YYYYYYYYYYY0000 95d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// + LOW_MEM_START = 0000000000001000000 96d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// -------------------------------------- 97d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// start 98d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// 990389cd57de8faedb85b749656b8e1735a7bce002Josh Gao// arc4random as an entropy source is exposed in Bionic, but not in glibc. When we 100d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// do not have Bionic, simply start with LOW_MEM_START. 101d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 102d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Function is standalone so it can be tested somewhat in mem_map_test.cc. 103d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 104d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampeuintptr_t CreateStartPos(uint64_t input) { 105d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe CHECK_NE(0, ART_BASE_ADDRESS); 106d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 107d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Start with all bits below highest bit in ART_BASE_ADDRESS. 108d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr size_t leading_zeros = CLZ(static_cast<uint32_t>(ART_BASE_ADDRESS)); 109d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr uintptr_t mask_ones = (1 << (31 - leading_zeros)) - 1; 110d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 111d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Lowest (usually 12) bits are not used, as aligned by page size. 112d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr uintptr_t mask = mask_ones & ~(kPageSize - 1); 113d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 114d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Mask input data. 115d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return (input & mask) + LOW_MEM_START; 116d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe} 117d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 118d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 119d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampestatic uintptr_t GenerateNextMemPos() { 120d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 1210389cd57de8faedb85b749656b8e1735a7bce002Josh Gao uint64_t random_data; 1220389cd57de8faedb85b749656b8e1735a7bce002Josh Gao arc4random_buf(&random_data, sizeof(random_data)); 1230389cd57de8faedb85b749656b8e1735a7bce002Josh Gao return CreateStartPos(random_data); 124d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#else 1250389cd57de8faedb85b749656b8e1735a7bce002Josh Gao // No arc4random on host, see above. 126d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return LOW_MEM_START; 127d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 128d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe} 129d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 130d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Initialize linear scan to random position. 131d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampeuintptr_t MemMap::next_mem_pos_ = GenerateNextMemPos(); 1328dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#endif 1338dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 13424a0fc8df930584446d6e3628df9ec6c36e53239Mathieu Chartier// Return true if the address range is contained in a single memory map by either reading 13524a0fc8df930584446d6e3628df9ec6c36e53239Mathieu Chartier// the maps_ variable or the /proc/self/map entry. 136e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierbool MemMap::ContainedWithinExistingMap(uint8_t* ptr, size_t size, std::string* error_msg) { 1375c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko uintptr_t begin = reinterpret_cast<uintptr_t>(ptr); 1385c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko uintptr_t end = begin + size; 139e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier 14024a0fc8df930584446d6e3628df9ec6c36e53239Mathieu Chartier // There is a suspicion that BacktraceMap::Create is occasionally missing maps. TODO: Investigate 14124a0fc8df930584446d6e3628df9ec6c36e53239Mathieu Chartier // further. 142e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier { 143e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 14424a0fc8df930584446d6e3628df9ec6c36e53239Mathieu Chartier for (auto& pair : *maps_) { 145e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier MemMap* const map = pair.second; 146e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier if (begin >= reinterpret_cast<uintptr_t>(map->Begin()) && 147e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier end <= reinterpret_cast<uintptr_t>(map->End())) { 148e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier return true; 149e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier } 150e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier } 151e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier } 152e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier 153a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); 154ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier if (map == nullptr) { 155ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier if (error_msg != nullptr) { 156ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier *error_msg = StringPrintf("Failed to build process map"); 157ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier } 158a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 159a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 160250a96671720090a3756d597a4bda0a394777222Christopher Ferris 161250a96671720090a3756d597a4bda0a394777222Christopher Ferris ScopedBacktraceMapIteratorLock lock(map.get()); 162a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 163a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if ((begin >= it->start && begin < it->end) // start of new within old 164a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo && (end > it->start && end <= it->end)) { // end of new within old 165a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return true; 166a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 167a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 168ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier if (error_msg != nullptr) { 169ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier PrintFileToLog("/proc/self/maps", LogSeverity::ERROR); 170ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier *error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " does not overlap " 171ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier "any existing map. See process maps in the log.", begin, end); 172ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier } 173a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 174a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo} 175a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 176a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// Return true if the address range does not conflict with any /proc/self/maps entry. 177a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guostatic bool CheckNonOverlapping(uintptr_t begin, 178a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t end, 179a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::string* error_msg) { 180a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); 181836572a07142627ff291d686a4e9e03a0988344bChristopher Ferris if (map.get() == nullptr) { 182a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Failed to build process map"); 183a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 184a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 185250a96671720090a3756d597a4bda0a394777222Christopher Ferris ScopedBacktraceMapIteratorLock(map.get()); 186a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 187a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if ((begin >= it->start && begin < it->end) // start of new within old 188a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo || (end > it->start && end < it->end) // end of new within old 189a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo || (begin <= it->start && end > it->end)) { // start/end of new includes all of old 190a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::ostringstream map_info; 191a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo map_info << std::make_pair(it, map->end()); 192a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " overlaps with " 193a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo "existing map 0x%08" PRIxPTR "-0x%08" PRIxPTR " (%s)\n%s", 194a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo begin, end, 195a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo static_cast<uintptr_t>(it->start), static_cast<uintptr_t>(it->end), 196a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo it->name.c_str(), 197a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo map_info.str().c_str()); 198a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 199a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 200a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 201a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return true; 202a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo} 203a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 204a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// CheckMapRequest to validate a non-MAP_FAILED mmap result based on 205a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// the expected value, calling munmap if validation fails, giving the 206a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// reason in error_msg. 207a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// 2082cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier// If the expected_ptr is null, nothing is checked beyond the fact 209a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// that the actual_ptr is not MAP_FAILED. However, if expected_ptr is 210a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// non-null, we check that pointer is the actual_ptr == expected_ptr, 211a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// and if not, report in error_msg what the conflict mapping was if 212a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// found, or a generic error in other cases. 21313735955f39b3b304c37d2b2840663c131262c18Ian Rogersstatic bool CheckMapRequest(uint8_t* expected_ptr, void* actual_ptr, size_t byte_count, 214a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::string* error_msg) { 2154fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Handled first by caller for more specific error messages. 2164fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(actual_ptr != MAP_FAILED); 2174fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 2184fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == nullptr) { 2194fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 2204fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 2214fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 222a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t actual = reinterpret_cast<uintptr_t>(actual_ptr); 223a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t expected = reinterpret_cast<uintptr_t>(expected_ptr); 224a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t limit = expected + byte_count; 225a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 2264fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == actual_ptr) { 2274fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 2284fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 2294fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 2304fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // We asked for an address but didn't get what we wanted, all paths below here should fail. 2314fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi int result = munmap(actual_ptr, byte_count); 2324fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (result == -1) { 2334fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi PLOG(WARNING) << StringPrintf("munmap(%p, %zd) failed", actual_ptr, byte_count); 23427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 235ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes 236ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier if (error_msg != nullptr) { 23783723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier // We call this here so that we can try and generate a full error 23883723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier // message with the overlapping mapping. There's no guarantee that 23983723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier // that there will be an overlap though, since 24083723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier // - The kernel is not *required* to honor expected_ptr unless MAP_FIXED is 24183723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier // true, even if there is no overlap 24283723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier // - There might have been an overlap at the point of mmap, but the 24383723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier // overlapping region has since been unmapped. 24483723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier std::string error_detail; 24583723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier CheckNonOverlapping(expected, limit, &error_detail); 246ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier std::ostringstream os; 247ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier os << StringPrintf("Failed to mmap at expected address, mapped at " 248ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier "0x%08" PRIxPTR " instead of 0x%08" PRIxPTR, 249ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier actual, expected); 250ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier if (!error_detail.empty()) { 251ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier os << " : " << error_detail; 252ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier } 253ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier *error_msg = os.str(); 254943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris } 2554fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 25627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 25727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 25838c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier#if USE_ART_LOW_4G_ALLOCATOR 25942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartierstatic inline void* TryMemMapLow4GB(void* ptr, 26042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier size_t page_aligned_byte_count, 26142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int prot, 26242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int flags, 26342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int fd, 26442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier off_t offset) { 26542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier void* actual = mmap(ptr, page_aligned_byte_count, prot, flags, fd, offset); 26638c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier if (actual != MAP_FAILED) { 26738c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier // Since we didn't use MAP_FIXED the kernel may have mapped it somewhere not in the low 26838c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier // 4GB. If this is the case, unmap and retry. 26938c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier if (reinterpret_cast<uintptr_t>(actual) + page_aligned_byte_count >= 4 * GB) { 27038c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier munmap(actual, page_aligned_byte_count); 27138c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier actual = MAP_FAILED; 27238c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier } 27338c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier } 27438c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier return actual; 27538c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier} 27638c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier#endif 27738c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier 27842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu ChartierMemMap* MemMap::MapAnonymous(const char* name, 27942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier uint8_t* expected_ptr, 28042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier size_t byte_count, 28142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int prot, 28242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier bool low_4gb, 28342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier bool reuse, 284a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray std::string* error_msg, 285a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray bool use_ashmem) { 2866a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#ifndef __LP64__ 2876a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(low_4gb); 2886a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#endif 2899004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 290a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(name, nullptr, 0, nullptr, 0, prot, false); 2919004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 292ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize); 2936c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 294997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers int flags = MAP_PRIVATE | MAP_ANONYMOUS; 2955c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko if (reuse) { 2965c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko // reuse means it is okay that it overlaps an existing page mapping. 2975c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko // Only use this if you actually made the page reservation yourself. 2985c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko CHECK(expected_ptr != nullptr); 2995c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 300b5505823ad3d0bab8fc9c15c266a3d8cd96ee59eVladimir Marko DCHECK(ContainedWithinExistingMap(expected_ptr, byte_count, error_msg)) << *error_msg; 3015c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko flags |= MAP_FIXED; 3025c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } 3035c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 304997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers ScopedFd fd(-1); 305997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers 306a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray if (use_ashmem) { 307a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray if (!kIsTargetBuild) { 308a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray // When not on Android ashmem is faked using files in /tmp. Ensure that such files won't 309a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray // fail due to ulimit restrictions. If they will then use a regular mmap. 310a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray struct rlimit rlimit_fsize; 311a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray CHECK_EQ(getrlimit(RLIMIT_FSIZE, &rlimit_fsize), 0); 312a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray use_ashmem = (rlimit_fsize.rlim_cur == RLIM_INFINITY) || 313a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray (page_aligned_byte_count < rlimit_fsize.rlim_cur); 314a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray } 315a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray } 316a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray 317997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers if (use_ashmem) { 318997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 319997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // prefixed "dalvik-". 320997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers std::string debug_friendly_name("dalvik-"); 321997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers debug_friendly_name += name; 322997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers fd.reset(ashmem_create_region(debug_friendly_name.c_str(), page_aligned_byte_count)); 323997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers if (fd.get() == -1) { 324997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", name, strerror(errno)); 325997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers return nullptr; 326997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers } 3275c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko flags &= ~MAP_ANONYMOUS; 328997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers } 3298dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 330aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom // We need to store and potentially set an error number for pretty printing of errors 331aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom int saved_errno = 0; 332aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 33342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier void* actual = MapInternal(expected_ptr, 33442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier page_aligned_byte_count, 33542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier prot, 33642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier flags, 33742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier fd.get(), 33842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 0, 33942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier low_4gb); 340aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = errno; 3418dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 34227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 34383723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier if (error_msg != nullptr) { 34483723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 34583723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier 34683723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier *error_msg = StringPrintf("Failed anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0): %s. " 34783723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier "See process maps in the log.", 34883723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier expected_ptr, 34983723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier page_aligned_byte_count, 35083723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier prot, 35183723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier flags, 35283723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier fd.get(), 35383723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier strerror(saved_errno)); 35483723aedac536fd8a3cd6e1662dbd6260e576194Mathieu Chartier } 3554fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 3564fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 3574fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 358a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) { 3598d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers return nullptr; 36027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 36113735955f39b3b304c37d2b2840663c131262c18Ian Rogers return new MemMap(name, reinterpret_cast<uint8_t*>(actual), byte_count, actual, 36201d4b5072c064d927260486c891a09fe689289c0Mathieu Chartier page_aligned_byte_count, prot, reuse); 36327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 36427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 3651baabf0726eb285284e0c908ccba9f209b399faeDavid SrbeckyMemMap* MemMap::MapDummy(const char* name, uint8_t* addr, size_t byte_count) { 3661baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky if (byte_count == 0) { 3671baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky return new MemMap(name, nullptr, 0, nullptr, 0, 0, false); 3681baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky } 3691baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky const size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize); 3701baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky return new MemMap(name, addr, byte_count, addr, page_aligned_byte_count, 0, true /* reuse */); 3711baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky} 3721baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky 37342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu ChartierMemMap* MemMap::MapFileAtAddress(uint8_t* expected_ptr, 37442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier size_t byte_count, 37542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int prot, 37642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int flags, 37742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int fd, 37842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier off_t start, 37942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier bool low_4gb, 38042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier bool reuse, 38142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier const char* filename, 3828d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg) { 38327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, prot); 38427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, flags & (MAP_SHARED | MAP_PRIVATE)); 385b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath 386b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // Note that we do not allow MAP_FIXED unless reuse == true, i.e we 387b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // expect his mapping to be contained within an existing map. 3884fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (reuse) { 3894fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // reuse means it is okay that it overlaps an existing page mapping. 3904fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Only use this if you actually made the page reservation yourself. 391a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo CHECK(expected_ptr != nullptr); 392b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath 393ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier DCHECK(ContainedWithinExistingMap(expected_ptr, byte_count, error_msg)) 394ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier << ((error_msg != nullptr) ? *error_msg : std::string()); 3954fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi flags |= MAP_FIXED; 3964fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } else { 3974fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK_EQ(0, flags & MAP_FIXED); 398b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // Don't bother checking for an overlapping region here. We'll 399b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // check this if required after the fact inside CheckMapRequest. 4004fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 4014fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 4029004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 403a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(filename, nullptr, 0, nullptr, 0, prot, false); 4049004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 405f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'offset' to be page-aligned as required by mmap. 40627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom int page_offset = start % kPageSize; 40727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom off_t page_aligned_offset = start - page_offset; 408f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'byte_count' to be page-aligned as we will map this anyway. 409ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count + page_offset, kPageSize); 410a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo // The 'expected_ptr' is modified (if specified, ie non-null) to be page aligned to the file but 411a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo // not necessarily to virtual memory. mmap will page align 'expected' for us. 4122cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier uint8_t* page_aligned_expected = 4132cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier (expected_ptr == nullptr) ? nullptr : (expected_ptr - page_offset); 4144fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 4151e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov size_t redzone_size = 0; 4161e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov if (RUNNING_ON_MEMORY_TOOL && kMemoryToolAddsRedzones && expected_ptr == nullptr) { 4171e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov redzone_size = kPageSize; 4181e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov page_aligned_byte_count += redzone_size; 4191e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov } 4201e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 42142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier uint8_t* actual = reinterpret_cast<uint8_t*>(MapInternal(page_aligned_expected, 42242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier page_aligned_byte_count, 42342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier prot, 42442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier flags, 42542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier fd, 42642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier page_aligned_offset, 42742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier low_4gb)); 42827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 429ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier if (error_msg != nullptr) { 430ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier auto saved_errno = errno; 431aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 432dfd7b70bbab8157fb385e4a6d6e4b55ae2e4e892Andreas Gampe if (kIsDebugBuild || VLOG_IS_ON(oat)) { 433dfd7b70bbab8157fb385e4a6d6e4b55ae2e4e892Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 434dfd7b70bbab8157fb385e4a6d6e4b55ae2e4e892Andreas Gampe } 435aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 436ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier *error_msg = StringPrintf("mmap(%p, %zd, 0x%x, 0x%x, %d, %" PRId64 437ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier ") of file '%s' failed: %s. See process maps in the log.", 438ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier page_aligned_expected, page_aligned_byte_count, prot, flags, fd, 439ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier static_cast<int64_t>(page_aligned_offset), filename, 440ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier strerror(saved_errno)); 441ebe2dfcb1346d2010787ebbb15ae2965fcd2b223Mathieu Chartier } 4424fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 4434fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 4444fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 445a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) { 4464fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 44727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 4481e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov if (redzone_size != 0) { 4491e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov const uint8_t *real_start = actual + page_offset; 4501e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov const uint8_t *real_end = actual + page_offset + byte_count; 4511e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov const uint8_t *mapping_end = actual + page_aligned_byte_count; 4521e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 4531e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_NOACCESS(actual, real_start - actual); 4541e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_NOACCESS(real_end, mapping_end - real_end); 4551e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov page_aligned_byte_count -= redzone_size; 4561e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov } 4571e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 4580d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return new MemMap(filename, actual + page_offset, byte_count, actual, page_aligned_byte_count, 4591e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov prot, reuse, redzone_size); 46027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 46127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 46227ec961a1da540ba7f16c07a682585ab167317adBrian CarlstromMemMap::~MemMap() { 4634fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 46427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return; 46527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 4661e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 4671e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov // Unlike Valgrind, AddressSanitizer requires that all manually poisoned memory is unpoisoned 4681e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov // before it is returned to the system. 4691e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov if (redzone_size_ != 0) { 4701e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_UNDEFINED( 4711e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov reinterpret_cast<char*>(base_begin_) + base_size_ - redzone_size_, 4721e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov redzone_size_); 4731e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov } 4741e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 475a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!reuse_) { 4761e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_UNDEFINED(base_begin_, base_size_); 477a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo int result = munmap(base_begin_, base_size_); 478a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (result == -1) { 479a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo PLOG(FATAL) << "munmap failed"; 480a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 48127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 4823eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 4833eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Remove it from maps_. 4843eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 4853eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi bool found = false; 4866e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 4876e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(base_begin_), end = maps_->end(); 4883eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == base_begin_; ++it) { 4893eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (it->second == this) { 4903eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi found = true; 4916e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_->erase(it); 4923eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi break; 4933eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 4943eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 4953eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(found) << "MemMap not found"; 49627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 49727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 49813735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap::MemMap(const std::string& name, uint8_t* begin, size_t size, void* base_begin, 4991e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov size_t base_size, int prot, bool reuse, size_t redzone_size) 5001c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier : name_(name), begin_(begin), size_(size), base_begin_(base_begin), base_size_(base_size), 5011e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov prot_(prot), reuse_(reuse), redzone_size_(redzone_size) { 5029004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (size_ == 0) { 5034fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ == nullptr); 5044fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ == nullptr); 5059004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_EQ(base_size_, 0U); 5069004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } else { 5074fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ != nullptr); 5084fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ != nullptr); 5099004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_NE(base_size_, 0U); 5103eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5113eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Add it to maps_. 5123eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 5136e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 5146e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_->insert(std::make_pair(base_begin_, this)); 5159004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 516c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampe} 51727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 51813735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap* MemMap::RemapAtEnd(uint8_t* new_end, const char* tail_name, int tail_prot, 519a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray std::string* error_msg, bool use_ashmem) { 520cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_GE(new_end, Begin()); 521cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_LE(new_end, End()); 52213735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK_LE(begin_ + size_, reinterpret_cast<uint8_t*>(base_begin_) + base_size_); 52314d90579f013b374638b599361970557ed4b3f09Roland Levillain DCHECK_ALIGNED(begin_, kPageSize); 52414d90579f013b374638b599361970557ed4b3f09Roland Levillain DCHECK_ALIGNED(base_begin_, kPageSize); 52514d90579f013b374638b599361970557ed4b3f09Roland Levillain DCHECK_ALIGNED(reinterpret_cast<uint8_t*>(base_begin_) + base_size_, kPageSize); 52614d90579f013b374638b599361970557ed4b3f09Roland Levillain DCHECK_ALIGNED(new_end, kPageSize); 52713735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* old_end = begin_ + size_; 52813735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* old_base_end = reinterpret_cast<uint8_t*>(base_begin_) + base_size_; 52913735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* new_base_end = new_end; 530fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(new_base_end, old_base_end); 531fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (new_base_end == old_base_end) { 532a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(tail_name, nullptr, 0, nullptr, 0, tail_prot, false); 533fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 53413735955f39b3b304c37d2b2840663c131262c18Ian Rogers size_ = new_end - reinterpret_cast<uint8_t*>(begin_); 53513735955f39b3b304c37d2b2840663c131262c18Ian Rogers base_size_ = new_base_end - reinterpret_cast<uint8_t*>(base_begin_); 53613735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK_LE(begin_ + size_, reinterpret_cast<uint8_t*>(base_begin_) + base_size_); 537fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_size = old_end - new_end; 53813735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* tail_base_begin = new_base_end; 539fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_base_size = old_base_end - new_base_end; 540fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_EQ(tail_base_begin + tail_base_size, old_base_end); 54114d90579f013b374638b599361970557ed4b3f09Roland Levillain DCHECK_ALIGNED(tail_base_size, kPageSize); 542fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 543a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray int int_fd = -1; 544fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int flags = MAP_PRIVATE | MAP_ANONYMOUS; 545a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray if (use_ashmem) { 546a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 547a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray // prefixed "dalvik-". 548a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray std::string debug_friendly_name("dalvik-"); 549a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray debug_friendly_name += tail_name; 550a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray int_fd = ashmem_create_region(debug_friendly_name.c_str(), tail_base_size); 551a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray flags = MAP_PRIVATE | MAP_FIXED; 552a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray if (int_fd == -1) { 553a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", 554a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray tail_name, strerror(errno)); 555a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray return nullptr; 556a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray } 557a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray } 558a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray ScopedFd fd(int_fd); 5591e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 5601e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_UNDEFINED(tail_base_begin, tail_base_size); 561fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Unmap/map the tail region. 562fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int result = munmap(tail_base_begin, tail_base_size); 563fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (result == -1) { 564a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 565a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe *error_msg = StringPrintf("munmap(%p, %zd) failed for '%s'. See process maps in the log.", 566a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe tail_base_begin, tail_base_size, name_.c_str()); 567fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 568fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 569fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Don't cause memory allocation between the munmap and the mmap 570fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // calls. Otherwise, libc (or something else) might take this memory 571fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // region. Note this isn't perfect as there's no way to prevent 572fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // other threads to try to take this memory region here. 57313735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(tail_base_begin, tail_base_size, tail_prot, 574fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi flags, fd.get(), 0)); 575fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (actual == MAP_FAILED) { 576a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 577a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe *error_msg = StringPrintf("anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0) failed. See process " 578a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe "maps in the log.", tail_base_begin, tail_base_size, tail_prot, flags, 579a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe fd.get()); 580fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 581fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 582a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(tail_name, actual, tail_size, actual, tail_base_size, tail_prot, false); 583cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier} 584d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 585c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogersvoid MemMap::MadviseDontNeedAndZero() { 586c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (base_begin_ != nullptr || base_size_ != 0) { 587c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (!kMadviseZeroes) { 588c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers memset(base_begin_, 0, base_size_); 589c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 590c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers int result = madvise(base_begin_, base_size_, MADV_DONTNEED); 591c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (result == -1) { 592c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers PLOG(WARNING) << "madvise failed"; 593c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 594c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 595c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers} 596c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers 5979bdf108885a27ba05fae8501725649574d7c491bVladimir Markobool MemMap::Sync() { 59829ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi bool result; 59929ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi if (redzone_size_ != 0) { 60029ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi // To avoid valgrind errors, temporarily lift the lower-end noaccess protection before passing 60129ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi // it to msync() as it only accepts page-aligned base address, and exclude the higher-end 60229ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi // noaccess protection from the msync range. b/27552451. 60329ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi uint8_t* base_begin = reinterpret_cast<uint8_t*>(base_begin_); 60429ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi MEMORY_TOOL_MAKE_DEFINED(base_begin, begin_ - base_begin); 60529ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi result = msync(BaseBegin(), End() - base_begin, MS_SYNC) == 0; 60629ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi MEMORY_TOOL_MAKE_NOACCESS(base_begin, begin_ - base_begin); 60729ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi } else { 60829ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi result = msync(BaseBegin(), BaseSize(), MS_SYNC) == 0; 60929ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi } 61029ab360433e0360bcccafb791b1231fe63914974Hiroshi Yamauchi return result; 6119bdf108885a27ba05fae8501725649574d7c491bVladimir Marko} 6129bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 613d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chienbool MemMap::Protect(int prot) { 6144fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 6151c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 616d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 617d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 618d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 619d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien if (mprotect(base_begin_, base_size_, prot) == 0) { 6201c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 621d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 622d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 623d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 624a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao PLOG(ERROR) << "mprotect(" << reinterpret_cast<void*>(base_begin_) << ", " << base_size_ << ", " 625a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao << prot << ") failed"; 626d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return false; 627d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien} 628d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 6293eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchibool MemMap::CheckNoGaps(MemMap* begin_map, MemMap* end_map) { 6303eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 6313eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(begin_map != nullptr); 6323eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(end_map != nullptr); 6333eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(HasMemMap(begin_map)); 6343eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(HasMemMap(end_map)); 6353eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK_LE(begin_map->BaseBegin(), end_map->BaseBegin()); 6363eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = begin_map; 6373eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi while (map->BaseBegin() != end_map->BaseBegin()) { 6383eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* next_map = GetLargestMemMapAt(map->BaseEnd()); 6393eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (next_map == nullptr) { 6403eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Found a gap. 6413eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return false; 6423eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6433eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi map = next_map; 6443eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6453eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return true; 6463eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 6473eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 64817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Markovoid MemMap::DumpMaps(std::ostream& os, bool terse) { 6493eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 65017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko DumpMapsLocked(os, terse); 6513eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 6523eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 65317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Markovoid MemMap::DumpMapsLocked(std::ostream& os, bool terse) { 65417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko const auto& mem_maps = *maps_; 65517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko if (!terse) { 65617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << mem_maps; 65717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko return; 65817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 65917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko 66017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // Terse output example: 66117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // [MemMap: 0x409be000+0x20P~0x11dP+0x20P~0x61cP+0x20P prot=0x3 LinearAlloc] 66217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // [MemMap: 0x451d6000+0x6bP(3) prot=0x3 large object space allocation] 66317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // The details: 66417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // "+0x20P" means 0x20 pages taken by a single mapping, 66517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // "~0x11dP" means a gap of 0x11d pages, 66617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // "+0x6bP(3)" means 3 mappings one after another, together taking 0x6b pages. 66717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "MemMap:" << std::endl; 66817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko for (auto it = mem_maps.begin(), maps_end = mem_maps.end(); it != maps_end;) { 66917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko MemMap* map = it->second; 67017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko void* base = it->first; 67117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko CHECK_EQ(base, map->BaseBegin()); 67217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "[MemMap: " << base; 67317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko ++it; 67417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // Merge consecutive maps with the same protect flags and name. 67517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko constexpr size_t kMaxGaps = 9; 67617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size_t num_gaps = 0; 67717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size_t num = 1u; 67817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size_t size = map->BaseSize(); 67914d90579f013b374638b599361970557ed4b3f09Roland Levillain CHECK_ALIGNED(size, kPageSize); 68017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko void* end = map->BaseEnd(); 68117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko while (it != maps_end && 68217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko it->second->GetProtect() == map->GetProtect() && 68317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko it->second->GetName() == map->GetName() && 68417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko (it->second->BaseBegin() == end || num_gaps < kMaxGaps)) { 68517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko if (it->second->BaseBegin() != end) { 68617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko ++num_gaps; 68717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "+0x" << std::hex << (size / kPageSize) << "P"; 68817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko if (num != 1u) { 68917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "(" << std::dec << num << ")"; 69017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 69117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size_t gap = 69217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko reinterpret_cast<uintptr_t>(it->second->BaseBegin()) - reinterpret_cast<uintptr_t>(end); 69314d90579f013b374638b599361970557ed4b3f09Roland Levillain CHECK_ALIGNED(gap, kPageSize); 69417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "~0x" << std::hex << (gap / kPageSize) << "P"; 69517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko num = 0u; 69617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size = 0u; 69717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 69814d90579f013b374638b599361970557ed4b3f09Roland Levillain CHECK_ALIGNED(it->second->BaseSize(), kPageSize); 69917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko ++num; 70017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size += it->second->BaseSize(); 70117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko end = it->second->BaseEnd(); 70217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko ++it; 70317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 70417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "+0x" << std::hex << (size / kPageSize) << "P"; 70517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko if (num != 1u) { 70617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "(" << std::dec << num << ")"; 70717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 70817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << " prot=0x" << std::hex << map->GetProtect() << " " << map->GetName() << "]" << std::endl; 70917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 7103eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 7113eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 7123eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchibool MemMap::HasMemMap(MemMap* map) { 7133eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi void* base_begin = map->BaseBegin(); 7146e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(base_begin), end = maps_->end(); 7153eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == base_begin; ++it) { 7163eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (it->second == map) { 7173eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return true; 7183eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 7193eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 7203eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return false; 7213eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 7223eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 7233eed93dd5be03e5539827bebf0f414251a12e15eHiroshi YamauchiMemMap* MemMap::GetLargestMemMapAt(void* address) { 7243eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi size_t largest_size = 0; 7253eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* largest_map = nullptr; 7266e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 7276e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(address), end = maps_->end(); 7283eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == address; ++it) { 7293eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = it->second; 7303eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(map != nullptr); 7313eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (largest_size < map->BaseSize()) { 7323eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi largest_size = map->BaseSize(); 7333eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi largest_map = map; 7343eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 7353eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 7363eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return largest_map; 7373eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 7383eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 7396e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartiervoid MemMap::Init() { 7406e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 7416e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier if (maps_ == nullptr) { 7426e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier // dex2oat calls MemMap::Init twice since its needed before the runtime is created. 7436e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_ = new Maps; 7446e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier } 7456e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier} 7466e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier 7476e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartiervoid MemMap::Shutdown() { 7486e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 7496e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier delete maps_; 7506e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_ = nullptr; 7516e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier} 7526e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier 753379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartiervoid MemMap::SetSize(size_t new_size) { 754379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier if (new_size == base_size_) { 755379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier return; 756379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier } 757379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier CHECK_ALIGNED(new_size, kPageSize); 758379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier CHECK_EQ(base_size_, size_) << "Unsupported"; 759379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier CHECK_LE(new_size, base_size_); 7601e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_UNDEFINED( 7611e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(BaseBegin()) + 7621e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov new_size), 7631e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov base_size_ - new_size); 764379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier CHECK_EQ(munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(BaseBegin()) + new_size), 765379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier base_size_ - new_size), 0) << new_size << " " << base_size_; 766379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier base_size_ = new_size; 767379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier size_ = new_size; 768379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier} 769379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier 77042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartiervoid* MemMap::MapInternal(void* addr, 77142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier size_t length, 77242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int prot, 77342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int flags, 77442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier int fd, 77542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier off_t offset, 77642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier bool low_4gb) { 77742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier#ifdef __LP64__ 77842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // When requesting low_4g memory and having an expectation, the requested range should fit into 77942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // 4GB. 78042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (low_4gb && ( 78142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Start out of bounds. 78242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier (reinterpret_cast<uintptr_t>(addr) >> 32) != 0 || 78342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // End out of bounds. For simplicity, this will fail for the last page of memory. 78442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier ((reinterpret_cast<uintptr_t>(addr) + length) >> 32) != 0)) { 78542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier LOG(ERROR) << "The requested address space (" << addr << ", " 78642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier << reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) + length) 78742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier << ") cannot fit in low_4gb"; 78842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier return MAP_FAILED; 78942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 79042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier#else 79142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier UNUSED(low_4gb); 79242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier#endif 79342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier DCHECK_ALIGNED(length, kPageSize); 79442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (low_4gb) { 79542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier DCHECK_EQ(flags & MAP_FIXED, 0); 79642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 79742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // TODO: 79842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // A page allocator would be a useful abstraction here, as 79942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // 1) It is doubtful that MAP_32BIT on x86_64 is doing the right job for us 80042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier void* actual = MAP_FAILED; 80142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier#if USE_ART_LOW_4G_ALLOCATOR 80242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // MAP_32BIT only available on x86_64. 80342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (low_4gb && addr == nullptr) { 80442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier bool first_run = true; 80542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 80642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 80742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier for (uintptr_t ptr = next_mem_pos_; ptr < 4 * GB; ptr += kPageSize) { 80842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Use maps_ as an optimization to skip over large maps. 80942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Find the first map which is address > ptr. 81042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier auto it = maps_->upper_bound(reinterpret_cast<void*>(ptr)); 81142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (it != maps_->begin()) { 81242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier auto before_it = it; 81342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier --before_it; 81442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Start at the end of the map before the upper bound. 81542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier ptr = std::max(ptr, reinterpret_cast<uintptr_t>(before_it->second->BaseEnd())); 81642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier CHECK_ALIGNED(ptr, kPageSize); 81742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 81842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier while (it != maps_->end()) { 81942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // How much space do we have until the next map? 82042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier size_t delta = reinterpret_cast<uintptr_t>(it->first) - ptr; 82142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // If the space may be sufficient, break out of the loop. 82242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (delta >= length) { 82342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier break; 82442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 82542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Otherwise, skip to the end of the map. 82642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier ptr = reinterpret_cast<uintptr_t>(it->second->BaseEnd()); 82742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier CHECK_ALIGNED(ptr, kPageSize); 82842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier ++it; 82942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 83042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 83142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Try to see if we get lucky with this address since none of the ART maps overlap. 83242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier actual = TryMemMapLow4GB(reinterpret_cast<void*>(ptr), length, prot, flags, fd, offset); 83342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (actual != MAP_FAILED) { 83442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier next_mem_pos_ = reinterpret_cast<uintptr_t>(actual) + length; 83542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier return actual; 83642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 83742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 83842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (4U * GB - ptr < length) { 83942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Not enough memory until 4GB. 84042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (first_run) { 84142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Try another time from the bottom; 84242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier ptr = LOW_MEM_START - kPageSize; 84342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier first_run = false; 84442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier continue; 84542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } else { 84642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Second try failed. 84742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier break; 84842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 84942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 85042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 85142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier uintptr_t tail_ptr; 85242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 85342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Check pages are free. 85442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier bool safe = true; 85542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier for (tail_ptr = ptr; tail_ptr < ptr + length; tail_ptr += kPageSize) { 85642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (msync(reinterpret_cast<void*>(tail_ptr), kPageSize, 0) == 0) { 85742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier safe = false; 85842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier break; 85942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } else { 86042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier DCHECK_EQ(errno, ENOMEM); 86142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 86242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 86342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 86442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier next_mem_pos_ = tail_ptr; // update early, as we break out when we found and mapped a region 86542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 86642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (safe == true) { 86742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier actual = TryMemMapLow4GB(reinterpret_cast<void*>(ptr), length, prot, flags, fd, offset); 86842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (actual != MAP_FAILED) { 86942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier return actual; 87042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 87142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } else { 87242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier // Skip over last page. 87342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier ptr = tail_ptr; 87442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 87542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 87642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 87742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (actual == MAP_FAILED) { 87842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier LOG(ERROR) << "Could not find contiguous low-memory space."; 87942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier errno = ENOMEM; 88042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 88142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } else { 88242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier actual = mmap(addr, length, prot, flags, fd, offset); 88342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 88442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 88542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier#else 88642bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier#if defined(__LP64__) 88742bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier if (low_4gb && addr == nullptr) { 88842bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier flags |= MAP_32BIT; 88942bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier } 89042bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier#endif 89142bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier actual = mmap(addr, length, prot, flags, fd, offset); 89242bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier#endif 89342bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier return actual; 89442bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier} 89542bddcec51e71d206f6d3b30a881ee6c1d50a63cMathieu Chartier 8960d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstromstd::ostream& operator<<(std::ostream& os, const MemMap& mem_map) { 8973eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << StringPrintf("[MemMap: %p-%p prot=0x%x %s]", 8983eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi mem_map.BaseBegin(), mem_map.BaseEnd(), mem_map.GetProtect(), 8993eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi mem_map.GetName().c_str()); 9000d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return os; 9010d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom} 9020d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom 9036edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchivoid MemMap::TryReadable() { 9046edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 9056edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi return; 9066edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi } 9076edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi CHECK_NE(prot_ & PROT_READ, 0); 9086edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi volatile uint8_t* begin = reinterpret_cast<volatile uint8_t*>(base_begin_); 9096edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi volatile uint8_t* end = begin + base_size_; 9106edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(begin)); 9116edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(end)); 9126edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi // Read the first byte of each page. Use volatile to prevent the compiler from optimizing away the 9136edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi // reads. 9146edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi for (volatile uint8_t* ptr = begin; ptr < end; ptr += kPageSize) { 9156edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi // This read could fault if protection wasn't set correctly. 9166edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi uint8_t value = *ptr; 9176edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi UNUSED(value); 9186edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi } 9196edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi} 9206edb9aecdbe8b31f7ae1d35f21d013631337a424Hiroshi Yamauchi 92127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} // namespace art 922