mem_map.cc revision 1e13374baf7dfaf442ffbf9809c37c131d681eaf
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> 22c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers 23700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory> 24c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include <sstream> 25e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes 26d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// See CreateStartPos below. 27d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 28d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#include <sys/auxv.h> 29d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 30d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 31e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 32277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 33277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic push 34277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic ignored "-Wshadow" 356c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "ScopedFd.h" 36277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic pop 37277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 38c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include "thread-inl.h" 396c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "utils.h" 406c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 416c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#define USE_ASHMEM 1 426c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 436c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 446c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include <cutils/ashmem.h> 45997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#ifndef ANDROID_OS 46997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#include <sys/resource.h> 47997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#endif 486c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 496c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 50d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#ifndef MAP_ANONYMOUS 51d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#define MAP_ANONYMOUS MAP_ANON 52d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#endif 53d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers 5427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstromnamespace art { 5527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 56943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferrisstatic std::ostream& operator<<( 57943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::ostream& os, 58943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::pair<BacktraceMap::const_iterator, BacktraceMap::const_iterator> iters) { 59943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris for (BacktraceMap::const_iterator it = iters.first; it != iters.second; ++it) { 60943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris os << StringPrintf("0x%08x-0x%08x %c%c%c %s\n", 61943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->start), 62943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->end), 63943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_READ) ? 'r' : '-', 64943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_WRITE) ? 'w' : '-', 65943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_EXEC) ? 'x' : '-', it->name.c_str()); 66ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes } 67ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes return os; 6896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes} 6996970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 70bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierstd::ostream& operator<<(std::ostream& os, const MemMap::Maps& mem_maps) { 713eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << "MemMap:" << std::endl; 723eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi for (auto it = mem_maps.begin(); it != mem_maps.end(); ++it) { 733eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi void* base = it->first; 743eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = it->second; 753eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK_EQ(base, map->BaseBegin()); 763eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << *map << std::endl; 773eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 783eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return os; 793eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 803eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 816e88ef6b604a7a945a466784580c42e6554c1289Mathieu ChartierMemMap::Maps* MemMap::maps_ = nullptr; 823eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 83c3ccc1039e0bbc0744f958cb8719cf96bce5b853Ian Rogers#if USE_ART_LOW_4G_ALLOCATOR 84d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Handling mem_map in 32b address range for 64b architectures that do not support MAP_32BIT. 85d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 86d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// The regular start of memory allocations. The first 64KB is protected by SELinux. 876bd621aa31aa94ed42a2a35256d219630bf0b687Andreas Gampestatic constexpr uintptr_t LOW_MEM_START = 64 * KB; 887104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 89d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Generate random starting position. 90d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// To not interfere with image position, take the image's address and only place it below. Current 91d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// formula (sketch): 92d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// 93d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ART_BASE_ADDR = 0001XXXXXXXXXXXXXXX 94d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ---------------------------------------- 95d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// = 0000111111111111111 96d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// & ~(kPageSize - 1) =~0000000000000001111 97d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ---------------------------------------- 98d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// mask = 0000111111111110000 99d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// & random data = YYYYYYYYYYYYYYYYYYY 100d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ----------------------------------- 101d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// tmp = 0000YYYYYYYYYYY0000 102d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// + LOW_MEM_START = 0000000000001000000 103d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// -------------------------------------- 104d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// start 105d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// 106d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// getauxval as an entropy source is exposed in Bionic, but not in glibc before 2.16. When we 107d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// do not have Bionic, simply start with LOW_MEM_START. 108d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 109d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Function is standalone so it can be tested somewhat in mem_map_test.cc. 110d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 111d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampeuintptr_t CreateStartPos(uint64_t input) { 112d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe CHECK_NE(0, ART_BASE_ADDRESS); 113d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 114d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Start with all bits below highest bit in ART_BASE_ADDRESS. 115d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr size_t leading_zeros = CLZ(static_cast<uint32_t>(ART_BASE_ADDRESS)); 116d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr uintptr_t mask_ones = (1 << (31 - leading_zeros)) - 1; 117d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 118d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Lowest (usually 12) bits are not used, as aligned by page size. 119d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr uintptr_t mask = mask_ones & ~(kPageSize - 1); 120d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 121d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Mask input data. 122d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return (input & mask) + LOW_MEM_START; 123d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe} 124d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 125d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 126d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampestatic uintptr_t GenerateNextMemPos() { 127d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 128d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe uint8_t* random_data = reinterpret_cast<uint8_t*>(getauxval(AT_RANDOM)); 129d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // The lower 8B are taken for the stack guard. Use the upper 8B (with mask). 130d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return CreateStartPos(*reinterpret_cast<uintptr_t*>(random_data + 8)); 131d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#else 132d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // No auxv on host, see above. 133d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return LOW_MEM_START; 134d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 135d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe} 136d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 137d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Initialize linear scan to random position. 138d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampeuintptr_t MemMap::next_mem_pos_ = GenerateNextMemPos(); 1398dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#endif 1408dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 141a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// Return true if the address range is contained in a single /proc/self/map entry. 1425c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markostatic bool ContainedWithinExistingMap(uint8_t* ptr, size_t size, 143b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath std::string* error_msg) { 1445c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko uintptr_t begin = reinterpret_cast<uintptr_t>(ptr); 1455c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko uintptr_t end = begin + size; 146a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); 147836572a07142627ff291d686a4e9e03a0988344bChristopher Ferris if (map.get() == nullptr) { 148a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Failed to build process map"); 149a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 150a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 151a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 152a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if ((begin >= it->start && begin < it->end) // start of new within old 153a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo && (end > it->start && end <= it->end)) { // end of new within old 154a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return true; 155a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 156a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 157b5505823ad3d0bab8fc9c15c266a3d8cd96ee59eVladimir Marko PrintFileToLog("/proc/self/maps", LogSeverity::ERROR); 158a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " does not overlap " 159a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe "any existing map. See process maps in the log.", begin, end); 160a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 161a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo} 162a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 163a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// Return true if the address range does not conflict with any /proc/self/maps entry. 164a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guostatic bool CheckNonOverlapping(uintptr_t begin, 165a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t end, 166a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::string* error_msg) { 167a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); 168836572a07142627ff291d686a4e9e03a0988344bChristopher Ferris if (map.get() == nullptr) { 169a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Failed to build process map"); 170a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 171a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 172a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 173a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if ((begin >= it->start && begin < it->end) // start of new within old 174a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo || (end > it->start && end < it->end) // end of new within old 175a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo || (begin <= it->start && end > it->end)) { // start/end of new includes all of old 176a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::ostringstream map_info; 177a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo map_info << std::make_pair(it, map->end()); 178a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " overlaps with " 179a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo "existing map 0x%08" PRIxPTR "-0x%08" PRIxPTR " (%s)\n%s", 180a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo begin, end, 181a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo static_cast<uintptr_t>(it->start), static_cast<uintptr_t>(it->end), 182a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo it->name.c_str(), 183a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo map_info.str().c_str()); 184a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 185a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 186a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 187a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return true; 188a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo} 189a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 190a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// CheckMapRequest to validate a non-MAP_FAILED mmap result based on 191a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// the expected value, calling munmap if validation fails, giving the 192a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// reason in error_msg. 193a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// 1942cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier// If the expected_ptr is null, nothing is checked beyond the fact 195a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// that the actual_ptr is not MAP_FAILED. However, if expected_ptr is 196a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// non-null, we check that pointer is the actual_ptr == expected_ptr, 197a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// and if not, report in error_msg what the conflict mapping was if 198a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// found, or a generic error in other cases. 19913735955f39b3b304c37d2b2840663c131262c18Ian Rogersstatic bool CheckMapRequest(uint8_t* expected_ptr, void* actual_ptr, size_t byte_count, 200a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::string* error_msg) { 2014fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Handled first by caller for more specific error messages. 2024fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(actual_ptr != MAP_FAILED); 2034fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 2044fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == nullptr) { 2054fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 2064fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 2074fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 208a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t actual = reinterpret_cast<uintptr_t>(actual_ptr); 209a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t expected = reinterpret_cast<uintptr_t>(expected_ptr); 210a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t limit = expected + byte_count; 211a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 2124fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == actual_ptr) { 2134fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 2144fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 2154fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 2164fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // We asked for an address but didn't get what we wanted, all paths below here should fail. 2174fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi int result = munmap(actual_ptr, byte_count); 2184fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (result == -1) { 2194fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi PLOG(WARNING) << StringPrintf("munmap(%p, %zd) failed", actual_ptr, byte_count); 22027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 221ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes 222b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // We call this here so that we can try and generate a full error 223b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // message with the overlapping mapping. There's no guarantee that 224b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // that there will be an overlap though, since 2251d8199d8215a6ee7b1904edc47372d83fcdee5a3Kenny Root // - The kernel is not *required* to honor expected_ptr unless MAP_FIXED is 226b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // true, even if there is no overlap 227b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // - There might have been an overlap at the point of mmap, but the 228b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // overlapping region has since been unmapped. 229b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath std::string error_detail; 230b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath CheckNonOverlapping(expected, limit, &error_detail); 231b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath 232b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath std::ostringstream os; 233b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath os << StringPrintf("Failed to mmap at expected address, mapped at " 234b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath "0x%08" PRIxPTR " instead of 0x%08" PRIxPTR, 235b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath actual, expected); 236b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath if (!error_detail.empty()) { 237b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath os << " : " << error_detail; 238943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris } 239a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 240b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath *error_msg = os.str(); 2414fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 24227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 24327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 24438c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier#if USE_ART_LOW_4G_ALLOCATOR 24538c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartierstatic inline void* TryMemMapLow4GB(void* ptr, size_t page_aligned_byte_count, int prot, int flags, 24638c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier int fd) { 24738c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier void* actual = mmap(ptr, page_aligned_byte_count, prot, flags, fd, 0); 24838c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier if (actual != MAP_FAILED) { 24938c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier // Since we didn't use MAP_FIXED the kernel may have mapped it somewhere not in the low 25038c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier // 4GB. If this is the case, unmap and retry. 25138c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier if (reinterpret_cast<uintptr_t>(actual) + page_aligned_byte_count >= 4 * GB) { 25238c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier munmap(actual, page_aligned_byte_count); 25338c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier actual = MAP_FAILED; 25438c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier } 25538c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier } 25638c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier return actual; 25738c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier} 25838c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier#endif 25938c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier 26013735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap* MemMap::MapAnonymous(const char* name, uint8_t* expected_ptr, size_t byte_count, int prot, 2615c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko bool low_4gb, bool reuse, std::string* error_msg) { 2626a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#ifndef __LP64__ 2636a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(low_4gb); 2646a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#endif 2659004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 266a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(name, nullptr, 0, nullptr, 0, prot, false); 2679004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 268ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize); 2696c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 270997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers int flags = MAP_PRIVATE | MAP_ANONYMOUS; 2715c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko if (reuse) { 2725c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko // reuse means it is okay that it overlaps an existing page mapping. 2735c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko // Only use this if you actually made the page reservation yourself. 2745c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko CHECK(expected_ptr != nullptr); 2755c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 276b5505823ad3d0bab8fc9c15c266a3d8cd96ee59eVladimir Marko DCHECK(ContainedWithinExistingMap(expected_ptr, byte_count, error_msg)) << *error_msg; 2775c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko flags |= MAP_FIXED; 2785c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } 2795c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 280997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers ScopedFd fd(-1); 281997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers 2826c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 283997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#ifdef HAVE_ANDROID_OS 284997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers const bool use_ashmem = true; 2856c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#else 286997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // When not on Android ashmem is faked using files in /tmp. Ensure that such files won't 287997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // fail due to ulimit restrictions. If they will then use a regular mmap. 288997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers struct rlimit rlimit_fsize; 289997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers CHECK_EQ(getrlimit(RLIMIT_FSIZE, &rlimit_fsize), 0); 290997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers const bool use_ashmem = (rlimit_fsize.rlim_cur == RLIM_INFINITY) || 291997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers (page_aligned_byte_count < rlimit_fsize.rlim_cur); 292997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#endif 293997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers if (use_ashmem) { 294997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 295997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // prefixed "dalvik-". 296997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers std::string debug_friendly_name("dalvik-"); 297997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers debug_friendly_name += name; 298997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers fd.reset(ashmem_create_region(debug_friendly_name.c_str(), page_aligned_byte_count)); 299997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers if (fd.get() == -1) { 300997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", name, strerror(errno)); 301997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers return nullptr; 302997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers } 3035c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko flags &= ~MAP_ANONYMOUS; 304997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers } 3056c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 3068dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 307aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom // We need to store and potentially set an error number for pretty printing of errors 308aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom int saved_errno = 0; 309aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 31084d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi#ifdef __LP64__ 31184d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // When requesting low_4g memory and having an expectation, the requested range should fit into 31284d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // 4GB. 31384d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi if (low_4gb && ( 31484d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // Start out of bounds. 315a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo (reinterpret_cast<uintptr_t>(expected_ptr) >> 32) != 0 || 31684d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // End out of bounds. For simplicity, this will fail for the last page of memory. 317a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo (reinterpret_cast<uintptr_t>(expected_ptr + page_aligned_byte_count) >> 32) != 0)) { 31884d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi *error_msg = StringPrintf("The requested address space (%p, %p) cannot fit in low_4gb", 319a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo expected_ptr, expected_ptr + page_aligned_byte_count); 32084d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi return nullptr; 32184d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi } 32284d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi#endif 32384d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi 3248dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // TODO: 3258dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // A page allocator would be a useful abstraction here, as 3268dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // 1) It is doubtful that MAP_32BIT on x86_64 is doing the right job for us 3278dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // 2) The linear scheme, even with simple saving of the last known position, is very crude 328c3ccc1039e0bbc0744f958cb8719cf96bce5b853Ian Rogers#if USE_ART_LOW_4G_ALLOCATOR 3298dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // MAP_32BIT only available on x86_64. 3308dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith void* actual = MAP_FAILED; 331a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (low_4gb && expected_ptr == nullptr) { 3327104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe bool first_run = true; 3337104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 3347889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 33571a3ebabb2a6b4921071d115aa176d8222aeb803Andreas Gampe for (uintptr_t ptr = next_mem_pos_; ptr < 4 * GB; ptr += kPageSize) { 3367889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier // Use maps_ as an optimization to skip over large maps. 3377889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier // Find the first map which is address > ptr. 3387889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier auto it = maps_->upper_bound(reinterpret_cast<void*>(ptr)); 3397889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier if (it != maps_->begin()) { 3407889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier auto before_it = it; 3417889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier --before_it; 3427889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier // Start at the end of the map before the upper bound. 3437889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier ptr = std::max(ptr, reinterpret_cast<uintptr_t>(before_it->second->BaseEnd())); 3447889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier CHECK_ALIGNED(ptr, kPageSize); 3457889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier } 3467889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier while (it != maps_->end()) { 3477889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier // How much space do we have until the next map? 3487889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier size_t delta = reinterpret_cast<uintptr_t>(it->first) - ptr; 3497889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier // If the space may be sufficient, break out of the loop. 3507889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier if (delta >= page_aligned_byte_count) { 3517889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier break; 3527889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier } 3537889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier // Otherwise, skip to the end of the map. 3547889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier ptr = reinterpret_cast<uintptr_t>(it->second->BaseEnd()); 3557889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier CHECK_ALIGNED(ptr, kPageSize); 3567889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier ++it; 3577889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier } 3587889a77e464b820745c9507ccd484f68e7b1c650Mathieu Chartier 35938c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier // Try to see if we get lucky with this address since none of the ART maps overlap. 36038c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier actual = TryMemMapLow4GB(reinterpret_cast<void*>(ptr), page_aligned_byte_count, prot, flags, 36138c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier fd.get()); 36238c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier if (actual != MAP_FAILED) { 36338c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier next_mem_pos_ = reinterpret_cast<uintptr_t>(actual) + page_aligned_byte_count; 36438c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier break; 36538c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier } 36638c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier 3677104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe if (4U * GB - ptr < page_aligned_byte_count) { 3687104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Not enough memory until 4GB. 3697104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe if (first_run) { 3707104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Try another time from the bottom; 3719de65ff3a9c49b91d80be292020f012f3d0a24efAndreas Gampe ptr = LOW_MEM_START - kPageSize; 3727104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe first_run = false; 3737104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe continue; 3747104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } else { 3757104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Second try failed. 3767104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe break; 3777104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } 3787104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } 3797104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 3808dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith uintptr_t tail_ptr; 3818dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 3828dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // Check pages are free. 3838dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith bool safe = true; 3848dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith for (tail_ptr = ptr; tail_ptr < ptr + page_aligned_byte_count; tail_ptr += kPageSize) { 3858dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (msync(reinterpret_cast<void*>(tail_ptr), kPageSize, 0) == 0) { 3868dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith safe = false; 3878dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith break; 3888dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 3898dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith DCHECK_EQ(errno, ENOMEM); 3908dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3918dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3928dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 3938dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith next_mem_pos_ = tail_ptr; // update early, as we break out when we found and mapped a region 3948dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 3958dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (safe == true) { 39638c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier actual = TryMemMapLow4GB(reinterpret_cast<void*>(ptr), page_aligned_byte_count, prot, flags, 39738c8221b8f8bd0411006c44d3126f78eb6a8e9abMathieu Chartier fd.get()); 3988dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (actual != MAP_FAILED) { 399c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier break; 4008dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 4018dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 4028dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // Skip over last page. 4038dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith ptr = tail_ptr; 4048dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 4058dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 4068dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 4078dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (actual == MAP_FAILED) { 408aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom LOG(ERROR) << "Could not find contiguous low-memory space."; 409aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = ENOMEM; 4108dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 4118dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 412a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo actual = mmap(expected_ptr, page_aligned_byte_count, prot, flags, fd.get(), 0); 413aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = errno; 4148dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 4158dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 4168dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#else 417c3ccc1039e0bbc0744f958cb8719cf96bce5b853Ian Rogers#if defined(__LP64__) 418a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (low_4gb && expected_ptr == nullptr) { 419ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers flags |= MAP_32BIT; 420ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 421ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 4224fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 423a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo void* actual = mmap(expected_ptr, page_aligned_byte_count, prot, flags, fd.get(), 0); 424aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = errno; 4258dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#endif 4268dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 42727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 428a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 429aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 430a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe *error_msg = StringPrintf("Failed anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0): %s. See process " 431a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe "maps in the log.", expected_ptr, page_aligned_byte_count, prot, 432a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe flags, fd.get(), strerror(saved_errno)); 4334fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 4344fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 4354fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 436a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) { 4378d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers return nullptr; 43827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 43913735955f39b3b304c37d2b2840663c131262c18Ian Rogers return new MemMap(name, reinterpret_cast<uint8_t*>(actual), byte_count, actual, 44001d4b5072c064d927260486c891a09fe689289c0Mathieu Chartier page_aligned_byte_count, prot, reuse); 44127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 44227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 4431baabf0726eb285284e0c908ccba9f209b399faeDavid SrbeckyMemMap* MemMap::MapDummy(const char* name, uint8_t* addr, size_t byte_count) { 4441baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky if (byte_count == 0) { 4451baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky return new MemMap(name, nullptr, 0, nullptr, 0, 0, false); 4461baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky } 4471baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky const size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize); 4481baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky return new MemMap(name, addr, byte_count, addr, page_aligned_byte_count, 0, true /* reuse */); 4491baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky} 4501baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky 4512cebb24bfc3247d3e9be138a3350106737455918Mathieu ChartierMemMap* MemMap::MapFileAtAddress(uint8_t* expected_ptr, size_t byte_count, int prot, int flags, 4522cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier int fd, off_t start, bool reuse, const char* filename, 4538d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg) { 45427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, prot); 45527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, flags & (MAP_SHARED | MAP_PRIVATE)); 456b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath 457b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // Note that we do not allow MAP_FIXED unless reuse == true, i.e we 458b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // expect his mapping to be contained within an existing map. 4594fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (reuse) { 4604fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // reuse means it is okay that it overlaps an existing page mapping. 4614fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Only use this if you actually made the page reservation yourself. 462a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo CHECK(expected_ptr != nullptr); 463b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath 464b5505823ad3d0bab8fc9c15c266a3d8cd96ee59eVladimir Marko DCHECK(ContainedWithinExistingMap(expected_ptr, byte_count, error_msg)) << *error_msg; 4654fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi flags |= MAP_FIXED; 4664fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } else { 4674fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK_EQ(0, flags & MAP_FIXED); 468b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // Don't bother checking for an overlapping region here. We'll 469b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // check this if required after the fact inside CheckMapRequest. 4704fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 4714fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 4729004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 473a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(filename, nullptr, 0, nullptr, 0, prot, false); 4749004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 475f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'offset' to be page-aligned as required by mmap. 47627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom int page_offset = start % kPageSize; 47727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom off_t page_aligned_offset = start - page_offset; 478f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'byte_count' to be page-aligned as we will map this anyway. 479ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count + page_offset, kPageSize); 480a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo // The 'expected_ptr' is modified (if specified, ie non-null) to be page aligned to the file but 481a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo // not necessarily to virtual memory. mmap will page align 'expected' for us. 4822cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier uint8_t* page_aligned_expected = 4832cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier (expected_ptr == nullptr) ? nullptr : (expected_ptr - page_offset); 4844fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 4851e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov size_t redzone_size = 0; 4861e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov if (RUNNING_ON_MEMORY_TOOL && kMemoryToolAddsRedzones && expected_ptr == nullptr) { 4871e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov redzone_size = kPageSize; 4881e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov page_aligned_byte_count += redzone_size; 4891e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov } 4901e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 49113735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(page_aligned_expected, 492ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes page_aligned_byte_count, 49327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom prot, 49427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom flags, 49527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom fd, 49627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom page_aligned_offset)); 49727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 498aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom auto saved_errno = errno; 499aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 500a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 501aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 502c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier *error_msg = StringPrintf("mmap(%p, %zd, 0x%x, 0x%x, %d, %" PRId64 503a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe ") of file '%s' failed: %s. See process maps in the log.", 5044fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi page_aligned_expected, page_aligned_byte_count, prot, flags, fd, 505aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom static_cast<int64_t>(page_aligned_offset), filename, 506a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe strerror(saved_errno)); 5074fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 5084fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 5094fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 510a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) { 5114fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 51227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 5131e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov if (redzone_size != 0) { 5141e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov const uint8_t *real_start = actual + page_offset; 5151e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov const uint8_t *real_end = actual + page_offset + byte_count; 5161e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov const uint8_t *mapping_end = actual + page_aligned_byte_count; 5171e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 5181e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_NOACCESS(actual, real_start - actual); 5191e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_NOACCESS(real_end, mapping_end - real_end); 5201e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov page_aligned_byte_count -= redzone_size; 5211e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov } 5221e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 5230d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return new MemMap(filename, actual + page_offset, byte_count, actual, page_aligned_byte_count, 5241e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov prot, reuse, redzone_size); 52527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 52627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 52727ec961a1da540ba7f16c07a682585ab167317adBrian CarlstromMemMap::~MemMap() { 5284fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 52927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return; 53027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 5311e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 5321e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov // Unlike Valgrind, AddressSanitizer requires that all manually poisoned memory is unpoisoned 5331e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov // before it is returned to the system. 5341e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov if (redzone_size_ != 0) { 5351e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_UNDEFINED( 5361e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov reinterpret_cast<char*>(base_begin_) + base_size_ - redzone_size_, 5371e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov redzone_size_); 5381e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov } 5391e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 540a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!reuse_) { 5411e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_UNDEFINED(base_begin_, base_size_); 542a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo int result = munmap(base_begin_, base_size_); 543a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (result == -1) { 544a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo PLOG(FATAL) << "munmap failed"; 545a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 54627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 5473eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5483eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Remove it from maps_. 5493eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 5503eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi bool found = false; 5516e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 5526e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(base_begin_), end = maps_->end(); 5533eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == base_begin_; ++it) { 5543eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (it->second == this) { 5553eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi found = true; 5566e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_->erase(it); 5573eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi break; 5583eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 5593eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 5603eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(found) << "MemMap not found"; 56127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 56227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 56313735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap::MemMap(const std::string& name, uint8_t* begin, size_t size, void* base_begin, 5641e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov size_t base_size, int prot, bool reuse, size_t redzone_size) 5651c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier : name_(name), begin_(begin), size_(size), base_begin_(base_begin), base_size_(base_size), 5661e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov prot_(prot), reuse_(reuse), redzone_size_(redzone_size) { 5679004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (size_ == 0) { 5684fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ == nullptr); 5694fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ == nullptr); 5709004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_EQ(base_size_, 0U); 5719004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } else { 5724fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ != nullptr); 5734fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ != nullptr); 5749004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_NE(base_size_, 0U); 5753eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5763eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Add it to maps_. 5773eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 5786e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 5796e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_->insert(std::make_pair(base_begin_, this)); 5809004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 581c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampe} 58227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 58313735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap* MemMap::RemapAtEnd(uint8_t* new_end, const char* tail_name, int tail_prot, 584fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string* error_msg) { 585cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_GE(new_end, Begin()); 586cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_LE(new_end, End()); 58713735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK_LE(begin_ + size_, reinterpret_cast<uint8_t*>(base_begin_) + base_size_); 588fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(begin_)); 589fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(base_begin_)); 59013735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK(IsAligned<kPageSize>(reinterpret_cast<uint8_t*>(base_begin_) + base_size_)); 591fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(new_end)); 59213735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* old_end = begin_ + size_; 59313735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* old_base_end = reinterpret_cast<uint8_t*>(base_begin_) + base_size_; 59413735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* new_base_end = new_end; 595fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(new_base_end, old_base_end); 596fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (new_base_end == old_base_end) { 597a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(tail_name, nullptr, 0, nullptr, 0, tail_prot, false); 598fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 59913735955f39b3b304c37d2b2840663c131262c18Ian Rogers size_ = new_end - reinterpret_cast<uint8_t*>(begin_); 60013735955f39b3b304c37d2b2840663c131262c18Ian Rogers base_size_ = new_base_end - reinterpret_cast<uint8_t*>(base_begin_); 60113735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK_LE(begin_ + size_, reinterpret_cast<uint8_t*>(base_begin_) + base_size_); 602fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_size = old_end - new_end; 60313735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* tail_base_begin = new_base_end; 604fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_base_size = old_base_end - new_base_end; 605fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_EQ(tail_base_begin + tail_base_size, old_base_end); 606fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(tail_base_size)); 607fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 608fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#ifdef USE_ASHMEM 609fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 610fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // prefixed "dalvik-". 611fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string debug_friendly_name("dalvik-"); 612fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi debug_friendly_name += tail_name; 613fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ScopedFd fd(ashmem_create_region(debug_friendly_name.c_str(), tail_base_size)); 6148dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith int flags = MAP_PRIVATE | MAP_FIXED; 615fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (fd.get() == -1) { 616fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", 617fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_name, strerror(errno)); 618fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 619fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 620fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#else 621fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ScopedFd fd(-1); 622fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int flags = MAP_PRIVATE | MAP_ANONYMOUS; 623fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#endif 624fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 6251e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov 6261e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_UNDEFINED(tail_base_begin, tail_base_size); 627fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Unmap/map the tail region. 628fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int result = munmap(tail_base_begin, tail_base_size); 629fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (result == -1) { 630a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 631a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe *error_msg = StringPrintf("munmap(%p, %zd) failed for '%s'. See process maps in the log.", 632a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe tail_base_begin, tail_base_size, name_.c_str()); 633fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 634fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 635fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Don't cause memory allocation between the munmap and the mmap 636fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // calls. Otherwise, libc (or something else) might take this memory 637fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // region. Note this isn't perfect as there's no way to prevent 638fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // other threads to try to take this memory region here. 63913735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(tail_base_begin, tail_base_size, tail_prot, 640fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi flags, fd.get(), 0)); 641fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (actual == MAP_FAILED) { 642a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 643a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe *error_msg = StringPrintf("anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0) failed. See process " 644a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe "maps in the log.", tail_base_begin, tail_base_size, tail_prot, flags, 645a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe fd.get()); 646fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 647fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 648a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(tail_name, actual, tail_size, actual, tail_base_size, tail_prot, false); 649cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier} 650d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 651c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogersvoid MemMap::MadviseDontNeedAndZero() { 652c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (base_begin_ != nullptr || base_size_ != 0) { 653c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (!kMadviseZeroes) { 654c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers memset(base_begin_, 0, base_size_); 655c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 656c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers int result = madvise(base_begin_, base_size_, MADV_DONTNEED); 657c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (result == -1) { 658c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers PLOG(WARNING) << "madvise failed"; 659c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 660c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 661c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers} 662c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers 663d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chienbool MemMap::Protect(int prot) { 6644fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 6651c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 666d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 667d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 668d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 669d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien if (mprotect(base_begin_, base_size_, prot) == 0) { 6701c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 671d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 672d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 673d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 674a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao PLOG(ERROR) << "mprotect(" << reinterpret_cast<void*>(base_begin_) << ", " << base_size_ << ", " 675a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao << prot << ") failed"; 676d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return false; 677d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien} 678d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 6793eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchibool MemMap::CheckNoGaps(MemMap* begin_map, MemMap* end_map) { 6803eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 6813eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(begin_map != nullptr); 6823eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(end_map != nullptr); 6833eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(HasMemMap(begin_map)); 6843eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(HasMemMap(end_map)); 6853eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK_LE(begin_map->BaseBegin(), end_map->BaseBegin()); 6863eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = begin_map; 6873eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi while (map->BaseBegin() != end_map->BaseBegin()) { 6883eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* next_map = GetLargestMemMapAt(map->BaseEnd()); 6893eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (next_map == nullptr) { 6903eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Found a gap. 6913eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return false; 6923eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6933eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi map = next_map; 6943eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6953eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return true; 6963eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 6973eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 69817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Markovoid MemMap::DumpMaps(std::ostream& os, bool terse) { 6993eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 70017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko DumpMapsLocked(os, terse); 7013eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 7023eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 70317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Markovoid MemMap::DumpMapsLocked(std::ostream& os, bool terse) { 70417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko const auto& mem_maps = *maps_; 70517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko if (!terse) { 70617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << mem_maps; 70717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko return; 70817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 70917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko 71017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // Terse output example: 71117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // [MemMap: 0x409be000+0x20P~0x11dP+0x20P~0x61cP+0x20P prot=0x3 LinearAlloc] 71217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // [MemMap: 0x451d6000+0x6bP(3) prot=0x3 large object space allocation] 71317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // The details: 71417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // "+0x20P" means 0x20 pages taken by a single mapping, 71517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // "~0x11dP" means a gap of 0x11d pages, 71617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // "+0x6bP(3)" means 3 mappings one after another, together taking 0x6b pages. 71717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "MemMap:" << std::endl; 71817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko for (auto it = mem_maps.begin(), maps_end = mem_maps.end(); it != maps_end;) { 71917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko MemMap* map = it->second; 72017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko void* base = it->first; 72117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko CHECK_EQ(base, map->BaseBegin()); 72217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "[MemMap: " << base; 72317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko ++it; 72417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko // Merge consecutive maps with the same protect flags and name. 72517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko constexpr size_t kMaxGaps = 9; 72617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size_t num_gaps = 0; 72717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size_t num = 1u; 72817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size_t size = map->BaseSize(); 72917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko CHECK(IsAligned<kPageSize>(size)); 73017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko void* end = map->BaseEnd(); 73117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko while (it != maps_end && 73217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko it->second->GetProtect() == map->GetProtect() && 73317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko it->second->GetName() == map->GetName() && 73417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko (it->second->BaseBegin() == end || num_gaps < kMaxGaps)) { 73517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko if (it->second->BaseBegin() != end) { 73617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko ++num_gaps; 73717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "+0x" << std::hex << (size / kPageSize) << "P"; 73817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko if (num != 1u) { 73917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "(" << std::dec << num << ")"; 74017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 74117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size_t gap = 74217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko reinterpret_cast<uintptr_t>(it->second->BaseBegin()) - reinterpret_cast<uintptr_t>(end); 74317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko CHECK(IsAligned<kPageSize>(gap)); 74417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "~0x" << std::hex << (gap / kPageSize) << "P"; 74517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko num = 0u; 74617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size = 0u; 74717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 74817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko CHECK(IsAligned<kPageSize>(it->second->BaseSize())); 74917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko ++num; 75017a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko size += it->second->BaseSize(); 75117a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko end = it->second->BaseEnd(); 75217a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko ++it; 75317a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 75417a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "+0x" << std::hex << (size / kPageSize) << "P"; 75517a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko if (num != 1u) { 75617a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << "(" << std::dec << num << ")"; 75717a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 75817a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko os << " prot=0x" << std::hex << map->GetProtect() << " " << map->GetName() << "]" << std::endl; 75917a924abde2b0f1f37f6008b451a0a75190c71ffVladimir Marko } 7603eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 7613eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 7623eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchibool MemMap::HasMemMap(MemMap* map) { 7633eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi void* base_begin = map->BaseBegin(); 7646e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(base_begin), end = maps_->end(); 7653eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == base_begin; ++it) { 7663eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (it->second == map) { 7673eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return true; 7683eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 7693eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 7703eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return false; 7713eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 7723eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 7733eed93dd5be03e5539827bebf0f414251a12e15eHiroshi YamauchiMemMap* MemMap::GetLargestMemMapAt(void* address) { 7743eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi size_t largest_size = 0; 7753eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* largest_map = nullptr; 7766e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 7776e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(address), end = maps_->end(); 7783eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == address; ++it) { 7793eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = it->second; 7803eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(map != nullptr); 7813eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (largest_size < map->BaseSize()) { 7823eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi largest_size = map->BaseSize(); 7833eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi largest_map = map; 7843eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 7853eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 7863eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return largest_map; 7873eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 7883eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 7896e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartiervoid MemMap::Init() { 7906e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 7916e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier if (maps_ == nullptr) { 7926e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier // dex2oat calls MemMap::Init twice since its needed before the runtime is created. 7936e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_ = new Maps; 7946e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier } 7956e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier} 7966e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier 7976e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartiervoid MemMap::Shutdown() { 7986e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 7996e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier delete maps_; 8006e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_ = nullptr; 8016e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier} 8026e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier 803379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartiervoid MemMap::SetSize(size_t new_size) { 804379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier if (new_size == base_size_) { 805379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier return; 806379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier } 807379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier CHECK_ALIGNED(new_size, kPageSize); 808379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier CHECK_EQ(base_size_, size_) << "Unsupported"; 809379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier CHECK_LE(new_size, base_size_); 8101e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov MEMORY_TOOL_MAKE_UNDEFINED( 8111e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(BaseBegin()) + 8121e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov new_size), 8131e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov base_size_ - new_size); 814379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier CHECK_EQ(munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(BaseBegin()) + new_size), 815379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier base_size_ - new_size), 0) << new_size << " " << base_size_; 816379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier base_size_ = new_size; 817379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier size_ = new_size; 818379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier} 819379d09fe3c3feb7c2a2fb5a3623689b5ace7e79bMathieu Chartier 8200d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstromstd::ostream& operator<<(std::ostream& os, const MemMap& mem_map) { 8213eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << StringPrintf("[MemMap: %p-%p prot=0x%x %s]", 8223eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi mem_map.BaseBegin(), mem_map.BaseEnd(), mem_map.GetProtect(), 8233eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi mem_map.GetName().c_str()); 8240d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return os; 8250d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom} 8260d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom 82727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} // namespace art 828