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