blob: 28dbb9856d475fda50228af1597390ea6a02d45b [file] [log] [blame]
Reid Spencer97374922004-10-04 11:08:32 +00001//===- Win32/MappedFile.cpp - Win32 MappedFile Implementation ---*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer97374922004-10-04 11:08:32 +00007//
8//===----------------------------------------------------------------------===//
9//
Reid Spencer8545fc12004-10-14 03:05:59 +000010// This file provides the Win32 implementation of the MappedFile concept.
Reid Spencer97374922004-10-04 11:08:32 +000011//
12//===----------------------------------------------------------------------===//
13
Reid Spencer8545fc12004-10-14 03:05:59 +000014//===----------------------------------------------------------------------===//
15//=== WARNING: Implementation here must contain only Win32 code.
16//===----------------------------------------------------------------------===//
17
Reid Spencer97374922004-10-04 11:08:32 +000018#include "Win32.h"
Reid Spencer8545fc12004-10-14 03:05:59 +000019#include "llvm/System/Process.h"
20
21namespace llvm {
22using namespace sys;
23
24struct sys::MappedFileInfo {
25 HANDLE hFile;
26 HANDLE hMapping;
27 size_t size;
28};
Reid Spencer97374922004-10-04 11:08:32 +000029
Reid Spencer05545752006-08-25 21:37:17 +000030bool MappedFile::initialize(std::string* ErrMsg) {
Reid Spencer8545fc12004-10-14 03:05:59 +000031 assert(!info_);
32 info_ = new MappedFileInfo;
33 info_->hFile = INVALID_HANDLE_VALUE;
34 info_->hMapping = NULL;
35
36 DWORD mode = options_ & WRITE_ACCESS ? GENERIC_WRITE : GENERIC_READ;
37 DWORD disposition = options_ & WRITE_ACCESS ? OPEN_ALWAYS : OPEN_EXISTING;
38 DWORD share = options_ & WRITE_ACCESS ? FILE_SHARE_WRITE : FILE_SHARE_READ;
39 share = options_ & SHARED_MAPPING ? share : 0;
40 info_->hFile = CreateFile(path_.c_str(), mode, share, NULL, disposition,
41 FILE_ATTRIBUTE_NORMAL, NULL);
42 if (info_->hFile == INVALID_HANDLE_VALUE) {
43 delete info_;
44 info_ = NULL;
Reid Spencer05545752006-08-25 21:37:17 +000045 return MakeErrMsg(ErrMsg,
46 std::string("Can't open file: ") + path_.toString());
Reid Spencer8545fc12004-10-14 03:05:59 +000047 }
48
49 LARGE_INTEGER size;
50 if (!GetFileSizeEx(info_->hFile, &size) ||
51 (info_->size = size_t(size.QuadPart), info_->size != size.QuadPart)) {
52 CloseHandle(info_->hFile);
53 delete info_;
54 info_ = NULL;
Reid Spencer05545752006-08-25 21:37:17 +000055 return MakeErrMsg(ErrMsg,
56 std::string("Can't get size of file: ") + path_.toString());
Reid Spencer8545fc12004-10-14 03:05:59 +000057 }
Anton Korobeynikov7d515442006-09-01 20:35:17 +000058
59 return false;
Reid Spencer97374922004-10-04 11:08:32 +000060}
61
62void MappedFile::terminate() {
Reid Spencer8545fc12004-10-14 03:05:59 +000063 unmap();
64 if (info_->hFile != INVALID_HANDLE_VALUE)
65 CloseHandle(info_->hFile);
66 delete info_;
67 info_ = NULL;
Reid Spencer97374922004-10-04 11:08:32 +000068}
69
70void MappedFile::unmap() {
Reid Spencer8545fc12004-10-14 03:05:59 +000071 assert(info_ && "MappedFile not initialized");
72 if (isMapped()) {
73 UnmapViewOfFile(base_);
74 base_ = NULL;
75 }
76 if (info_->hMapping != INVALID_HANDLE_VALUE) {
77 CloseHandle(info_->hMapping);
78 info_->hMapping = NULL;
79 }
Reid Spencer97374922004-10-04 11:08:32 +000080}
81
Reid Spencer05545752006-08-25 21:37:17 +000082void* MappedFile::map(std::string* ErrMsg) {
Reid Spencer8545fc12004-10-14 03:05:59 +000083 if (!isMapped()) {
84 DWORD prot = PAGE_READONLY;
85 if (options_ & EXEC_ACCESS)
86 prot = SEC_IMAGE;
87 else if (options_ & WRITE_ACCESS)
88 prot = PAGE_READWRITE;
89 info_->hMapping = CreateFileMapping(info_->hFile, NULL, prot, 0, 0, NULL);
Reid Spencer05545752006-08-25 21:37:17 +000090 if (info_->hMapping == NULL) {
91 MakeErrMsg(ErrMsg, std::string("Can't map file: ") + path_.toString());
92 return 0;
93 }
Reid Spencer8545fc12004-10-14 03:05:59 +000094
95 prot = (options_ & WRITE_ACCESS) ? FILE_MAP_WRITE : FILE_MAP_READ;
96 base_ = MapViewOfFileEx(info_->hMapping, prot, 0, 0, 0, NULL);
97 if (base_ == NULL) {
98 CloseHandle(info_->hMapping);
99 info_->hMapping = NULL;
Reid Spencer05545752006-08-25 21:37:17 +0000100 MakeErrMsg(ErrMsg, std::string("Can't map file: ") + path_.toString());
101 return 0;
Reid Spencer8545fc12004-10-14 03:05:59 +0000102 }
103 }
104 return base_;
Reid Spencer97374922004-10-04 11:08:32 +0000105}
106
Jeff Cohen32653692004-12-13 06:26:35 +0000107size_t MappedFile::size() const {
Reid Spencer8545fc12004-10-14 03:05:59 +0000108 assert(info_ && "MappedFile not initialized");
109 return info_->size;
Reid Spencer97374922004-10-04 11:08:32 +0000110}
111
Reid Spencer05545752006-08-25 21:37:17 +0000112bool MappedFile::size(size_t new_size, std::string* ErrMsg) {
Reid Spencer8545fc12004-10-14 03:05:59 +0000113 assert(info_ && "MappedFile not initialized");
114
115 // Take the mapping out of memory.
116 unmap();
117
118 // Adjust the new_size to a page boundary.
119 size_t pagesizem1 = Process::GetPageSize() - 1;
120 new_size = (new_size + pagesizem1) & ~pagesizem1;
121
122 // If the file needs to be extended, do so.
123 if (new_size > info_->size) {
124 LARGE_INTEGER eof;
125 eof.QuadPart = new_size;
126 if (!SetFilePointerEx(info_->hFile, eof, NULL, FILE_BEGIN))
Reid Spencer05545752006-08-25 21:37:17 +0000127 return MakeErrMsg(ErrMsg,
128 std::string("Can't set end of file: ") + path_.toString());
Reid Spencer8545fc12004-10-14 03:05:59 +0000129 if (!SetEndOfFile(info_->hFile))
Reid Spencer05545752006-08-25 21:37:17 +0000130 return MakeErrMsg(ErrMsg,
131 std::string("Can't set end of file: ") + path_.toString());
Reid Spencer8545fc12004-10-14 03:05:59 +0000132 info_->size = new_size;
133 }
134
135 // Remap the file.
Reid Spencer05545752006-08-25 21:37:17 +0000136 return map(ErrMsg);
Reid Spencer8545fc12004-10-14 03:05:59 +0000137}
138
Reid Spencer97374922004-10-04 11:08:32 +0000139}
140