Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/link/internal/ld/outbuf_mmap.go

Documentation: cmd/link/internal/ld

     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
     6  // +build aix darwin dragonfly freebsd linux netbsd openbsd
     7  
     8  package ld
     9  
    10  import (
    11  	"syscall"
    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) (err error) {
    18  	oldlen := len(out.buf)
    19  	if oldlen != 0 {
    20  		out.munmap()
    21  	}
    22  
    23  	for {
    24  		if err = out.fallocate(filesize); err != syscall.EINTR {
    25  			break
    26  		}
    27  	}
    28  	if err != nil {
    29  		// Some file systems do not support fallocate. We ignore that error as linking
    30  		// can still take place, but you might SIGBUS when you write to the mmapped
    31  		// area.
    32  		if err != syscall.ENOTSUP && err != syscall.EPERM && err != errNoFallocate {
    33  			return err
    34  		}
    35  	}
    36  	err = out.f.Truncate(int64(filesize))
    37  	if err != nil {
    38  		Exitf("resize output file failed: %v", err)
    39  	}
    40  	out.buf, err = syscall.Mmap(int(out.f.Fd()), 0, int(filesize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED|syscall.MAP_FILE)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	// copy heap to new mapping
    46  	if uint64(oldlen+len(out.heap)) > filesize {
    47  		panic("mmap size too small")
    48  	}
    49  	copy(out.buf[oldlen:], out.heap)
    50  	out.heap = out.heap[:0]
    51  	return nil
    52  }
    53  
    54  func (out *OutBuf) munmap() {
    55  	if out.buf == nil {
    56  		return
    57  	}
    58  	syscall.Munmap(out.buf)
    59  	out.buf = nil
    60  }
    61  

View as plain text