mem_map.cc revision 3eed93dd5be03e5539827bebf0f414251a12e15e
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" 183eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi#include "thread-inl.h" 1927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 20debeb3aaaa4257684029f15733dc30af5dcb8aabIan Rogers#include <inttypes.h> 21943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris#include <backtrace/BacktraceMap.h> 22700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory> 23e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes 24d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// See CreateStartPos below. 25d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 26d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#include <sys/auxv.h> 27d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 28d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 29e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 306c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "ScopedFd.h" 316c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "utils.h" 326c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 336c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#define USE_ASHMEM 1 346c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 356c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 366c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include <cutils/ashmem.h> 376c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 386c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 3927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstromnamespace art { 4027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 41943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferrisstatic std::ostream& operator<<( 42943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::ostream& os, 43943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::pair<BacktraceMap::const_iterator, BacktraceMap::const_iterator> iters) { 44943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris for (BacktraceMap::const_iterator it = iters.first; it != iters.second; ++it) { 45943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris os << StringPrintf("0x%08x-0x%08x %c%c%c %s\n", 46943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->start), 47943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->end), 48943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_READ) ? 'r' : '-', 49943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_WRITE) ? 'w' : '-', 50943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_EXEC) ? 'x' : '-', it->name.c_str()); 51ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes } 52ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes return os; 5396970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes} 5496970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 553eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchistd::ostream& operator<<(std::ostream& os, const std::multimap<void*, MemMap*>& mem_maps) { 563eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << "MemMap:" << std::endl; 573eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi for (auto it = mem_maps.begin(); it != mem_maps.end(); ++it) { 583eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi void* base = it->first; 593eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = it->second; 603eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK_EQ(base, map->BaseBegin()); 613eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << *map << std::endl; 623eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 633eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return os; 643eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 653eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 663eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchistd::multimap<void*, MemMap*> MemMap::maps_; 673eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 688dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#if defined(__LP64__) && !defined(__x86_64__) 69d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Handling mem_map in 32b address range for 64b architectures that do not support MAP_32BIT. 70d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 71d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// The regular start of memory allocations. The first 64KB is protected by SELinux. 726bd621aa31aa94ed42a2a35256d219630bf0b687Andreas Gampestatic constexpr uintptr_t LOW_MEM_START = 64 * KB; 737104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 74d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Generate random starting position. 75d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// To not interfere with image position, take the image's address and only place it below. Current 76d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// formula (sketch): 77d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// 78d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ART_BASE_ADDR = 0001XXXXXXXXXXXXXXX 79d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ---------------------------------------- 80d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// = 0000111111111111111 81d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// & ~(kPageSize - 1) =~0000000000000001111 82d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ---------------------------------------- 83d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// mask = 0000111111111110000 84d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// & random data = YYYYYYYYYYYYYYYYYYY 85d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// ----------------------------------- 86d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// tmp = 0000YYYYYYYYYYY0000 87d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// + LOW_MEM_START = 0000000000001000000 88d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// -------------------------------------- 89d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// start 90d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// 91d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// getauxval as an entropy source is exposed in Bionic, but not in glibc before 2.16. When we 92d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// do not have Bionic, simply start with LOW_MEM_START. 93d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 94d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Function is standalone so it can be tested somewhat in mem_map_test.cc. 95d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 96d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampeuintptr_t CreateStartPos(uint64_t input) { 97d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe CHECK_NE(0, ART_BASE_ADDRESS); 98d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 99d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Start with all bits below highest bit in ART_BASE_ADDRESS. 100d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr size_t leading_zeros = CLZ(static_cast<uint32_t>(ART_BASE_ADDRESS)); 101d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr uintptr_t mask_ones = (1 << (31 - leading_zeros)) - 1; 102d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 103d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Lowest (usually 12) bits are not used, as aligned by page size. 104d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe constexpr uintptr_t mask = mask_ones & ~(kPageSize - 1); 105d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 106d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // Mask input data. 107d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return (input & mask) + LOW_MEM_START; 108d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe} 109d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 110d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 111d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampestatic uintptr_t GenerateNextMemPos() { 112d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#ifdef __BIONIC__ 113d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe uint8_t* random_data = reinterpret_cast<uint8_t*>(getauxval(AT_RANDOM)); 114d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // The lower 8B are taken for the stack guard. Use the upper 8B (with mask). 115d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return CreateStartPos(*reinterpret_cast<uintptr_t*>(random_data + 8)); 116d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#else 117d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe // No auxv on host, see above. 118d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe return LOW_MEM_START; 119d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe#endif 120d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe} 121d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe 122d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampe// Initialize linear scan to random position. 123d8f26dbebe72c1cbdfa85bdeeb003283c7435db3Andreas Gampeuintptr_t MemMap::next_mem_pos_ = GenerateNextMemPos(); 1248dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#endif 1258dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 1264fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchistatic bool CheckMapRequest(byte* expected_ptr, void* actual_ptr, size_t byte_count, 1274fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream* error_msg) { 1284fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Handled first by caller for more specific error messages. 1294fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(actual_ptr != MAP_FAILED); 1304fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 1314fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == nullptr) { 1324fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 1334fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 1344fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 1354fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == actual_ptr) { 1364fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 1374fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 1384fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 1394fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // We asked for an address but didn't get what we wanted, all paths below here should fail. 1404fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi int result = munmap(actual_ptr, byte_count); 1414fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (result == -1) { 1424fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi PLOG(WARNING) << StringPrintf("munmap(%p, %zd) failed", actual_ptr, byte_count); 14327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 144ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes 1454fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi uintptr_t actual = reinterpret_cast<uintptr_t>(actual_ptr); 1464fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi uintptr_t expected = reinterpret_cast<uintptr_t>(expected_ptr); 1474fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi uintptr_t limit = expected + byte_count; 148ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes 149700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid())); 150caf22aca3482e2fcc8bf443f911718a5021da1c9Christopher Ferris if (!map->Build()) { 1514fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg << StringPrintf("Failed to build process map to determine why mmap returned " 1524fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi "0x%08" PRIxPTR " instead of 0x%08" PRIxPTR, actual, expected); 1534fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 1544fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 155943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris } 156caf22aca3482e2fcc8bf443f911718a5021da1c9Christopher Ferris for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 1574fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if ((expected >= it->start && expected < it->end) // start of new within old 1584fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi || (limit > it->start && limit < it->end) // end of new within old 1594fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi || (expected <= it->start && limit > it->end)) { // start/end of new includes all of old 1604fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg 1614fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi << StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " overlaps with " 1624fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi "existing map 0x%08" PRIxPTR "-0x%08" PRIxPTR " (%s)\n", 1634fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi expected, limit, 1644fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi static_cast<uintptr_t>(it->start), static_cast<uintptr_t>(it->end), 1654fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi it->name.c_str()) 1664fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi << std::make_pair(it, map->end()); 1674fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 1684fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 16996970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes } 1704fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg << StringPrintf("Failed to mmap at expected address, mapped at " 1714fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi "0x%08" PRIxPTR " instead of 0x%08" PRIxPTR, actual, expected); 1724fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 17327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 17427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 1754fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi YamauchiMemMap* MemMap::MapAnonymous(const char* name, byte* expected, size_t byte_count, int prot, 176ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers bool low_4gb, std::string* error_msg) { 1779004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 1784fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return new MemMap(name, nullptr, 0, nullptr, 0, prot); 1799004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 180ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize); 1816c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 1826c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 183a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 184a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers // prefixed "dalvik-". 185a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers std::string debug_friendly_name("dalvik-"); 186a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers debug_friendly_name += name; 187a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers ScopedFd fd(ashmem_create_region(debug_friendly_name.c_str(), page_aligned_byte_count)); 1886c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes if (fd.get() == -1) { 1898d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", name, strerror(errno)); 1908d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers return nullptr; 1916c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes } 1924fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi int flags = MAP_PRIVATE; 1936c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#else 1946c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes ScopedFd fd(-1); 1956c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes int flags = MAP_PRIVATE | MAP_ANONYMOUS; 1966c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 1978dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 198aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom // We need to store and potentially set an error number for pretty printing of errors 199aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom int saved_errno = 0; 200aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 20184d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi#ifdef __LP64__ 20284d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // When requesting low_4g memory and having an expectation, the requested range should fit into 20384d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // 4GB. 20484d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi if (low_4gb && ( 20584d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // Start out of bounds. 20684d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi (reinterpret_cast<uintptr_t>(expected) >> 32) != 0 || 20784d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi // End out of bounds. For simplicity, this will fail for the last page of memory. 20884d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi (reinterpret_cast<uintptr_t>(expected + page_aligned_byte_count) >> 32) != 0)) { 20984d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi *error_msg = StringPrintf("The requested address space (%p, %p) cannot fit in low_4gb", 21084d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi expected, expected + page_aligned_byte_count); 21184d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi return nullptr; 21284d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi } 21384d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi#endif 21484d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi 2158dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // TODO: 2168dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // A page allocator would be a useful abstraction here, as 2178dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // 1) It is doubtful that MAP_32BIT on x86_64 is doing the right job for us 2188dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // 2) The linear scheme, even with simple saving of the last known position, is very crude 2198dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#if defined(__LP64__) && !defined(__x86_64__) 2208dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // MAP_32BIT only available on x86_64. 2218dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith void* actual = MAP_FAILED; 2228dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (low_4gb && expected == nullptr) { 2238dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith flags |= MAP_FIXED; 2248dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 2257104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe bool first_run = true; 2267104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 22771a3ebabb2a6b4921071d115aa176d8222aeb803Andreas Gampe for (uintptr_t ptr = next_mem_pos_; ptr < 4 * GB; ptr += kPageSize) { 2287104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe if (4U * GB - ptr < page_aligned_byte_count) { 2297104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Not enough memory until 4GB. 2307104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe if (first_run) { 2317104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Try another time from the bottom; 2329de65ff3a9c49b91d80be292020f012f3d0a24efAndreas Gampe ptr = LOW_MEM_START - kPageSize; 2337104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe first_run = false; 2347104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe continue; 2357104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } else { 2367104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe // Second try failed. 2377104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe break; 2387104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } 2397104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe } 2407104cbf9c594563c6daae592b8f38f49a423d12eAndreas Gampe 2418dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith uintptr_t tail_ptr; 2428dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 2438dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // Check pages are free. 2448dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith bool safe = true; 2458dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith for (tail_ptr = ptr; tail_ptr < ptr + page_aligned_byte_count; tail_ptr += kPageSize) { 2468dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (msync(reinterpret_cast<void*>(tail_ptr), kPageSize, 0) == 0) { 2478dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith safe = false; 2488dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith break; 2498dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 2508dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith DCHECK_EQ(errno, ENOMEM); 2518dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 2528dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 2538dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 2548dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith next_mem_pos_ = tail_ptr; // update early, as we break out when we found and mapped a region 2558dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 2568dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (safe == true) { 2578dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith actual = mmap(reinterpret_cast<void*>(ptr), page_aligned_byte_count, prot, flags, fd.get(), 2588dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 0); 2598dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (actual != MAP_FAILED) { 2608dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith break; 2618dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 2628dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 2638dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith // Skip over last page. 2648dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith ptr = tail_ptr; 2658dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 2668dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 2678dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 2688dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith if (actual == MAP_FAILED) { 269aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom LOG(ERROR) << "Could not find contiguous low-memory space."; 270aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = ENOMEM; 2718dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 2728dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } else { 2738dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith actual = mmap(expected, page_aligned_byte_count, prot, flags, fd.get(), 0); 274aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = errno; 2758dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith } 2768dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 2778dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#else 2788dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#ifdef __x86_64__ 27984d49ccd79088eb9a9f423c0a96e3905468cfe7dQiming Shi if (low_4gb && expected == nullptr) { 280ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers flags |= MAP_32BIT; 281ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 282ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 2834fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 2844fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi void* actual = mmap(expected, page_aligned_byte_count, prot, flags, fd.get(), 0); 285aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom saved_errno = errno; 2868dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith#endif 2878dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith 28827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 2898161c0336b97e11e02c000af357f8f40de2e23e4jeffhao std::string maps; 2908161c0336b97e11e02c000af357f8f40de2e23e4jeffhao ReadFileToString("/proc/self/maps", &maps); 291aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 2924fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg = StringPrintf("Failed anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0): %s\n%s", 2934fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi expected, page_aligned_byte_count, prot, flags, fd.get(), 294aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom strerror(saved_errno), maps.c_str()); 2954fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 2964fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 2974fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 2984fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (!CheckMapRequest(expected, actual, page_aligned_byte_count, &check_map_request_error_msg)) { 2994fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg = check_map_request_error_msg.str(); 3008d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers return nullptr; 30127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 3024fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return new MemMap(name, reinterpret_cast<byte*>(actual), byte_count, actual, 3034fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi page_aligned_byte_count, prot); 30427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 30527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 3064fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi YamauchiMemMap* MemMap::MapFileAtAddress(byte* expected, size_t byte_count, int prot, int flags, int fd, 3078d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers off_t start, bool reuse, const char* filename, 3088d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg) { 30927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, prot); 31027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, flags & (MAP_SHARED | MAP_PRIVATE)); 3114fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (reuse) { 3124fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // reuse means it is okay that it overlaps an existing page mapping. 3134fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Only use this if you actually made the page reservation yourself. 3144fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(expected != nullptr); 3154fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi flags |= MAP_FIXED; 3164fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } else { 3174fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK_EQ(0, flags & MAP_FIXED); 3184fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 3194fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 3209004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 3214fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return new MemMap(filename, nullptr, 0, nullptr, 0, prot); 3229004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 323f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'offset' to be page-aligned as required by mmap. 32427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom int page_offset = start % kPageSize; 32527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom off_t page_aligned_offset = start - page_offset; 326f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'byte_count' to be page-aligned as we will map this anyway. 327ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count + page_offset, kPageSize); 3284fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // The 'expected' is modified (if specified, ie non-null) to be page aligned to the file but not 3294fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // necessarily to virtual memory. mmap will page align 'expected' for us. 3304fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi byte* page_aligned_expected = (expected == nullptr) ? nullptr : (expected - page_offset); 3314fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 3324fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi byte* actual = reinterpret_cast<byte*>(mmap(page_aligned_expected, 333ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes page_aligned_byte_count, 33427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom prot, 33527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom flags, 33627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom fd, 33727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom page_aligned_offset)); 33827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 339aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom auto saved_errno = errno; 340aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 3418161c0336b97e11e02c000af357f8f40de2e23e4jeffhao std::string maps; 3428161c0336b97e11e02c000af357f8f40de2e23e4jeffhao ReadFileToString("/proc/self/maps", &maps); 343aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom 344c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier *error_msg = StringPrintf("mmap(%p, %zd, 0x%x, 0x%x, %d, %" PRId64 345c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier ") of file '%s' failed: %s\n%s", 3464fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi page_aligned_expected, page_aligned_byte_count, prot, flags, fd, 347aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom static_cast<int64_t>(page_aligned_offset), filename, 348aa94cf3e77035bf204a21d0341d8f8513a19885cBrian Carlstrom strerror(saved_errno), maps.c_str()); 3494fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 3504fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 3514fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 3524fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (!CheckMapRequest(expected, actual, page_aligned_byte_count, &check_map_request_error_msg)) { 3534fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg = check_map_request_error_msg.str(); 3544fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 35527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 3560d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return new MemMap(filename, actual + page_offset, byte_count, actual, page_aligned_byte_count, 3571c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier prot); 35827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 35927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 36027ec961a1da540ba7f16c07a682585ab167317adBrian CarlstromMemMap::~MemMap() { 3614fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 36227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return; 36327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 36430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers int result = munmap(base_begin_, base_size_); 36527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (result == -1) { 36627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom PLOG(FATAL) << "munmap failed"; 36727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 3683eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 3693eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Remove it from maps_. 3703eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 3713eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi bool found = false; 3723eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi for (auto it = maps_.lower_bound(base_begin_), end = maps_.end(); 3733eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == base_begin_; ++it) { 3743eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (it->second == this) { 3753eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi found = true; 3763eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi maps_.erase(it); 3773eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi break; 3783eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 3793eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 3803eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(found) << "MemMap not found"; 38127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 38227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 3831c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu ChartierMemMap::MemMap(const std::string& name, byte* begin, size_t size, void* base_begin, 3841c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier size_t base_size, int prot) 3851c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier : name_(name), begin_(begin), size_(size), base_begin_(base_begin), base_size_(base_size), 3861c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier prot_(prot) { 3879004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (size_ == 0) { 3884fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ == nullptr); 3894fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ == nullptr); 3909004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_EQ(base_size_, 0U); 3919004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } else { 3924fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ != nullptr); 3934fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ != nullptr); 3949004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_NE(base_size_, 0U); 3953eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 3963eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Add it to maps_. 3973eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 3983eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi maps_.insert(std::pair<void*, MemMap*>(base_begin_, this)); 3999004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 40027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom}; 40127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 402fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi YamauchiMemMap* MemMap::RemapAtEnd(byte* new_end, const char* tail_name, int tail_prot, 403fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string* error_msg) { 404cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_GE(new_end, Begin()); 405cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_LE(new_end, End()); 406fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(begin_ + size_, reinterpret_cast<byte*>(base_begin_) + base_size_); 407fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(begin_)); 408fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(base_begin_)); 409fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(reinterpret_cast<byte*>(base_begin_) + base_size_)); 410fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(new_end)); 411fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* old_end = begin_ + size_; 412fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* old_base_end = reinterpret_cast<byte*>(base_begin_) + base_size_; 413fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* new_base_end = new_end; 414fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(new_base_end, old_base_end); 415fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (new_base_end == old_base_end) { 4164fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return new MemMap(tail_name, nullptr, 0, nullptr, 0, tail_prot); 417fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 418fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_ = new_end - reinterpret_cast<byte*>(begin_); 419fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi base_size_ = new_base_end - reinterpret_cast<byte*>(base_begin_); 420fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(begin_ + size_, reinterpret_cast<byte*>(base_begin_) + base_size_); 421fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_size = old_end - new_end; 422fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* tail_base_begin = new_base_end; 423fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_base_size = old_base_end - new_base_end; 424fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_EQ(tail_base_begin + tail_base_size, old_base_end); 425fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(tail_base_size)); 426fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 427fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#ifdef USE_ASHMEM 428fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 429fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // prefixed "dalvik-". 430fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string debug_friendly_name("dalvik-"); 431fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi debug_friendly_name += tail_name; 432fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ScopedFd fd(ashmem_create_region(debug_friendly_name.c_str(), tail_base_size)); 4338dba5aaaffc0bc2b2580bf02f0d9095c00d26a17Stuart Monteith int flags = MAP_PRIVATE | MAP_FIXED; 434fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (fd.get() == -1) { 435fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", 436fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_name, strerror(errno)); 437fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 438fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 439fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#else 440fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ScopedFd fd(-1); 441fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int flags = MAP_PRIVATE | MAP_ANONYMOUS; 442fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#endif 443fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 444fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Unmap/map the tail region. 445fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int result = munmap(tail_base_begin, tail_base_size); 446fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (result == -1) { 447fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string maps; 448fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ReadFileToString("/proc/self/maps", &maps); 449fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi *error_msg = StringPrintf("munmap(%p, %zd) failed for '%s'\n%s", 450fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_base_begin, tail_base_size, name_.c_str(), 451fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi maps.c_str()); 452fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 453fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 454fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Don't cause memory allocation between the munmap and the mmap 455fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // calls. Otherwise, libc (or something else) might take this memory 456fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // region. Note this isn't perfect as there's no way to prevent 457fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // other threads to try to take this memory region here. 458fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* actual = reinterpret_cast<byte*>(mmap(tail_base_begin, tail_base_size, tail_prot, 459fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi flags, fd.get(), 0)); 460fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (actual == MAP_FAILED) { 461fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string maps; 462fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ReadFileToString("/proc/self/maps", &maps); 463c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier *error_msg = StringPrintf("anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0) failed\n%s", 464fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_base_begin, tail_base_size, tail_prot, flags, fd.get(), 465fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi maps.c_str()); 466fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 467fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 468fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return new MemMap(tail_name, actual, tail_size, actual, tail_base_size, tail_prot); 469cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier} 470d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 471d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chienbool MemMap::Protect(int prot) { 4724fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 4731c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 474d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 475d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 476d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 477d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien if (mprotect(base_begin_, base_size_, prot) == 0) { 4781c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 479d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 480d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 481d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 482a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao PLOG(ERROR) << "mprotect(" << reinterpret_cast<void*>(base_begin_) << ", " << base_size_ << ", " 483a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao << prot << ") failed"; 484d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return false; 485d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien} 486d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 4873eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchibool MemMap::CheckNoGaps(MemMap* begin_map, MemMap* end_map) { 4883eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 4893eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(begin_map != nullptr); 4903eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(end_map != nullptr); 4913eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(HasMemMap(begin_map)); 4923eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(HasMemMap(end_map)); 4933eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK_LE(begin_map->BaseBegin(), end_map->BaseBegin()); 4943eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = begin_map; 4953eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi while (map->BaseBegin() != end_map->BaseBegin()) { 4963eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* next_map = GetLargestMemMapAt(map->BaseEnd()); 4973eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (next_map == nullptr) { 4983eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi // Found a gap. 4993eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return false; 5003eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 5013eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi map = next_map; 5023eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 5033eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return true; 5043eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 5053eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5063eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchivoid MemMap::DumpMaps(std::ostream& os) { 5073eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi DumpMaps(os, maps_); 5083eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 5093eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5103eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchivoid MemMap::DumpMaps(std::ostream& os, const std::multimap<void*, MemMap*>& mem_maps) { 5113eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_); 5123eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi DumpMapsLocked(os, mem_maps); 5133eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 5143eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5153eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchivoid MemMap::DumpMapsLocked(std::ostream& os, const std::multimap<void*, MemMap*>& mem_maps) { 5163eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << mem_maps; 5173eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 5183eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5193eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchibool MemMap::HasMemMap(MemMap* map) { 5203eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi void* base_begin = map->BaseBegin(); 5213eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi for (auto it = maps_.lower_bound(base_begin), end = maps_.end(); 5223eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == base_begin; ++it) { 5233eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (it->second == map) { 5243eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return true; 5253eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 5263eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 5273eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return false; 5283eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 5293eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5303eed93dd5be03e5539827bebf0f414251a12e15eHiroshi YamauchiMemMap* MemMap::GetLargestMemMapAt(void* address) { 5313eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi size_t largest_size = 0; 5323eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* largest_map = nullptr; 5333eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi for (auto it = maps_.lower_bound(address), end = maps_.end(); 5343eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi it != end && it->first == address; ++it) { 5353eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi MemMap* map = it->second; 5363eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi CHECK(map != nullptr); 5373eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi if (largest_size < map->BaseSize()) { 5383eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi largest_size = map->BaseSize(); 5393eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi largest_map = map; 5403eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 5413eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi } 5423eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi return largest_map; 5433eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi} 5443eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi 5450d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstromstd::ostream& operator<<(std::ostream& os, const MemMap& mem_map) { 5463eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi os << StringPrintf("[MemMap: %p-%p prot=0x%x %s]", 5473eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi mem_map.BaseBegin(), mem_map.BaseEnd(), mem_map.GetProtect(), 5483eed93dd5be03e5539827bebf0f414251a12e15eHiroshi Yamauchi mem_map.GetName().c_str()); 5490d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return os; 5500d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom} 5510d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom 55227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} // namespace art 553