github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/ld/outbuf_mmap.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 //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris 6 7 package ld 8 9 import ( 10 "syscall" 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) (err error) { 17 oldlen := len(out.buf) 18 if oldlen != 0 { 19 out.munmap() 20 } 21 22 for { 23 if err = out.fallocate(filesize); err != syscall.EINTR { 24 break 25 } 26 } 27 if err != nil { 28 // Some file systems do not support fallocate. We ignore that error as linking 29 // can still take place, but you might SIGBUS when you write to the mmapped 30 // area. 31 if err != syscall.ENOTSUP && err != syscall.EPERM && err != errNoFallocate { 32 return err 33 } 34 } 35 err = out.f.Truncate(int64(filesize)) 36 if err != nil { 37 Exitf("resize output file failed: %v", err) 38 } 39 out.buf, err = syscall.Mmap(int(out.f.Fd()), 0, int(filesize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED|syscall.MAP_FILE) 40 if err != nil { 41 return err 42 } 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 syscall.Munmap(out.buf) 58 out.buf = nil 59 }