mem_map.cc revision a060ed959efb8d57419edc3c5c1fa48372cc6588
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
236a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao  PLOG(ERROR) << "mprotect(" << reinterpret_cast<void*>(base_begin_) << ", " << base_size_ << ", "
237a060ed959efb8d57419edc3c5c1fa48372cc6588Shih-wei Liao              << prot << ") failed";
238d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien  return false;
239d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien}
240d88fa26892ad5ddebb7ab3407cdc574c54ed8258Logan Chien
24127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom}  // namespace art
242