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::MappedFile; 35 using android::base::StringPrintf; 36 37 static off_t allocation_granularity; 38 39 void MemMap::TargetMMapInit() { 40 SYSTEM_INFO si; 41 GetSystemInfo(&si); 42 allocation_granularity = si.dwAllocationGranularity; 43 } 44 45 void* MemMap::TargetMMap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) { 46 UNUSED(start); 47 size_t padding = fd_off % allocation_granularity; 48 off_t file_offset = fd_off - padding; 49 off_t map_length = len + padding; 50 51 // Only read and write permissions are supported. 52 if ((prot != PROT_READ) && (prot != (PROT_READ | PROT_WRITE))) { 53 PLOG(ERROR) << "Protection or flag error was not supported."; 54 errno = EINVAL; 55 return MAP_FAILED; 56 } 57 // Fixed is not currently supported either. 58 // TODO(sehr): add MAP_FIXED support. 59 if ((flags & MAP_FIXED) != 0) { 60 PLOG(ERROR) << "MAP_FIXED not supported."; 61 errno = EINVAL; 62 return MAP_FAILED; 63 } 64 65 // Compute the Windows access flags for the two APIs from the PROTs and MAPs. 66 DWORD map_access = 0; 67 DWORD view_access = 0; 68 if ((prot & PROT_WRITE) != 0) { 69 map_access = PAGE_READWRITE; 70 if (((flags & MAP_SHARED) != 0) && ((flags & MAP_PRIVATE) == 0)) { 71 view_access = FILE_MAP_ALL_ACCESS; 72 } else if (((flags & MAP_SHARED) == 0) && ((flags & MAP_PRIVATE) != 0)) { 73 view_access = FILE_MAP_COPY | FILE_MAP_READ; 74 } else { 75 PLOG(ERROR) << "MAP_PRIVATE and MAP_SHARED inconsistently set."; 76 errno = EINVAL; 77 return MAP_FAILED; 78 } 79 } else { 80 map_access = PAGE_READONLY; 81 view_access = FILE_MAP_READ; 82 } 83 84 // MapViewOfFile does not like to see a size greater than the file size of the 85 // underlying file object, unless the underlying file object is writable. If 86 // the mapped region would go beyond the end of the underlying file, use zero, 87 // as this indicates the physical size. 88 HANDLE file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); 89 LARGE_INTEGER file_length; 90 if (!::GetFileSizeEx(file_handle, &file_length)) { 91 PLOG(ERROR) << "Couldn't get file size."; 92 errno = EINVAL; 93 return MAP_FAILED; 94 } 95 if (((map_access & PAGE_READONLY) != 0) && 96 file_offset + map_length > file_length.QuadPart) { 97 map_length = 0; 98 } 99 100 // Create a file mapping object that will be used to access the file. 101 HANDLE handle = ::CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)), 102 nullptr, 103 map_access, 104 0, 105 0, 106 nullptr); 107 if (handle == nullptr) { 108 DWORD error = ::GetLastError(); 109 PLOG(ERROR) << StringPrintf("Couldn't create file mapping %lx.", error); 110 errno = EINVAL; 111 return MAP_FAILED; 112 } 113 114 // Map the file into the process address space. 115 DWORD offset_low = static_cast<DWORD>(file_offset & 0xffffffffU); 116 #ifdef _WIN64 117 DWORD offset_high = static_cast<DWORD>(file_offset >> 32); 118 #else 119 DWORD offset_high = static_cast<DWORD>(0); 120 #endif 121 void* view_address = MapViewOfFile(handle, view_access, offset_high, offset_low, map_length); 122 if (view_address == nullptr) { 123 DWORD error = ::GetLastError(); 124 PLOG(ERROR) << StringPrintf("Couldn't create file view %lx.", error); 125 ::CloseHandle(handle); 126 errno = EINVAL; 127 return MAP_FAILED; 128 } 129 130 return view_address; 131 } 132 133 int MemMap::TargetMUnmap(void* start, size_t len) { 134 // TODO(sehr): implement unmap. 135 UNUSED(start); 136 UNUSED(len); 137 return 0; 138 } 139 140 } // namespace art 141