github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/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 mmapMemory(size int) ([]byte, error) { 16 return syscall.Mmap( 17 -1, 18 0, 19 size, 20 syscall.PROT_READ|syscall.PROT_WRITE, 21 // Anonymous as this is not an actual file, but a memory, 22 // Private as this is in-process memory region. 23 syscall.MAP_ANON|syscall.MAP_PRIVATE, 24 ) 25 } 26 27 func munmapCodeSegment(code []byte) error { 28 return syscall.Munmap(code) 29 } 30 31 // mmapCodeSegmentAMD64 gives all read-write-exec permission to the mmap region 32 // to enter the function. Otherwise, segmentation fault exception is raised. 33 func mmapCodeSegmentAMD64(size int) ([]byte, error) { 34 // The region must be RWX: RW for writing native codes, X for executing the region. 35 return mmapCodeSegment(size, mmapProtAMD64) 36 } 37 38 // mmapCodeSegmentARM64 cannot give all read-write-exec permission to the mmap region. 39 // Otherwise, the mmap systemcall would raise an error. Here we give read-write 40 // to the region so that we can write contents at call-sites. Callers are responsible to 41 // execute MprotectRX on the returned buffer. 42 func mmapCodeSegmentARM64(size int) ([]byte, error) { 43 // The region must be RW: RW for writing native codes. 44 return mmapCodeSegment(size, mmapProtARM64) 45 } 46 47 // MprotectRX is like syscall.Mprotect with RX permission, defined locally so that freebsd compiles. 48 func MprotectRX(b []byte) (err error) { 49 var _p0 unsafe.Pointer 50 if len(b) > 0 { 51 _p0 = unsafe.Pointer(&b[0]) 52 } 53 const prot = syscall.PROT_READ | syscall.PROT_EXEC 54 _, _, e1 := syscall.Syscall(syscall.SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) 55 if e1 != 0 { 56 err = syscall.Errno(e1) 57 } 58 return 59 }