loader: anonymous mmap passes fd `0` and fails with `EINVAL` on BSD
Describe the bug
loader/mmap_unix.go currently invokes SYS_MMAP with MAP_ANON | MAP_PRIVATE but passes 0 as the fd argument:
syscall.RawSyscall6(
syscall.SYS_MMAP,
0,
uintptr(nb),
_RW,
_AP,
0, // fd
0, // offset
)This causes JIT memory allocation to fail with EINVAL on BSD distros.
The earlier fix for #564, merged as #567, changed the build constraints so that this implementation is selected on additional non-Windows systems. It resolved the compilation failure, but exposed a runtime incompatibility in the mmap arguments.
Platform compatibility
Using -1 is the portable choice for platforms on which this POSIX/BSD-style anonymous mmap implementation is used:
- FreeBSD requires
fd == -1andoffset == 0forMAP_ANON. FreeBSD mmap(2) - OpenBSD requires
fd == -1. OpenBSD mmap(2) - DragonFly BSD requires
fd == -1. DragonFly mmap(2) - Linux ignores
fdforMAP_ANONYMOUS, but its documentation recommends-1for portable applications and says theoffsetshould be zero. man7.org Linux mmap(2) - Darwin permits
-1when no Mach VM flags are being supplied through the descriptor argument. Apple Documentation Archive mmap(2)
Consequently, changing the descriptor from 0 to -1 fixes BSD issue without changing the anonymous-mapping behavior on Linux or macOS.
Expected behavior
For an anonymous mapping, the call should use:
mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);In a raw Go syscall, -1 can be represented as ^uintptr(0)
Sonic version: latest
Additional context
Related work:
- #564 reported that the mmap implementation was not selected for BSD targets.
- #567 broadened the build constraint, but did not change the mmap descriptor.
- #902 contains a proposed descriptor fix and appears to address this runtime issue.
Source: bytedance/sonic