File: mem_map_windows.cc

package info (click to toggle)
android-platform-art 11.0.0%2Br48-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 78,932 kB
  • sloc: cpp: 459,858; java: 163,268; asm: 22,644; python: 9,815; sh: 6,330; ansic: 4,117; xml: 2,855; perl: 77; makefile: 73
file content (140 lines) | stat: -rw-r--r-- 4,446 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mem_map.h"

#include <windows.h>

#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "android-base/mapped_file.h"
#ifdef PROT_READ
#undef PROT_READ
#endif
#ifdef PROT_WRITE
#undef PROT_WRITE
#endif
#include "mman.h"

namespace art {

using android::base::MappedFile;
using android::base::StringPrintf;

static off_t allocation_granularity;

void MemMap::TargetMMapInit() {
  SYSTEM_INFO si;
  GetSystemInfo(&si);
  allocation_granularity = si.dwAllocationGranularity;
}

void* MemMap::TargetMMap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) {
  UNUSED(start);
  size_t padding = fd_off % allocation_granularity;
  off_t file_offset = fd_off - padding;
  off_t map_length = len + padding;

  // Only read and write permissions are supported.
  if ((prot != PROT_READ) && (prot != (PROT_READ | PROT_WRITE))) {
    PLOG(ERROR) << "Protection or flag error was not supported.";
    errno = EINVAL;
    return MAP_FAILED;
  }
  // Fixed is not currently supported either.
  // TODO(sehr): add MAP_FIXED support.
  if ((flags & MAP_FIXED) != 0) {
    PLOG(ERROR) << "MAP_FIXED not supported.";
    errno = EINVAL;
    return MAP_FAILED;
  }

  // Compute the Windows access flags for the two APIs from the PROTs and MAPs.
  DWORD map_access = 0;
  DWORD view_access = 0;
  if ((prot & PROT_WRITE) != 0) {
    map_access = PAGE_READWRITE;
    if (((flags & MAP_SHARED) != 0) && ((flags & MAP_PRIVATE) == 0)) {
      view_access = FILE_MAP_ALL_ACCESS;
    } else if (((flags & MAP_SHARED) == 0) && ((flags & MAP_PRIVATE) != 0)) {
      view_access = FILE_MAP_COPY | FILE_MAP_READ;
    } else {
      PLOG(ERROR) << "MAP_PRIVATE and MAP_SHARED inconsistently set.";
      errno = EINVAL;
      return MAP_FAILED;
    }
  } else {
    map_access = PAGE_READONLY;
    view_access = FILE_MAP_READ;
  }

  // MapViewOfFile does not like to see a size greater than the file size of the
  // underlying file object, unless the underlying file object is writable.  If
  // the mapped region would go beyond the end of the underlying file, use zero,
  // as this indicates the physical size.
  HANDLE file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
  LARGE_INTEGER file_length;
  if (!::GetFileSizeEx(file_handle, &file_length)) {
    PLOG(ERROR) << "Couldn't get file size.";
    errno = EINVAL;
    return MAP_FAILED;
  }
  if (((map_access & PAGE_READONLY) != 0) &&
      file_offset + map_length > file_length.QuadPart) {
    map_length = 0;
  }

  // Create a file mapping object that will be used to access the file.
  HANDLE handle = ::CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
                                      nullptr,
                                      map_access,
                                      0,
                                      0,
                                      nullptr);
  if (handle == nullptr) {
    DWORD error = ::GetLastError();
    PLOG(ERROR) << StringPrintf("Couldn't create file mapping %lx.", error);
    errno = EINVAL;
    return MAP_FAILED;
  }

  // Map the file into the process address space.
  DWORD offset_low = static_cast<DWORD>(file_offset & 0xffffffffU);
#ifdef _WIN64
  DWORD offset_high = static_cast<DWORD>(file_offset >> 32);
#else
  DWORD offset_high = static_cast<DWORD>(0);
#endif
  void* view_address = MapViewOfFile(handle, view_access, offset_high, offset_low, map_length);
  if (view_address == nullptr) {
    DWORD error = ::GetLastError();
    PLOG(ERROR) << StringPrintf("Couldn't create file view %lx.", error);
    ::CloseHandle(handle);
    errno = EINVAL;
    return MAP_FAILED;
  }

  return view_address;
}

int MemMap::TargetMUnmap(void* start, size_t len) {
  // TODO(sehr): implement unmap.
  UNUSED(start);
  UNUSED(len);
  return 0;
}

}  // namespace art