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 }