1
1
mirror of https://github.com/rui314/mold.git synced 2024-08-17 08:50:56 +03:00

Merge pull request #1201 from nga888/win-mem-map-output-file

Add "basic" support for memory mapping to Windows OutputFile
This commit is contained in:
Rui Ueyama 2024-03-16 11:35:25 +09:00 committed by GitHub
commit 8375741489
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -6,6 +6,66 @@
namespace mold {
template <typename Context>
class MemoryMappedOutputFile : public OutputFile<Context> {
public:
MemoryMappedOutputFile(Context &ctx, std::string path, i64 filesize, i64 perm)
: OutputFile<Context>(path, filesize, true) {
// TODO: use intermediate temporary file for output.
DWORD file_attrs =
(perm & 0200) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_READONLY;
file_handle =
CreateFileA(path.c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, CREATE_ALWAYS, file_attrs, nullptr);
if (file_handle == INVALID_HANDLE_VALUE)
Fatal(ctx) << "cannot open " << path << ": " << GetLastError();
HANDLE mapping_handle = CreateFileMapping(
file_handle, nullptr, PAGE_READWRITE, 0, filesize, nullptr);
if (!mapping_handle)
Fatal(ctx) << path << ": CreateFileMapping failed: " << GetLastError();
this->buf =
(u8 *)MapViewOfFile(mapping_handle, FILE_MAP_WRITE, 0, 0, filesize);
CloseHandle(mapping_handle);
if (!this->buf)
Fatal(ctx) << path << ": MapViewOfFile failed: " << GetLastError();
mold::output_buffer_start = this->buf;
mold::output_buffer_end = this->buf + filesize;
}
~MemoryMappedOutputFile() {
if (file_handle != INVALID_HANDLE_VALUE)
CloseHandle(file_handle);
}
void close(Context &ctx) override {
Timer t(ctx, "close_file");
UnmapViewOfFile(this->buf);
if (!this->buf2.empty()) {
if (SetFilePointer(file_handle, 0, nullptr, FILE_END) ==
INVALID_SET_FILE_POINTER)
Fatal(ctx) << this->path
<< ": SetFilePointer failed: " << GetLastError();
DWORD written;
if (!WriteFile(file_handle, this->buf2.data(), this->buf2.size(),
&written, nullptr))
Fatal(ctx) << this->path << ": WriteFile failed: " << GetLastError();
}
CloseHandle(file_handle);
file_handle = INVALID_HANDLE_VALUE;
}
private:
HANDLE file_handle;
};
template <typename Context>
std::unique_ptr<OutputFile<Context>>
OutputFile<Context>::open(Context &ctx, std::string path, i64 filesize, i64 perm) {
@ -14,7 +74,26 @@ OutputFile<Context>::open(Context &ctx, std::string path, i64 filesize, i64 perm
if (path.starts_with('/') && !ctx.arg.chroot.empty())
path = ctx.arg.chroot + "/" + path_clean(path);
OutputFile<Context> *file = new MallocOutputFile(ctx, path, filesize, perm);
bool is_special = false;
if (path == "-") {
is_special = true;
} else {
HANDLE file_handle =
CreateFileA(path.c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file_handle != INVALID_HANDLE_VALUE) {
if (GetFileType(file_handle) != FILE_TYPE_DISK)
is_special = true;
CloseHandle(file_handle);
}
}
OutputFile<Context> *file;
if (is_special)
file = new MallocOutputFile(ctx, path, filesize, perm);
else
file = new MemoryMappedOutputFile(ctx, path, filesize, perm);
if (ctx.arg.filler != -1)
memset(file->buf, ctx.arg.filler, filesize);