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
|