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