This moves the platform-specific runtime code (currently only used by the compiler) into its own package. Specifically, this moves the mmap logic, and in doing so makes it easier to test, for example new operating systems. This also backfills missing RATIONALE about x/sys and hints at a future possibility to allow a plugin. However, the next step is to get FreeBSD working natively on the compiler without any additional dependencies. See #607 Signed-off-by: Adrian Cole <adrian@tetrate.io>
58 lines
1.6 KiB
Go
58 lines
1.6 KiB
Go
//go:build !windows
|
|
|
|
package platform
|
|
|
|
import (
|
|
"syscall"
|
|
)
|
|
|
|
func munmapCodeSegment(code []byte) error {
|
|
return syscall.Munmap(code)
|
|
}
|
|
|
|
// mmapCodeSegmentAMD64 gives all read-write-exec permission to the mmap region
|
|
// to enter the function. Otherwise, segmentation fault exception is raised.
|
|
func mmapCodeSegmentAMD64(code []byte) ([]byte, error) {
|
|
mmapFunc, err := syscall.Mmap(
|
|
-1,
|
|
0,
|
|
len(code),
|
|
// The region must be RWX: RW for writing native codes, X for executing the region.
|
|
syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC,
|
|
// Anonymous as this is not an actual file, but a memory,
|
|
// Private as this is in-process memory region.
|
|
syscall.MAP_ANON|syscall.MAP_PRIVATE,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
copy(mmapFunc, code)
|
|
return mmapFunc, nil
|
|
}
|
|
|
|
// mmapCodeSegmentARM64 cannot give all read-write-exec permission to the mmap region.
|
|
// Otherwise, the mmap systemcall would raise an error. Here we give read-write
|
|
// to the region at first, write the native code and then change the perm to
|
|
// read-exec so we can execute the native code.
|
|
func mmapCodeSegmentARM64(code []byte) ([]byte, error) {
|
|
mmapFunc, err := syscall.Mmap(
|
|
-1,
|
|
0,
|
|
len(code),
|
|
// The region must be RW: RW for writing native codes.
|
|
syscall.PROT_READ|syscall.PROT_WRITE,
|
|
// Anonymous as this is not an actual file, but a memory,
|
|
// Private as this is in-process memory region.
|
|
syscall.MAP_ANON|syscall.MAP_PRIVATE,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
copy(mmapFunc, code)
|
|
|
|
// Then we're done with writing code, change the permission to RX.
|
|
err = syscall.Mprotect(mmapFunc, syscall.PROT_READ|syscall.PROT_EXEC)
|
|
return mmapFunc, err
|
|
}
|