github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/platform/mmap_unix.go (about)

     1  //go:build darwin || linux || freebsd
     2  
     3  package platform
     4  
     5  import (
     6  	"syscall"
     7  	"unsafe"
     8  )
     9  
    10  const (
    11  	mmapProtAMD64 = syscall.PROT_READ | syscall.PROT_WRITE | syscall.PROT_EXEC
    12  	mmapProtARM64 = syscall.PROT_READ | syscall.PROT_WRITE
    13  )
    14  
    15  func munmapCodeSegment(code []byte) error {
    16  	return syscall.Munmap(code)
    17  }
    18  
    19  // mmapCodeSegmentAMD64 gives all read-write-exec permission to the mmap region
    20  // to enter the function. Otherwise, segmentation fault exception is raised.
    21  func mmapCodeSegmentAMD64(size int) ([]byte, error) {
    22  	// The region must be RWX: RW for writing native codes, X for executing the region.
    23  	return mmapCodeSegment(size, mmapProtAMD64)
    24  }
    25  
    26  // mmapCodeSegmentARM64 cannot give all read-write-exec permission to the mmap region.
    27  // Otherwise, the mmap systemcall would raise an error. Here we give read-write
    28  // to the region so that we can write contents at call-sites. Callers are responsible to
    29  // execute MprotectRX on the returned buffer.
    30  func mmapCodeSegmentARM64(size int) ([]byte, error) {
    31  	// The region must be RW: RW for writing native codes.
    32  	return mmapCodeSegment(size, mmapProtARM64)
    33  }
    34  
    35  // MprotectRX is like syscall.Mprotect with RX permission, defined locally so that freebsd compiles.
    36  func MprotectRX(b []byte) (err error) {
    37  	var _p0 unsafe.Pointer
    38  	if len(b) > 0 {
    39  		_p0 = unsafe.Pointer(&b[0])
    40  	}
    41  	const prot = syscall.PROT_READ | syscall.PROT_EXEC
    42  	_, _, e1 := syscall.Syscall(syscall.SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
    43  	if e1 != 0 {
    44  		err = syscall.Errno(e1)
    45  	}
    46  	return
    47  }