github.com/tetratelabs/wazero@v1.2.1/internal/platform/platform.go (about)

     1  // Package platform includes runtime-specific code needed for the compiler or otherwise.
     2  //
     3  // Note: This is a dependency-free alternative to depending on parts of Go's x/sys.
     4  // See /RATIONALE.md for more context.
     5  package platform
     6  
     7  import (
     8  	"runtime"
     9  	"strings"
    10  )
    11  
    12  // TODO: IsAtLeastGo120
    13  var IsGo120 = strings.Contains(runtime.Version(), "go1.20")
    14  
    15  // archRequirementsVerified is set by platform-specific init to true if the platform is supported
    16  var archRequirementsVerified bool
    17  
    18  // CompilerSupported is exported for tests and includes constraints here and also the assembler.
    19  func CompilerSupported() bool {
    20  	switch runtime.GOOS {
    21  	case "darwin", "windows", "linux", "freebsd":
    22  	default:
    23  		return false
    24  	}
    25  
    26  	return archRequirementsVerified
    27  }
    28  
    29  // MmapCodeSegment copies the code into the executable region and returns the byte slice of the region.
    30  //
    31  // See https://man7.org/linux/man-pages/man2/mmap.2.html for mmap API and flags.
    32  func MmapCodeSegment(size int) ([]byte, error) {
    33  	if size == 0 {
    34  		panic("BUG: MmapCodeSegment with zero length")
    35  	}
    36  	if runtime.GOARCH == "amd64" {
    37  		return mmapCodeSegmentAMD64(size)
    38  	} else {
    39  		return mmapCodeSegmentARM64(size)
    40  	}
    41  }
    42  
    43  // RemapCodeSegment reallocates the memory mapping of an existing code segment
    44  // to increase its size. The previous code mapping is unmapped and must not be
    45  // reused after the function returns.
    46  //
    47  // This is similar to mremap(2) on linux, and emulated on platforms which do not
    48  // have this syscall.
    49  //
    50  // See https://man7.org/linux/man-pages/man2/mremap.2.html
    51  func RemapCodeSegment(code []byte, size int) ([]byte, error) {
    52  	if size < len(code) {
    53  		panic("BUG: RemapCodeSegment with size less than code")
    54  	}
    55  	if code == nil {
    56  		return MmapCodeSegment(size)
    57  	}
    58  	if runtime.GOARCH == "amd64" {
    59  		return remapCodeSegmentAMD64(code, size)
    60  	} else {
    61  		return remapCodeSegmentARM64(code, size)
    62  	}
    63  }
    64  
    65  // MunmapCodeSegment unmaps the given memory region.
    66  func MunmapCodeSegment(code []byte) error {
    67  	if len(code) == 0 {
    68  		panic("BUG: MunmapCodeSegment with zero length")
    69  	}
    70  	return munmapCodeSegment(code)
    71  }
    72  
    73  // mustMunmapCodeSegment panics instead of returning an error to the
    74  // application.
    75  //
    76  // # Why panic?
    77  //
    78  // It is less disruptive to the application to leak the previous block if it
    79  // could be unmapped than to leak the new block and return an error.
    80  // Realistically, either scenarios are pretty hard to debug, so we panic.
    81  func mustMunmapCodeSegment(code []byte) {
    82  	if err := munmapCodeSegment(code); err != nil {
    83  		panic(err)
    84  	}
    85  }