• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "mem_map.h"
18 
19 #include <windows.h>
20 
21 #include "android-base/logging.h"
22 #include "android-base/stringprintf.h"
23 #include "android-base/mapped_file.h"
24 #ifdef PROT_READ
25 #undef PROT_READ
26 #endif
27 #ifdef PROT_WRITE
28 #undef PROT_WRITE
29 #endif
30 #include "mman.h"
31 
32 namespace art {
33 
34 using android::base::StringPrintf;
35 
36 static off_t allocation_granularity;
37 
TargetMMapInit()38 void MemMap::TargetMMapInit() {
39   SYSTEM_INFO si;
40   GetSystemInfo(&si);
41   allocation_granularity = si.dwAllocationGranularity;
42 }
43 
TargetMMap(void * start,size_t len,int prot,int flags,int fd,off_t fd_off)44 void* MemMap::TargetMMap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) {
45   UNUSED(start);
46   size_t padding = fd_off % allocation_granularity;
47   off_t file_offset = fd_off - padding;
48   off_t map_length = len + padding;
49 
50   // Only read and write permissions are supported.
51   if ((prot != PROT_READ) && (prot != (PROT_READ | PROT_WRITE))) {
52     PLOG(ERROR) << "Protection or flag error was not supported.";
53     errno = EINVAL;
54     return MAP_FAILED;
55   }
56   // Fixed is not currently supported either.
57   // TODO(sehr): add MAP_FIXED support.
58   if ((flags & MAP_FIXED) != 0) {
59     PLOG(ERROR) << "MAP_FIXED not supported.";
60     errno = EINVAL;
61     return MAP_FAILED;
62   }
63 
64   // Compute the Windows access flags for the two APIs from the PROTs and MAPs.
65   DWORD map_access = 0;
66   DWORD view_access = 0;
67   if ((prot & PROT_WRITE) != 0) {
68     map_access = PAGE_READWRITE;
69     if (((flags & MAP_SHARED) != 0) && ((flags & MAP_PRIVATE) == 0)) {
70       view_access = FILE_MAP_ALL_ACCESS;
71     } else if (((flags & MAP_SHARED) == 0) && ((flags & MAP_PRIVATE) != 0)) {
72       view_access = FILE_MAP_COPY | FILE_MAP_READ;
73     } else {
74       PLOG(ERROR) << "MAP_PRIVATE and MAP_SHARED inconsistently set.";
75       errno = EINVAL;
76       return MAP_FAILED;
77     }
78   } else {
79     map_access = PAGE_READONLY;
80     view_access = FILE_MAP_READ;
81   }
82 
83   // MapViewOfFile does not like to see a size greater than the file size of the
84   // underlying file object, unless the underlying file object is writable.  If
85   // the mapped region would go beyond the end of the underlying file, use zero,
86   // as this indicates the physical size.
87   HANDLE file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
88   LARGE_INTEGER file_length;
89   if (!::GetFileSizeEx(file_handle, &file_length)) {
90     PLOG(ERROR) << "Couldn't get file size.";
91     errno = EINVAL;
92     return MAP_FAILED;
93   }
94   if (((map_access & PAGE_READONLY) != 0) &&
95       file_offset + map_length > file_length.QuadPart) {
96     map_length = 0;
97   }
98 
99   // Create a file mapping object that will be used to access the file.
100   HANDLE handle = ::CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
101                                       nullptr,
102                                       map_access,
103                                       0,
104                                       0,
105                                       nullptr);
106   if (handle == nullptr) {
107     DWORD error = ::GetLastError();
108     PLOG(ERROR) << StringPrintf("Couldn't create file mapping %lx.", error);
109     errno = EINVAL;
110     return MAP_FAILED;
111   }
112 
113   // Map the file into the process address space.
114   DWORD offset_low = static_cast<DWORD>(file_offset & 0xffffffffU);
115 #ifdef _WIN64
116   DWORD offset_high = static_cast<DWORD>(file_offset >> 32);
117 #else
118   DWORD offset_high = static_cast<DWORD>(0);
119 #endif
120   void* view_address = MapViewOfFile(handle, view_access, offset_high, offset_low, map_length);
121   if (view_address == nullptr) {
122     DWORD error = ::GetLastError();
123     PLOG(ERROR) << StringPrintf("Couldn't create file view %lx.", error);
124     ::CloseHandle(handle);
125     errno = EINVAL;
126     return MAP_FAILED;
127   }
128 
129   return view_address;
130 }
131 
TargetMUnmap(void * start,size_t len)132 int MemMap::TargetMUnmap(void* start, size_t len) {
133   // TODO(sehr): implement unmap.
134   UNUSED(start);
135   UNUSED(len);
136   return 0;
137 }
138 
139 }  // namespace art
140