mem_map.cc revision d88fa26892ad5ddebb7ab3407cdc574c54ed8258
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 1927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <sys/mman.h> 2027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 216c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "ScopedFd.h" 226c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include "utils.h" 236c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 246c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#define USE_ASHMEM 1 256c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 266c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 276c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#include <cutils/ashmem.h> 286c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 296c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 3027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstromnamespace art { 3127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 3296970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes#if !defined(NDEBUG) 3396970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 3496970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughesstatic size_t ParseHex(const std::string& string) { 3527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_EQ(8U, string.size()); 3627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom const char* str = string.c_str(); 3727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom char* end; 3827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom size_t value = strtoul(str, &end, 16); 3927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK(end != str) << "Failed to parse hexadecimal value from " << string; 40cc607471d301e468ac0d84deacd1f60667331f67Elliott Hughes CHECK_EQ(*end, '\0') << "Failed to parse hexadecimal value from " << string; 4127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return value; 4227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 4327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 4496970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughesstatic void CheckMapRegion(uint32_t base, uint32_t limit, uint32_t start, uint32_t end, const std::string& maps) { 4596970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes CHECK(!(base >= start && base < end) // start of new within old 4696970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes && !(limit > start && limit < end) // end of new within old 4796970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes && !(base <= start && limit > end)) // start/end of new includes all of old 4896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes << StringPrintf("Requested region %08x-%08x overlaps with existing map %08x-%08x\n", 4996970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes base, limit, start, end) 5096970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes << maps; 5196970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes} 5296970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 5327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstromvoid CheckMapRequest(byte* addr, size_t length) { 5427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (addr == NULL) { 5527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return; 5627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 5796970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes uint32_t base = reinterpret_cast<size_t>(addr); 5896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes uint32_t limit = base + length; 5996970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 6096970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes#if defined(__APPLE__) 6196970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // Mac OS vmmap(1) output currently looks something like this: 6227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 6396970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // Virtual Memory Map of process 51036 (dex2oatd) 6496970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // Output report format: 2.2 -- 32-bit process 6596970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // 6696970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // ==== regions for process 51036 (non-writable and writable regions are interleaved) 6796970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // __PAGEZERO 00000000-00001000 [ 4K 0K 0K] ---/--- SM=NUL out/host/darwin-x86/bin/dex2oatd 6896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // __TEXT 00001000-00015000 [ 80K 80K 0K] r-x/rwx SM=COW out/host/darwin-x86/bin/dex2oatd 6996970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // __DATA 00015000-00016000 [ 4K 4K 4K] rw-/rwx SM=PRV out/host/darwin-x86/bin/dex2oatd 7096970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // __LINKEDIT 00016000-00044000 [ 184K 184K 0K] r--/rwx SM=COW out/host/darwin-x86/bin/dex2oatd 7196970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // __TEXT 00044000-00046000 [ 8K 8K 4K] r-x/rwx SM=COW out/host/darwin-x86/obj/lib/libnativehelper.dylib 7296970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // __DATA 00046000-00047000 [ 4K 4K 4K] rw-/rwx SM=ZER out/host/darwin-x86/obj/lib/libnativehelper.dylib 7396970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // __LINKEDIT 00047000-0004a000 [ 12K 12K 0K] r--/rwx SM=COW out/host/darwin-x86/obj/lib/libnativehelper.dylib 7496970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes // ... 7596970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 76ba7a3ecc0c7342a19951f076474c41d43168f68eElliott Hughes // TODO: the -v option replaces "-w -resident -dirty -purge -submap -allSplitLibs -noCoalesce" >= 10.6. 778d524a1bd3cbbe701572b232cf2e690835c95346Elliott Hughes std::string command(StringPrintf("vmmap -w -resident -submap -allSplitLibs -interleaved %d", getpid())); 7896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes FILE* fp = popen(command.c_str(), "r"); 7996970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes if (fp == NULL) { 8096970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes PLOG(FATAL) << "popen failed"; 8196970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes } 8296970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes std::vector<char> chars(512); 8396970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes std::string maps; 8496970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes while (fgets(&chars[0], chars.size(), fp) != NULL) { 8596970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes std::string line(&chars[0]); 8696970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes maps += line; 8796970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes if (line.size() < 40 || line[31] != '-') { 8896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes continue; 8996970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes } 9096970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 91448e93c728b352729afde3c8e95e902c08b1d929Elliott Hughes std::string start_str(line.substr(23, 8)); 92448e93c728b352729afde3c8e95e902c08b1d929Elliott Hughes std::string end_str(line.substr(32, 8)); 9396970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes uint32_t start = ParseHex(start_str); 9496970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes uint32_t end = ParseHex(end_str); 9596970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes CheckMapRegion(base, limit, start, end, maps); 9696970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes } 9796970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes if (ferror(fp)) { 9896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes PLOG(FATAL) << "fgets failed"; 9996970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes } 10096970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes if (pclose(fp) == -1) { 10196970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes PLOG(FATAL) << "pclose failed"; 10296970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes } 10396970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes#else // Linux 10427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom std::string maps; 10527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom bool read = ReadFileToString("/proc/self/maps", &maps); 10627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (!read) { 10727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom PLOG(FATAL) << "Failed to read /proc/self/maps"; 10827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 10927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // Quick and dirty parse of output like shown below. We only focus 11027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // on grabbing the two 32-bit hex values at the start of each line 11127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // and will fail on wider addresses found on 64-bit systems. 11227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 11327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 00008000-0001f000 r-xp 00000000 b3:01 273 /system/bin/toolbox 11427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 0001f000-00021000 rw-p 00017000 b3:01 273 /system/bin/toolbox 11527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 00021000-00029000 rw-p 00000000 00:00 0 [heap] 11627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 40011000-40053000 r-xp 00000000 b3:01 1050 /system/lib/libc.so 11727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 40053000-40056000 rw-p 00042000 b3:01 1050 /system/lib/libc.so 11827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 40056000-40061000 rw-p 00000000 00:00 0 11927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 40061000-40063000 r-xp 00000000 b3:01 1107 /system/lib/libusbhost.so 12027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 40063000-40064000 rw-p 00002000 b3:01 1107 /system/lib/libusbhost.so 12127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 4009d000-400a0000 r-xp 00000000 b3:01 1022 /system/lib/liblog.so 12227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 400a0000-400a1000 rw-p 00003000 b3:01 1022 /system/lib/liblog.so 12327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 400b7000-400cc000 r-xp 00000000 b3:01 932 /system/lib/libm.so 12427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 400cc000-400cd000 rw-p 00015000 b3:01 932 /system/lib/libm.so 12527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 400cf000-400d0000 r--p 00000000 00:00 0 12627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 400e4000-400ec000 r--s 00000000 00:0b 388 /dev/__properties__ (deleted) 12727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 400ec000-400fa000 r-xp 00000000 b3:01 1101 /system/lib/libcutils.so 12827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 400fa000-400fb000 rw-p 0000e000 b3:01 1101 /system/lib/libcutils.so 12927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 400fb000-4010a000 rw-p 00000000 00:00 0 13027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 4010d000-4010e000 r-xp 00000000 b3:01 929 /system/lib/libstdc++.so 13127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // 4010e000-4010f000 rw-p 00001000 b3:01 929 /system/lib/libstdc++.so 13227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // b0001000-b0009000 r-xp 00001000 b3:01 1098 /system/bin/linker 13327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // b0009000-b000a000 rw-p 00009000 b3:01 1098 /system/bin/linker 13427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // b000a000-b0015000 rw-p 00000000 00:00 0 13527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // bee35000-bee56000 rw-p 00000000 00:00 0 [stack] 13627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors] 13727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 13827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom for (size_t i = 0; i < maps.size(); i++) { 13927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom size_t remaining = maps.size() - i; 14027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (remaining < 8+1+8) { // 00008000-0001f000 14127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom LOG(FATAL) << "Failed to parse at pos " << i << "\n" << maps; 14227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 143955724179c6c739524f610023287f56b24dc31deElliott Hughes std::string start_str(maps.substr(i, 8)); 144955724179c6c739524f610023287f56b24dc31deElliott Hughes std::string end_str(maps.substr(i+1+8, 8)); 14527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom uint32_t start = ParseHex(start_str); 14627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom uint32_t end = ParseHex(end_str); 14796970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes CheckMapRegion(base, limit, start, end, maps); 14827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom i += 8+1+8; 14927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom i = maps.find('\n', i); 15027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK(i != std::string::npos) << "Failed to find newline from pos " << i << "\n" << maps; 15127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 15227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#endif 15327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 15427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 15596970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes#else 1561bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesstatic void CheckMapRequest(byte*, size_t) { } 15796970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes#endif 15896970cdab3e28511322ce37fa578f6eff8931d72Elliott Hughes 15989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian CarlstromMemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t length, int prot) { 16027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0U, length); 16127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, prot); 16227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom size_t page_aligned_size = RoundUp(length, kPageSize); 16327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CheckMapRequest(addr, page_aligned_size); 1646c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 1656c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#ifdef USE_ASHMEM 1666c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes ScopedFd fd(ashmem_create_region(name, page_aligned_size)); 1676c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes int flags = MAP_PRIVATE; 1686c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes if (fd.get() == -1) { 1696c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes PLOG(ERROR) << "ashmem_create_region failed (" << name << ")"; 1706c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes return NULL; 1716c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes } 1726c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#else 1736c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes ScopedFd fd(-1); 1746c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes int flags = MAP_PRIVATE | MAP_ANONYMOUS; 1756c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes#endif 1766c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes 1776c9c06dbb0b16714079afaedbebd3d548aa832b2Elliott Hughes byte* actual = reinterpret_cast<byte*>(mmap(addr, page_aligned_size, prot, flags, fd.get(), 0)); 17827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 1795ea8d4b0912a5bc139be21fc901f982a6b023675Elliott Hughes PLOG(ERROR) << "mmap(" << reinterpret_cast<void*>(addr) << ", " << page_aligned_size 1805ea8d4b0912a5bc139be21fc901f982a6b023675Elliott Hughes << ", " << prot << ", " << flags << ", " << fd.get() << ", 0) failed for " << name; 18127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return NULL; 18227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 18327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return new MemMap(actual, length, actual, page_aligned_size); 18427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 18527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 18689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian CarlstromMemMap* MemMap::MapFileAtAddress(byte* addr, size_t length, int prot, int flags, int fd, off_t start) { 18727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0U, length); 18827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, prot); 18927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CHECK_NE(0, flags & (MAP_SHARED | MAP_PRIVATE)); 19027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom // adjust to be page-aligned 19127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom int page_offset = start % kPageSize; 19227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom off_t page_aligned_offset = start - page_offset; 19327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom size_t page_aligned_size = RoundUp(length + page_offset, kPageSize); 19427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom CheckMapRequest(addr, page_aligned_size); 19527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom byte* actual = reinterpret_cast<byte*>(mmap(addr, 19627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom page_aligned_size, 19727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom prot, 19827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom flags, 19927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom fd, 20027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom page_aligned_offset)); 20127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (actual == MAP_FAILED) { 20227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom PLOG(ERROR) << "mmap failed"; 20327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return NULL; 20427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 20527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return new MemMap(actual + page_offset, length, actual, page_aligned_size); 20627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 20727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 20827ec961a1da540ba7f16c07a682585ab167317adBrian CarlstromMemMap::~MemMap() { 20930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers if (base_begin_ == NULL && base_size_ == 0) { 21027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom return; 21127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 21230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers int result = munmap(base_begin_, base_size_); 21327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (result == -1) { 21427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom PLOG(FATAL) << "munmap failed"; 21527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 21627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} 21727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 21830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian RogersMemMap::MemMap(byte* begin, size_t size, void* base_begin, size_t base_size) 21930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers : begin_(begin), size_(size), base_begin_(base_begin), base_size_(base_size) { 22030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK(begin_ != NULL); 22130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK_NE(size_, 0U); 22230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK(base_begin_ != NULL); 22330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK_NE(base_size_, 0U); 22427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom}; 22527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 226d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 227d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chienbool MemMap::Protect(int prot) { 228d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien if (base_begin_ == NULL && base_size_ == 0) { 229d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 230d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 231d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 232d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien if (mprotect(base_begin_, base_size_, prot) == 0) { 233d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return true; 234d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien } 235d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 236d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien PLOG(ERROR) << "mprotect(" << base_begin_ << ", " << base_size_ << ", " << prot << ") failed"; 237d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien return false; 238d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien} 239d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien 24027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom} // namespace art 241