mem_map.cc revision 4fb5df8453367aa3f160ac230c03a7a98a28e562
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 19debeb3aaaa4257684029f15733dc30af5dcb8aabIan Rogers#include <inttypes.h> 20943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris#include <backtrace/BacktraceMap.h> 21e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes 22caf22aca3482e2fcc8bf443f911718a5021da1c9Christopher Ferris#include "UniquePtr.h" 23e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 246c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "ScopedFd.h" 256c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "utils.h" 266c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 276c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#define USE_ASHMEM 1 286c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 296c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 306c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include <cutils/ashmem.h> 316c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 326c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 3327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstromnamespace art { 3427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 35943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferrisstatic std::ostream& operator<<( 36943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::ostream& os, 37943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris std::pair<BacktraceMap::const_iterator, BacktraceMap::const_iterator> iters) { 38943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris for (BacktraceMap::const_iterator it = iters.first; it != iters.second; ++it) { 39943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris os << StringPrintf("0x%08x-0x%08x %c%c%c %s\n", 40943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->start), 41943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris static_cast<uint32_t>(it->end), 42943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_READ) ? 'r' : '-', 43943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_WRITE) ? 'w' : '-', 44943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris (it->flags & PROT_EXEC) ? 'x' : '-', it->name.c_str()); 45ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes } 46ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes return os; 4796970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes} 4896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 494fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchistatic bool CheckMapRequest(byte* expected_ptr, void* actual_ptr, size_t byte_count, 504fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream* error_msg) { 514fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Handled first by caller for more specific error messages. 524fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(actual_ptr != MAP_FAILED); 534fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 544fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == nullptr) { 554fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 564fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 574fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 584fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (expected_ptr == actual_ptr) { 594fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return true; 604fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 614fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 624fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // We asked for an address but didn't get what we wanted, all paths below here should fail. 634fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi int result = munmap(actual_ptr, byte_count); 644fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (result == -1) { 654fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi PLOG(WARNING) << StringPrintf("munmap(%p, %zd) failed", actual_ptr, byte_count); 6627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 67ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes 684fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi uintptr_t actual = reinterpret_cast<uintptr_t>(actual_ptr); 694fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi uintptr_t expected = reinterpret_cast<uintptr_t>(expected_ptr); 704fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi uintptr_t limit = expected + byte_count; 71ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes 72caf22aca3482e2fcc8bf443f911718a5021da1c9Christopher Ferris UniquePtr<BacktraceMap> map(BacktraceMap::Create(getpid())); 73caf22aca3482e2fcc8bf443f911718a5021da1c9Christopher Ferris if (!map->Build()) { 744fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg << StringPrintf("Failed to build process map to determine why mmap returned " 754fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi "0x%08" PRIxPTR " instead of 0x%08" PRIxPTR, actual, expected); 764fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 774fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 78943af7dab1454517c5bd11a31ab99f260afb22d1Christopher Ferris } 79caf22aca3482e2fcc8bf443f911718a5021da1c9Christopher Ferris for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 804fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if ((expected >= it->start && expected < it->end) // start of new within old 814fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi || (limit > it->start && limit < it->end) // end of new within old 824fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi || (expected <= it->start && limit > it->end)) { // start/end of new includes all of old 834fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg 844fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi << StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " overlaps with " 854fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi "existing map 0x%08" PRIxPTR "-0x%08" PRIxPTR " (%s)\n", 864fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi expected, limit, 874fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi static_cast<uintptr_t>(it->start), static_cast<uintptr_t>(it->end), 884fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi it->name.c_str()) 894fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi << std::make_pair(it, map->end()); 904fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 914fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 9296970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes } 934fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg << StringPrintf("Failed to mmap at expected address, mapped at " 944fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi "0x%08" PRIxPTR " instead of 0x%08" PRIxPTR, actual, expected); 954fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return false; 9627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 9727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 984fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi YamauchiMemMap* MemMap::MapAnonymous(const char* name, byte* expected, size_t byte_count, int prot, 99ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers bool low_4gb, std::string* error_msg) { 1009004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 1014fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return new MemMap(name, nullptr, 0, nullptr, 0, prot); 1029004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 103ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize); 1046c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 1056c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 106a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 107a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers // prefixed "dalvik-". 108a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers std::string debug_friendly_name("dalvik-"); 109a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers debug_friendly_name += name; 110a40307e8562c20d9b9ce46e773864d07d95512a1Ian Rogers ScopedFd fd(ashmem_create_region(debug_friendly_name.c_str(), page_aligned_byte_count)); 1116c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes if (fd.get() == -1) { 1128d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", name, strerror(errno)); 1138d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers return nullptr; 1146c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes } 1154fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi int flags = MAP_PRIVATE; 1166c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#else 1176c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes ScopedFd fd(-1); 1186c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes int flags = MAP_PRIVATE | MAP_ANONYMOUS; 1196c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 120ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifdef __LP64__ 121ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (low_4gb) { 122ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers flags |= MAP_32BIT; 123ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 124ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 1254fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 1264fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi void* actual = mmap(expected, page_aligned_byte_count, prot, flags, fd.get(), 0); 1274fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::string strerr(strerror(errno)); 12827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 1298161c0336b97e11e02c000af357f8f40de2e23e4jeffhao std::string maps; 1308161c0336b97e11e02c000af357f8f40de2e23e4jeffhao ReadFileToString("/proc/self/maps", &maps); 1314fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg = StringPrintf("Failed anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0): %s\n%s", 1324fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi expected, page_aligned_byte_count, prot, flags, fd.get(), 1334fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi strerr.c_str(), maps.c_str()); 1344fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 1354fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 1364fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 1374fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (!CheckMapRequest(expected, actual, page_aligned_byte_count, &check_map_request_error_msg)) { 1384fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg = check_map_request_error_msg.str(); 1398d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers return nullptr; 14027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 1414fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return new MemMap(name, reinterpret_cast<byte*>(actual), byte_count, actual, 1424fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi page_aligned_byte_count, prot); 14327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 14427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 1454fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi YamauchiMemMap* MemMap::MapFileAtAddress(byte* expected, size_t byte_count, int prot, int flags, int fd, 1468d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers off_t start, bool reuse, const char* filename, 1478d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg) { 14827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, prot); 14927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, flags & (MAP_SHARED | MAP_PRIVATE)); 1504fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (reuse) { 1514fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // reuse means it is okay that it overlaps an existing page mapping. 1524fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // Only use this if you actually made the page reservation yourself. 1534fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(expected != nullptr); 1544fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi flags |= MAP_FIXED; 1554fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } else { 1564fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK_EQ(0, flags & MAP_FIXED); 1574fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 1584fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 1599004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (byte_count == 0) { 1604fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return new MemMap(filename, nullptr, 0, nullptr, 0, prot); 1619004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 162f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'offset' to be page-aligned as required by mmap. 16327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom int page_offset = start % kPageSize; 16427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom off_t page_aligned_offset = start - page_offset; 165f8adc60455b90c95a6a3c8f87830e4e88b2644e1Ian Rogers // Adjust 'byte_count' to be page-aligned as we will map this anyway. 166ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes size_t page_aligned_byte_count = RoundUp(byte_count + page_offset, kPageSize); 1674fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // The 'expected' is modified (if specified, ie non-null) to be page aligned to the file but not 1684fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi // necessarily to virtual memory. mmap will page align 'expected' for us. 1694fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi byte* page_aligned_expected = (expected == nullptr) ? nullptr : (expected - page_offset); 1704fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi 1714fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi byte* actual = reinterpret_cast<byte*>(mmap(page_aligned_expected, 172ecd3a6fc6e29d7dc4cb825c5282a8054ac52b8cfElliott Hughes page_aligned_byte_count, 17327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom prot, 17427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom flags, 17527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom fd, 17627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom page_aligned_offset)); 1774fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::string strerr(strerror(errno)); 17827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 1798161c0336b97e11e02c000af357f8f40de2e23e4jeffhao std::string maps; 1808161c0336b97e11e02c000af357f8f40de2e23e4jeffhao ReadFileToString("/proc/self/maps", &maps); 181c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier *error_msg = StringPrintf("mmap(%p, %zd, 0x%x, 0x%x, %d, %" PRId64 182c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier ") of file '%s' failed: %s\n%s", 1834fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi page_aligned_expected, page_aligned_byte_count, prot, flags, fd, 1843b6f0fae76fddf81930a263a075dc87b6039b7fcMathieu Chartier static_cast<int64_t>(page_aligned_offset), filename, strerr.c_str(), 1853b6f0fae76fddf81930a263a075dc87b6039b7fcMathieu Chartier maps.c_str()); 1864fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 1874fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi } 1884fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi std::ostringstream check_map_request_error_msg; 1894fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (!CheckMapRequest(expected, actual, page_aligned_byte_count, &check_map_request_error_msg)) { 1904fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi *error_msg = check_map_request_error_msg.str(); 1914fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return nullptr; 19227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 1930d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return new MemMap(filename, actual + page_offset, byte_count, actual, page_aligned_byte_count, 1941c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier prot); 19527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 19627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 19727ec961a1da540ba7f16c07a682585ab167317adBrian CarlstromMemMap::~MemMap() { 1984fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 19927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return; 20027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 20130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers int result = munmap(base_begin_, base_size_); 20227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (result == -1) { 20327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom PLOG(FATAL) << "munmap failed"; 20427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 20527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 20627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 2071c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu ChartierMemMap::MemMap(const std::string& name, byte* begin, size_t size, void* base_begin, 2081c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier size_t base_size, int prot) 2091c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier : name_(name), begin_(begin), size_(size), base_begin_(base_begin), base_size_(base_size), 2101c23e1edb7361bbaec6e57fca86d8d3797960ad2Mathieu Chartier prot_(prot) { 2119004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom if (size_ == 0) { 2124fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ == nullptr); 2134fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ == nullptr); 2149004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_EQ(base_size_, 0U); 2159004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } else { 2164fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(begin_ != nullptr); 2174fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi CHECK(base_begin_ != nullptr); 2189004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom CHECK_NE(base_size_, 0U); 2199004cb6591781d1e6c5ec6d7bc6dc99d9ecee124Brian Carlstrom } 22027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom}; 22127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 222fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi YamauchiMemMap* MemMap::RemapAtEnd(byte* new_end, const char* tail_name, int tail_prot, 223fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string* error_msg) { 224cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_GE(new_end, Begin()); 225cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier DCHECK_LE(new_end, End()); 226fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(begin_ + size_, reinterpret_cast<byte*>(base_begin_) + base_size_); 227fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(begin_)); 228fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(base_begin_)); 229fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(reinterpret_cast<byte*>(base_begin_) + base_size_)); 230fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(new_end)); 231fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* old_end = begin_ + size_; 232fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* old_base_end = reinterpret_cast<byte*>(base_begin_) + base_size_; 233fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* new_base_end = new_end; 234fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(new_base_end, old_base_end); 235fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (new_base_end == old_base_end) { 2364fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi return new MemMap(tail_name, nullptr, 0, nullptr, 0, tail_prot); 237fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 238fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_ = new_end - reinterpret_cast<byte*>(begin_); 239fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi base_size_ = new_base_end - reinterpret_cast<byte*>(base_begin_); 240fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_LE(begin_ + size_, reinterpret_cast<byte*>(base_begin_) + base_size_); 241fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_size = old_end - new_end; 242fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* tail_base_begin = new_base_end; 243fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi size_t tail_base_size = old_base_end - new_base_end; 244fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK_EQ(tail_base_begin + tail_base_size, old_base_end); 245fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi DCHECK(IsAligned<kPageSize>(tail_base_size)); 246fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 247fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#ifdef USE_ASHMEM 248fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // android_os_Debug.cpp read_mapinfo assumes all ashmem regions associated with the VM are 249fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // prefixed "dalvik-". 250fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string debug_friendly_name("dalvik-"); 251fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi debug_friendly_name += tail_name; 252fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ScopedFd fd(ashmem_create_region(debug_friendly_name.c_str(), tail_base_size)); 253fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int flags = MAP_PRIVATE; 254fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (fd.get() == -1) { 255fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", 256fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_name, strerror(errno)); 257fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 258fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 259fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#else 260fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ScopedFd fd(-1); 261fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int flags = MAP_PRIVATE | MAP_ANONYMOUS; 262fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi#endif 263fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi 264fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Unmap/map the tail region. 265fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi int result = munmap(tail_base_begin, tail_base_size); 266fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (result == -1) { 267fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string maps; 268fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ReadFileToString("/proc/self/maps", &maps); 269fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi *error_msg = StringPrintf("munmap(%p, %zd) failed for '%s'\n%s", 270fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_base_begin, tail_base_size, name_.c_str(), 271fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi maps.c_str()); 272fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 273fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 274fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // Don't cause memory allocation between the munmap and the mmap 275fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // calls. Otherwise, libc (or something else) might take this memory 276fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // region. Note this isn't perfect as there's no way to prevent 277fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi // other threads to try to take this memory region here. 278fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi byte* actual = reinterpret_cast<byte*>(mmap(tail_base_begin, tail_base_size, tail_prot, 279fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi flags, fd.get(), 0)); 280fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi if (actual == MAP_FAILED) { 281fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi std::string maps; 282fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi ReadFileToString("/proc/self/maps", &maps); 283c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier *error_msg = StringPrintf("anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0) failed\n%s", 284fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi tail_base_begin, tail_base_size, tail_prot, flags, fd.get(), 285fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi maps.c_str()); 286fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return nullptr; 287fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi } 288fd7e7f1253927c8d7f17e7cbc259daaf51868bd3Hiroshi Yamauchi return new MemMap(tail_name, actual, tail_size, actual, tail_base_size, tail_prot); 289cc236d74772dda5a4161d9bc5f497fd3d956eb87Mathieu Chartier} 290d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 291d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chienbool MemMap::Protect(int prot) { 2924fb5df8453367aa3f160ac230c03a7a98a28e562Hiroshi Yamauchi if (base_begin_ == nullptr && base_size_ == 0) { 2931c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 294d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 295d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 296d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 297d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien if (mprotect(base_begin_, base_size_, prot) == 0) { 2981c849e5badc85b6753dee0c0487729b2c0529f51Ian Rogers prot_ = prot; 299d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 300d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 301d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 302a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao PLOG(ERROR) << "mprotect(" << reinterpret_cast<void*>(base_begin_) << ", " << base_size_ << ", " 303a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao << prot << ") failed"; 304d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return false; 305d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien} 306d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 3070d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstromstd::ostream& operator<<(std::ostream& os, const MemMap& mem_map) { 308c7cb1901b776129044a4ad3886fd6450e83df681Mathieu Chartier os << StringPrintf("[MemMap: %s prot=0x%x %p-%p]", 3090d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom mem_map.GetName().c_str(), mem_map.GetProtect(), 3100d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom mem_map.BaseBegin(), mem_map.BaseEnd()); 3110d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom return os; 3120d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom} 3130d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom 31427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} // namespace art 315