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