github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/ld/outbuf_windows.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ld 6 7 import ( 8 "github.com/bir3/gocompiler/src/internal/unsafeheader" 9 "syscall" 10 "unsafe" 11 ) 12 13 // Mmap maps the output file with the given size. It unmaps the old mapping 14 // if it is already mapped. It also flushes any in-heap data to the new 15 // mapping. 16 func (out *OutBuf) Mmap(filesize uint64) error { 17 oldlen := len(out.buf) 18 if oldlen != 0 { 19 out.munmap() 20 } 21 22 err := out.f.Truncate(int64(filesize)) 23 if err != nil { 24 Exitf("resize output file failed: %v", err) 25 } 26 27 low, high := uint32(filesize), uint32(filesize>>32) 28 fmap, err := syscall.CreateFileMapping(syscall.Handle(out.f.Fd()), nil, syscall.PAGE_READWRITE, high, low, nil) 29 if err != nil { 30 return err 31 } 32 defer syscall.CloseHandle(fmap) 33 34 ptr, err := syscall.MapViewOfFile(fmap, syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, uintptr(filesize)) 35 if err != nil { 36 return err 37 } 38 bufHdr := (*unsafeheader.Slice)(unsafe.Pointer(&out.buf)) 39 bufHdr.Data = unsafe.Pointer(ptr) 40 bufHdr.Len = int(filesize) 41 bufHdr.Cap = int(filesize) 42 43 // copy heap to new mapping 44 if uint64(oldlen+len(out.heap)) > filesize { 45 panic("mmap size too small") 46 } 47 copy(out.buf[oldlen:], out.heap) 48 out.heap = out.heap[:0] 49 return nil 50 } 51 52 func (out *OutBuf) munmap() { 53 if out.buf == nil { 54 return 55 } 56 // Apparently unmapping without flush may cause ACCESS_DENIED error 57 // (see issue 38440). 58 err := syscall.FlushViewOfFile(uintptr(unsafe.Pointer(&out.buf[0])), 0) 59 if err != nil { 60 Exitf("FlushViewOfFile failed: %v", err) 61 } 62 // Issue 44817: apparently the call below may be needed (according 63 // to the Windows docs) in addition to the FlushViewOfFile call 64 // above, " ... to flush all the dirty pages plus the metadata for 65 // the file and ensure that they are physically written to disk". 66 // Windows DOC links: 67 // 68 // https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-flushviewoffile 69 // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-flushfilebuffers 70 err = syscall.FlushFileBuffers(syscall.Handle(out.f.Fd())) 71 if err != nil { 72 Exitf("FlushFileBuffers failed: %v", err) 73 } 74 err = syscall.UnmapViewOfFile(uintptr(unsafe.Pointer(&out.buf[0]))) 75 out.buf = nil 76 if err != nil { 77 Exitf("UnmapViewOfFile failed: %v", err) 78 } 79 }