mem_map.cc revision 6a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866f
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 19943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris#include <backtrace/BacktraceMap.h> 20c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include <inttypes.h> 21c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers 22700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory> 23c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include <sstream> 24e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes 25d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// See CreateStartPos below. 26d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 27d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#include <sys/auxv.h> 28d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 29d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 30e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 316c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "ScopedFd.h" 32c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include "thread-inl.h" 336c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "utils.h" 346c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 356c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#define USE_ASHMEM 1 366c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 376c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 386c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include <cutils/ashmem.h> 39997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#ifndef ANDROID_OS 40997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#include <sys/resource.h> 41997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#endif 426c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 436c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 44d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#ifndef MAP_ANONYMOUS 45d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#define MAP_ANONYMOUS MAP_ANON 46d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers#endif 47d6b6865cf787be8e4548e018762e72c7d1a40e52Ian Rogers 4827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstromnamespace art { 4927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 50943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferrisstatic std::ostream& operator<<( 51943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::ostream& os, 52943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::pair<BacktraceMap::const_iterator, BacktraceMap::const_iterator> iters) { 53943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris for (BacktraceMap::const_iterator it = iters.first; it != iters.second; ++it) { 54943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris os << StringPrintf("0x%08x-0x%08x %c%c%c %s\n", 55943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->start), 56943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->end), 57943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_READ) ? 'r' : '-', 58943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_WRITE) ? 'w' : '-', 59943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_EXEC) ? 'x' : '-', it->name.c_str()); 60ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes } 61ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes return os; 6296970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes} 6396970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 64bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierstd::ostream& operator<<(std::ostream& os, const MemMap::Maps& mem_maps) { 653eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << "MemMap:" << std::endl; 663eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi for (auto it = mem_maps.begin(); it != mem_maps.end(); ++it) { 673eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi void* base = it->first; 683eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = it->second; 693eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK_EQ(base, map->BaseBegin()); 703eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << *map << std::endl; 713eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 723eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return os; 733eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 743eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 756e88ef6b604a7a945a466784580c42e6554c1289Mathieu ChartierMemMap::Maps* MemMap::maps_ = nullptr; 763eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 77c3ccc1039e0bbc0744f958cb8719cf96bce5b853Ian Rogers#if USE_ART_LOW_4G_ALLOCATOR 78d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Handling mem_map in 32b address range for 64b architectures that do not support MAP_32BIT. 79d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 80d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// The regular start of memory allocations. The first 64KB is protected by SELinux. 816bd621aa31aa94ed42a2a35256d219630bf0b687Andreas Gampestatic constexpr uintptr_t LOW_MEM_START = 64 * KB; 827104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 83d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Generate random starting position. 84d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// To not interfere with image position, take the image's address and only place it below. Current 85d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// formula (sketch): 86d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// 87d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ART_BASE_ADDR = 0001XXXXXXXXXXXXXXX 88d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ---------------------------------------- 89d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// = 0000111111111111111 90d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// & ~(kPageSize - 1) =~0000000000000001111 91d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ---------------------------------------- 92d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// mask = 0000111111111110000 93d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// & random data = YYYYYYYYYYYYYYYYYYY 94d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ----------------------------------- 95d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// tmp = 0000YYYYYYYYYYY0000 96d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// + LOW_MEM_START = 0000000000001000000 97d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// -------------------------------------- 98d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// start 99d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// 100d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// getauxval as an entropy source is exposed in Bionic, but not in glibc before 2.16. When we 101d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// do not have Bionic, simply start with LOW_MEM_START. 102d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 103d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Function is standalone so it can be tested somewhat in mem_map_test.cc. 104d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 105d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampeuintptr_t CreateStartPos(uint64_t input) { 106d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe CHECK_NE(0, ART_BASE_ADDRESS); 107d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 108d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Start with all bits below highest bit in ART_BASE_ADDRESS. 109d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr size_t leading_zeros = CLZ(static_cast<uint32_t>(ART_BASE_ADDRESS)); 110d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr uintptr_t mask_ones = (1 << (31 - leading_zeros)) - 1; 111d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 112d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Lowest (usually 12) bits are not used, as aligned by page size. 113d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr uintptr_t mask = mask_ones & ~(kPageSize - 1); 114d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 115d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Mask input data. 116d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return (input & mask) + LOW_MEM_START; 117d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe} 118d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 119d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 120d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampestatic uintptr_t GenerateNextMemPos() { 121d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 122d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe uint8_t* random_data = reinterpret_cast<uint8_t*>(getauxval(AT_RANDOM)); 123d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // The lower 8B are taken for the stack guard. Use the upper 8B (with mask). 124d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return CreateStartPos(*reinterpret_cast<uintptr_t*>(random_data + 8)); 125d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#else 126d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // No auxv on host, see above. 127d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return LOW_MEM_START; 128d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 129d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe} 130d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 131d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Initialize linear scan to random position. 132d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampeuintptr_t MemMap::next_mem_pos_ = GenerateNextMemPos(); 1338dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#endif 1348dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 135a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// Return true if the address range is contained in a single /proc/self/map entry. 136b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamathstatic bool ContainedWithinExistingMap(uintptr_t begin, 137b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath uintptr_t end, 138b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath std::string* error_msg) { 139a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); 140836572a07142627ff291d686a4e9e03a0988344bChristopher Ferris if (map.get() == nullptr) { 141a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Failed to build process map"); 142a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 143a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 144a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 145a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if ((begin >= it->start && begin < it->end) // start of new within old 146a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo && (end > it->start && end <= it->end)) { // end of new within old 147a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return true; 148a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 149a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 150a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::string maps; 151a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo ReadFileToString("/proc/self/maps", &maps); 152a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " does not overlap " 153a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo "any existing map:\n%s\n", 154a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo begin, end, maps.c_str()); 155a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 156a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo} 157a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 158a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// Return true if the address range does not conflict with any /proc/self/maps entry. 159a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guostatic bool CheckNonOverlapping(uintptr_t begin, 160a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t end, 161a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::string* error_msg) { 162a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); 163836572a07142627ff291d686a4e9e03a0988344bChristopher Ferris if (map.get() == nullptr) { 164a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Failed to build process map"); 165a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 166a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 167a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 168a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if ((begin >= it->start && begin < it->end) // start of new within old 169a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo || (end > it->start && end < it->end) // end of new within old 170a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo || (begin <= it->start && end > it->end)) { // start/end of new includes all of old 171a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::ostringstream map_info; 172a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo map_info << std::make_pair(it, map->end()); 173a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo *error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " overlaps with " 174a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo "existing map 0x%08" PRIxPTR "-0x%08" PRIxPTR " (%s)\n%s", 175a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo begin, end, 176a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo static_cast<uintptr_t>(it->start), static_cast<uintptr_t>(it->end), 177a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo it->name.c_str(), 178a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo map_info.str().c_str()); 179a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return false; 180a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 181a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 182a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return true; 183a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo} 184a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 185a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// CheckMapRequest to validate a non-MAP_FAILED mmap result based on 186a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// the expected value, calling munmap if validation fails, giving the 187a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// reason in error_msg. 188a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// 189a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// If the expected_ptr is nullptr, nothing is checked beyond the fact 190a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// that the actual_ptr is not MAP_FAILED. However, if expected_ptr is 191a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// non-null, we check that pointer is the actual_ptr == expected_ptr, 192a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// and if not, report in error_msg what the conflict mapping was if 193a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo// found, or a generic error in other cases. 19413735955f39b3b304c37d2b2840663c131262c18Ian Rogersstatic bool CheckMapRequest(uint8_t* expected_ptr, void* actual_ptr, size_t byte_count, 195a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo std::string* error_msg) { 1964fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Handled first by caller for more specific error messages. 1974fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(actual_ptr != MAP_FAILED); 1984fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 1994fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == nullptr) { 2004fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 2014fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 2024fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 203a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t actual = reinterpret_cast<uintptr_t>(actual_ptr); 204a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t expected = reinterpret_cast<uintptr_t>(expected_ptr); 205a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t limit = expected + byte_count; 206a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 2074fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == actual_ptr) { 2084fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 2094fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 2104fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 2114fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // We asked for an address but didn't get what we wanted, all paths below here should fail. 2124fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi int result = munmap(actual_ptr, byte_count); 2134fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (result == -1) { 2144fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi PLOG(WARNING) << StringPrintf("munmap(%p, %zd) failed", actual_ptr, byte_count); 21527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 216ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes 217b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // We call this here so that we can try and generate a full error 218b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // message with the overlapping mapping. There's no guarantee that 219b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // that there will be an overlap though, since 220b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // - The kernel is not *required* to honour expected_ptr unless MAP_FIXED is 221b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // true, even if there is no overlap 222b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // - There might have been an overlap at the point of mmap, but the 223b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // overlapping region has since been unmapped. 224b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath std::string error_detail; 225b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath CheckNonOverlapping(expected, limit, &error_detail); 226b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath 227b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath std::ostringstream os; 228b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath os << StringPrintf("Failed to mmap at expected address, mapped at " 229b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath "0x%08" PRIxPTR " instead of 0x%08" PRIxPTR, 230b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath actual, expected); 231b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath if (!error_detail.empty()) { 232b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath os << " : " << error_detail; 233943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris } 234a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo 235b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath *error_msg = os.str(); 2364fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 23727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 23827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 23913735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap* MemMap::MapAnonymous(const char* name, uint8_t* expected_ptr, size_t byte_count, int prot, 240ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers bool low_4gb, std::string* error_msg) { 2416a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#ifndef __LP64__ 2426a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(low_4gb); 2436a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#endif 2449004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 245a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(name, nullptr, 0, nullptr, 0, prot, false); 2469004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 247ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize); 2486c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 249997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers int flags = MAP_PRIVATE | MAP_ANONYMOUS; 250997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers ScopedFd fd(-1); 251997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers 2526c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 253997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#ifdef HAVE_ANDROID_OS 254997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers const bool use_ashmem = true; 2556c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#else 256997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // When not on Android ashmem is faked using files in /tmp. Ensure that such files won't 257997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // fail due to ulimit restrictions. If they will then use a regular mmap. 258997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers struct rlimit rlimit_fsize; 259997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers CHECK_EQ(getrlimit(RLIMIT_FSIZE, &rlimit_fsize), 0); 260997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers const bool use_ashmem = (rlimit_fsize.rlim_cur == RLIM_INFINITY) || 261997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers (page_aligned_byte_count < rlimit_fsize.rlim_cur); 262997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers#endif 263997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers if (use_ashmem) { 264997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 265997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers // prefixed "dalvik-". 266997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers std::string debug_friendly_name("dalvik-"); 267997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers debug_friendly_name += name; 268997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers fd.reset(ashmem_create_region(debug_friendly_name.c_str(), page_aligned_byte_count)); 269997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers if (fd.get() == -1) { 270997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", name, strerror(errno)); 271997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers return nullptr; 272997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers } 273997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers flags = MAP_PRIVATE; 274997f0f9e69ce7aee73cebd64be8dc40af9164257Ian Rogers } 2756c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 2768dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 277aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom // We need to store and potentially set an error number for pretty printing of errors 278aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom int saved_errno = 0; 279aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 28084d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi#ifdef __LP64__ 28184d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // When requesting low_4g memory and having an expectation, the requested range should fit into 28284d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // 4GB. 28384d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi if (low_4gb && ( 28484d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // Start out of bounds. 285a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo (reinterpret_cast<uintptr_t>(expected_ptr) >> 32) != 0 || 28684d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // End out of bounds. For simplicity, this will fail for the last page of memory. 287a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo (reinterpret_cast<uintptr_t>(expected_ptr + page_aligned_byte_count) >> 32) != 0)) { 28884d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi *error_msg = StringPrintf("The requested address space (%p, %p) cannot fit in low_4gb", 289a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo expected_ptr, expected_ptr + page_aligned_byte_count); 29084d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi return nullptr; 29184d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi } 29284d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi#endif 29384d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi 2948dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // TODO: 2958dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // A page allocator would be a useful abstraction here, as 2968dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // 1) It is doubtful that MAP_32BIT on x86_64 is doing the right job for us 2978dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // 2) The linear scheme, even with simple saving of the last known position, is very crude 298c3ccc1039e0bbc0744f958cb8719cf96bce5b853Ian Rogers#if USE_ART_LOW_4G_ALLOCATOR 2998dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // MAP_32BIT only available on x86_64. 3008dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith void* actual = MAP_FAILED; 301a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (low_4gb && expected_ptr == nullptr) { 3027104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe bool first_run = true; 3037104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 30471a3ebabb2a6b4921071d115aa176d8222aeb803Andreas Gampe for (uintptr_t ptr = next_mem_pos_; ptr < 4 * GB; ptr += kPageSize) { 3057104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe if (4U * GB - ptr < page_aligned_byte_count) { 3067104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Not enough memory until 4GB. 3077104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe if (first_run) { 3087104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Try another time from the bottom; 3099de65ff3a9c49b91d80be292020f012f3d0a24efAndreas Gampe ptr = LOW_MEM_START - kPageSize; 3107104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe first_run = false; 3117104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe continue; 3127104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } else { 3137104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Second try failed. 3147104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe break; 3157104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } 3167104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } 3177104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 3188dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith uintptr_t tail_ptr; 3198dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 3208dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // Check pages are free. 3218dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith bool safe = true; 3228dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith for (tail_ptr = ptr; tail_ptr < ptr + page_aligned_byte_count; tail_ptr += kPageSize) { 3238dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (msync(reinterpret_cast<void*>(tail_ptr), kPageSize, 0) == 0) { 3248dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith safe = false; 3258dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith break; 3268dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 3278dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith DCHECK_EQ(errno, ENOMEM); 3288dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3298dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3308dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 3318dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith next_mem_pos_ = tail_ptr; // update early, as we break out when we found and mapped a region 3328dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 3338dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (safe == true) { 3348dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith actual = mmap(reinterpret_cast<void*>(ptr), page_aligned_byte_count, prot, flags, fd.get(), 3358dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 0); 3368dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (actual != MAP_FAILED) { 337c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier // Since we didn't use MAP_FIXED the kernel may have mapped it somewhere not in the low 338c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier // 4GB. If this is the case, unmap and retry. 339c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier if (reinterpret_cast<uintptr_t>(actual) + page_aligned_byte_count < 4 * GB) { 340c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier break; 341c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier } else { 342c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier munmap(actual, page_aligned_byte_count); 343c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier actual = MAP_FAILED; 344c355a2a78d6ebdfdb645221275affb9136b4c667Mathieu Chartier } 3458dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3468dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 3478dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // Skip over last page. 3488dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith ptr = tail_ptr; 3498dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3508dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3518dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 3528dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (actual == MAP_FAILED) { 353aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom LOG(ERROR) << "Could not find contiguous low-memory space."; 354aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = ENOMEM; 3558dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3568dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 357a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo actual = mmap(expected_ptr, page_aligned_byte_count, prot, flags, fd.get(), 0); 358aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = errno; 3598dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 3608dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 3618dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#else 362c3ccc1039e0bbc0744f958cb8719cf96bce5b853Ian Rogers#if defined(__LP64__) 363a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (low_4gb && expected_ptr == nullptr) { 364ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers flags |= MAP_32BIT; 365ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 366ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 3674fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 368a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo void* actual = mmap(expected_ptr, page_aligned_byte_count, prot, flags, fd.get(), 0); 369aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = errno; 3708dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#endif 3718dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 37227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 3738161c0336b97e11e02c000af357f8f40de2e23e4jeffhao std::string maps; 3748161c0336b97e11e02c000af357f8f40de2e23e4jeffhao ReadFileToString("/proc/self/maps", &maps); 375aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 3764fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg = StringPrintf("Failed anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0): %s\n%s", 377a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo expected_ptr, page_aligned_byte_count, prot, flags, fd.get(), 378aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom strerror(saved_errno), maps.c_str()); 3794fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 3804fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 3814fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 382a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) { 3838d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers return nullptr; 38427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 38513735955f39b3b304c37d2b2840663c131262c18Ian Rogers return new MemMap(name, reinterpret_cast<uint8_t*>(actual), byte_count, actual, 386a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo page_aligned_byte_count, prot, false); 38727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 38827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 38913735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap* MemMap::MapFileAtAddress(uint8_t* expected_ptr, size_t byte_count, int prot, int flags, int fd, 3908d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers off_t start, bool reuse, const char* filename, 3918d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg) { 39227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, prot); 39327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, flags & (MAP_SHARED | MAP_PRIVATE)); 394a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t expected = reinterpret_cast<uintptr_t>(expected_ptr); 395a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo uintptr_t limit = expected + byte_count; 396b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath 397b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // Note that we do not allow MAP_FIXED unless reuse == true, i.e we 398b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // expect his mapping to be contained within an existing map. 3994fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (reuse) { 4004fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // reuse means it is okay that it overlaps an existing page mapping. 4014fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Only use this if you actually made the page reservation yourself. 402a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo CHECK(expected_ptr != nullptr); 403b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath 404b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath DCHECK(ContainedWithinExistingMap(expected, limit, error_msg)); 4054fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi flags |= MAP_FIXED; 4064fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } else { 4074fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK_EQ(0, flags & MAP_FIXED); 408b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // Don't bother checking for an overlapping region here. We'll 409b89c3da592de1a2741a08cc3c8ed2908e8bdd15aNarayan Kamath // check this if required after the fact inside CheckMapRequest. 4104fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 4114fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 4129004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 413a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(filename, nullptr, 0, nullptr, 0, prot, false); 4149004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 415f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'offset' to be page-aligned as required by mmap. 41627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom int page_offset = start % kPageSize; 41727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom off_t page_aligned_offset = start - page_offset; 418f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'byte_count' to be page-aligned as we will map this anyway. 419ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count + page_offset, kPageSize); 420a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo // The 'expected_ptr' is modified (if specified, ie non-null) to be page aligned to the file but 421a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo // not necessarily to virtual memory. mmap will page align 'expected' for us. 42213735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* page_aligned_expected = (expected_ptr == nullptr) ? nullptr : (expected_ptr - page_offset); 4234fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 42413735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(page_aligned_expected, 425ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes page_aligned_byte_count, 42627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom prot, 42727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom flags, 42827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom fd, 42927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom page_aligned_offset)); 43027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 431aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom auto saved_errno = errno; 432aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 4338161c0336b97e11e02c000af357f8f40de2e23e4jeffhao std::string maps; 4348161c0336b97e11e02c000af357f8f40de2e23e4jeffhao ReadFileToString("/proc/self/maps", &maps); 435aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 436c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier *error_msg = StringPrintf("mmap(%p, %zd, 0x%x, 0x%x, %d, %" PRId64 437c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier ") of file '%s' failed: %s\n%s", 4384fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi page_aligned_expected, page_aligned_byte_count, prot, flags, fd, 439aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom static_cast<int64_t>(page_aligned_offset), filename, 440aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom strerror(saved_errno), maps.c_str()); 4414fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 4424fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 4434fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 444a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) { 4454fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 44627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 4470d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return new MemMap(filename, actual + page_offset, byte_count, actual, page_aligned_byte_count, 448a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo prot, reuse); 44927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 45027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 45127ec961a1da540ba7f16c07a682585ab167317adBrian CarlstromMemMap::~MemMap() { 4524fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 45327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return; 45427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 455a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (!reuse_) { 456a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo int result = munmap(base_begin_, base_size_); 457a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo if (result == -1) { 458a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo PLOG(FATAL) << "munmap failed"; 459a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo } 46027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 4613eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 4623eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Remove it from maps_. 4633eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 4643eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi bool found = false; 4656e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 4666e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(base_begin_), end = maps_->end(); 4673eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == base_begin_; ++it) { 4683eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (it->second == this) { 4693eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi found = true; 4706e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_->erase(it); 4713eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi break; 4723eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 4733eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 4743eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(found) << "MemMap not found"; 47527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 47627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 47713735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap::MemMap(const std::string& name, uint8_t* begin, size_t size, void* base_begin, 478a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo size_t base_size, int prot, bool reuse) 4791c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier : name_(name), begin_(begin), size_(size), base_begin_(base_begin), base_size_(base_size), 480a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo prot_(prot), reuse_(reuse) { 4819004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (size_ == 0) { 4824fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ == nullptr); 4834fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ == nullptr); 4849004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_EQ(base_size_, 0U); 4859004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } else { 4864fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ != nullptr); 4874fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ != nullptr); 4889004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_NE(base_size_, 0U); 4893eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 4903eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Add it to maps_. 4913eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 4926e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 4936e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_->insert(std::make_pair(base_begin_, this)); 4949004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 495c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampe} 49627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 49713735955f39b3b304c37d2b2840663c131262c18Ian RogersMemMap* MemMap::RemapAtEnd(uint8_t* new_end, const char* tail_name, int tail_prot, 498fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string* error_msg) { 499cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_GE(new_end, Begin()); 500cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_LE(new_end, End()); 50113735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK_LE(begin_ + size_, reinterpret_cast<uint8_t*>(base_begin_) + base_size_); 502fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(begin_)); 503fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(base_begin_)); 50413735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK(IsAligned<kPageSize>(reinterpret_cast<uint8_t*>(base_begin_) + base_size_)); 505fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(new_end)); 50613735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* old_end = begin_ + size_; 50713735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* old_base_end = reinterpret_cast<uint8_t*>(base_begin_) + base_size_; 50813735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* new_base_end = new_end; 509fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(new_base_end, old_base_end); 510fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (new_base_end == old_base_end) { 511a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(tail_name, nullptr, 0, nullptr, 0, tail_prot, false); 512fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 51313735955f39b3b304c37d2b2840663c131262c18Ian Rogers size_ = new_end - reinterpret_cast<uint8_t*>(begin_); 51413735955f39b3b304c37d2b2840663c131262c18Ian Rogers base_size_ = new_base_end - reinterpret_cast<uint8_t*>(base_begin_); 51513735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK_LE(begin_ + size_, reinterpret_cast<uint8_t*>(base_begin_) + base_size_); 516fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_size = old_end - new_end; 51713735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* tail_base_begin = new_base_end; 518fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_base_size = old_base_end - new_base_end; 519fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_EQ(tail_base_begin + tail_base_size, old_base_end); 520fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(tail_base_size)); 521fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 522fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#ifdef USE_ASHMEM 523fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 524fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // prefixed "dalvik-". 525fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string debug_friendly_name("dalvik-"); 526fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi debug_friendly_name += tail_name; 527fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ScopedFd fd(ashmem_create_region(debug_friendly_name.c_str(), tail_base_size)); 5288dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith int flags = MAP_PRIVATE | MAP_FIXED; 529fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (fd.get() == -1) { 530fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", 531fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_name, strerror(errno)); 532fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 533fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 534fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#else 535fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ScopedFd fd(-1); 536fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int flags = MAP_PRIVATE | MAP_ANONYMOUS; 537fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#endif 538fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 539fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Unmap/map the tail region. 540fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int result = munmap(tail_base_begin, tail_base_size); 541fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (result == -1) { 542fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string maps; 543fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ReadFileToString("/proc/self/maps", &maps); 544fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi *error_msg = StringPrintf("munmap(%p, %zd) failed for '%s'\n%s", 545fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_base_begin, tail_base_size, name_.c_str(), 546fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi maps.c_str()); 547fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 548fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 549fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Don't cause memory allocation between the munmap and the mmap 550fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // calls. Otherwise, libc (or something else) might take this memory 551fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // region. Note this isn't perfect as there's no way to prevent 552fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // other threads to try to take this memory region here. 55313735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(tail_base_begin, tail_base_size, tail_prot, 554fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi flags, fd.get(), 0)); 555fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (actual == MAP_FAILED) { 556fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string maps; 557fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ReadFileToString("/proc/self/maps", &maps); 558c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier *error_msg = StringPrintf("anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0) failed\n%s", 559fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_base_begin, tail_base_size, tail_prot, flags, fd.get(), 560fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi maps.c_str()); 561fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 562fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 563a62a588a9202f69e53fbeb3045ea8ea5ec2587f8Jim_Guo return new MemMap(tail_name, actual, tail_size, actual, tail_base_size, tail_prot, false); 564cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier} 565d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 566c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogersvoid MemMap::MadviseDontNeedAndZero() { 567c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (base_begin_ != nullptr || base_size_ != 0) { 568c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (!kMadviseZeroes) { 569c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers memset(base_begin_, 0, base_size_); 570c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 571c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers int result = madvise(base_begin_, base_size_, MADV_DONTNEED); 572c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers if (result == -1) { 573c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers PLOG(WARNING) << "madvise failed"; 574c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 575c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers } 576c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers} 577c5f17732d8144491c642776b6b48c85dfadf4b52Ian Rogers 578d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chienbool MemMap::Protect(int prot) { 5794fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 5801c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 581d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 582d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 583d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 584d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien if (mprotect(base_begin_, base_size_, prot) == 0) { 5851c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 586d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 587d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 588d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 589a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao PLOG(ERROR) << "mprotect(" << reinterpret_cast<void*>(base_begin_) << ", " << base_size_ << ", " 590a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao << prot << ") failed"; 591d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return false; 592d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien} 593d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 5943eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchibool MemMap::CheckNoGaps(MemMap* begin_map, MemMap* end_map) { 5953eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 5963eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(begin_map != nullptr); 5973eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(end_map != nullptr); 5983eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(HasMemMap(begin_map)); 5993eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(HasMemMap(end_map)); 6003eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK_LE(begin_map->BaseBegin(), end_map->BaseBegin()); 6013eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = begin_map; 6023eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi while (map->BaseBegin() != end_map->BaseBegin()) { 6033eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* next_map = GetLargestMemMapAt(map->BaseEnd()); 6043eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (next_map == nullptr) { 6053eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Found a gap. 6063eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return false; 6073eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6083eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi map = next_map; 6093eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6103eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return true; 6113eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 6123eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 6133eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchivoid MemMap::DumpMaps(std::ostream& os) { 6143eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 615bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier DumpMapsLocked(os); 6163eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 6173eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 618bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiervoid MemMap::DumpMapsLocked(std::ostream& os) { 619bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier os << maps_; 6203eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 6213eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 6223eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchibool MemMap::HasMemMap(MemMap* map) { 6233eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi void* base_begin = map->BaseBegin(); 6246e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(base_begin), end = maps_->end(); 6253eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == base_begin; ++it) { 6263eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (it->second == map) { 6273eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return true; 6283eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6293eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6303eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return false; 6313eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 6323eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 6333eed93dd5be03e5539827bebf0f414251a12e15eHiroshi YamauchiMemMap* MemMap::GetLargestMemMapAt(void* address) { 6343eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi size_t largest_size = 0; 6353eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* largest_map = nullptr; 6366e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier DCHECK(maps_ != nullptr); 6376e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier for (auto it = maps_->lower_bound(address), end = maps_->end(); 6383eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == address; ++it) { 6393eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = it->second; 6403eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(map != nullptr); 6413eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (largest_size < map->BaseSize()) { 6423eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi largest_size = map->BaseSize(); 6433eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi largest_map = map; 6443eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6453eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 6463eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return largest_map; 6473eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 6483eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 6496e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartiervoid MemMap::Init() { 6506e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 6516e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier if (maps_ == nullptr) { 6526e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier // dex2oat calls MemMap::Init twice since its needed before the runtime is created. 6536e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_ = new Maps; 6546e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier } 6556e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier} 6566e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier 6576e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartiervoid MemMap::Shutdown() { 6586e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 6596e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier delete maps_; 6606e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier maps_ = nullptr; 6616e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier} 6626e88ef6b604a7a945a466784580c42e6554c1289Mathieu Chartier 6630d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstromstd::ostream& operator<<(std::ostream& os, const MemMap& mem_map) { 6643eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << StringPrintf("[MemMap: %p-%p prot=0x%x %s]", 6653eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi mem_map.BaseBegin(), mem_map.BaseEnd(), mem_map.GetProtect(), 6663eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi mem_map.GetName().c_str()); 6670d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return os; 6680d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom} 6690d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom 67027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} // namespace art 671