wasi preview 2 support (#4027)

* all: wasip2 support

Co-authored-by: Randy Reddig <randy.reddig@fastly.com>
This commit is contained in:
Damian Gryski
2024-07-02 07:02:03 -07:00
committed by GitHub
parent f18c6e342f
commit 9cb263479c
125 changed files with 7035 additions and 154 deletions
+59
View File
@@ -0,0 +1,59 @@
//go:build darwin || nintendoswitch || wasip1
package syscall
import (
"unsafe"
)
func Environ() []string {
// This function combines all the environment into a single allocation.
// While this optimizes for memory usage and garbage collector
// overhead, it does run the risk of potentially pinning a "large"
// allocation if a user holds onto a single environment variable or
// value. Having each variable be its own allocation would make the
// trade-off in the other direction.
// calculate total memory required
var length uintptr
var vars int
for environ := libc_environ; *environ != nil; {
length += libc_strlen(*environ)
vars++
environ = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))
}
// allocate our backing slice for the strings
b := make([]byte, length)
// and the slice we're going to return
envs := make([]string, 0, vars)
// loop over the environment again, this time copying over the data to the backing slice
for environ := libc_environ; *environ != nil; {
length = libc_strlen(*environ)
// construct a Go string pointing at the libc-allocated environment variable data
var envVar string
rawEnvVar := (*struct {
ptr unsafe.Pointer
length uintptr
})(unsafe.Pointer(&envVar))
rawEnvVar.ptr = *environ
rawEnvVar.length = length
// pull off the number of bytes we need for this environment variable
var bs []byte
bs, b = b[:length], b[length:]
// copy over the bytes to the Go heap
copy(bs, envVar)
// convert trimmed slice to string
s := *(*string)(unsafe.Pointer(&bs))
// add s to our list of environment variables
envs = append(envs, s)
// environ++
environ = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))
}
return envs
}
//go:extern environ
var libc_environ *unsafe.Pointer
+11
View File
@@ -0,0 +1,11 @@
//go:build wasip2
package syscall
func Environ() []string {
var env []string
for k, v := range libc_envs {
env = append(env, k+"="+v)
}
return env
}
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build !wasip1 && !darwin
//go:build !wasip1 && !wasip2 && !darwin
package syscall
+8
View File
@@ -0,0 +1,8 @@
//go:build wasip1
package syscall
// Use a go:extern definition to access the errno from wasi-libc
//
//go:extern errno
var libcErrno Errno
+7
View File
@@ -0,0 +1,7 @@
//go:build wasip2
package syscall
// The errno for libc_wasip2.go
var libcErrno Errno
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build baremetal || (wasm && !wasip1) || wasm_unknown
//go:build baremetal || (wasm && !wasip1 && !wasip2) || wasm_unknown
// This file emulates some file-related functions that are only available
// under a real operating system.
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build !(baremetal || (wasm && !wasip1) || wasm_unknown)
//go:build !(baremetal || (wasm && !wasip1 && !wasip2) || wasm_unknown)
// This file assumes there is a libc available that runs on a real operating
// system.
File diff suppressed because it is too large Load Diff
+1 -53
View File
@@ -1,4 +1,4 @@
//go:build darwin || nintendoswitch || wasi || wasip1
//go:build darwin || nintendoswitch || wasip1 || wasip2
package syscall
@@ -260,55 +260,6 @@ func Mprotect(b []byte, prot int) (err error) {
return
}
func Environ() []string {
// This function combines all the environment into a single allocation.
// While this optimizes for memory usage and garbage collector
// overhead, it does run the risk of potentially pinning a "large"
// allocation if a user holds onto a single environment variable or
// value. Having each variable be its own allocation would make the
// trade-off in the other direction.
// calculate total memory required
var length uintptr
var vars int
for environ := libc_environ; *environ != nil; {
length += libc_strlen(*environ)
vars++
environ = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))
}
// allocate our backing slice for the strings
b := make([]byte, length)
// and the slice we're going to return
envs := make([]string, 0, vars)
// loop over the environment again, this time copying over the data to the backing slice
for environ := libc_environ; *environ != nil; {
length = libc_strlen(*environ)
// construct a Go string pointing at the libc-allocated environment variable data
var envVar string
rawEnvVar := (*struct {
ptr unsafe.Pointer
length uintptr
})(unsafe.Pointer(&envVar))
rawEnvVar.ptr = *environ
rawEnvVar.length = length
// pull off the number of bytes we need for this environment variable
var bs []byte
bs, b = b[:length], b[length:]
// copy over the bytes to the Go heap
copy(bs, envVar)
// convert trimmed slice to string
s := *(*string)(unsafe.Pointer(&bs))
// add s to our list of environment variables
envs = append(envs, s)
// environ++
environ = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))
}
return envs
}
// BytePtrFromString returns a pointer to a NUL-terminated array of
// bytes containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
@@ -445,6 +396,3 @@ func libc_readlink(path *byte, buf *byte, count uint) int
//
//export unlink
func libc_unlink(pathname *byte) int32
//go:extern environ
var libc_environ *unsafe.Pointer
@@ -1,4 +1,4 @@
//go:build wasip1
//go:build wasip1 || wasip2
package syscall
@@ -70,9 +70,10 @@ const (
__WASI_FILETYPE_SYMBOLIC_LINK = 7
// ../../lib/wasi-libc/libc-bottom-half/headers/public/__header_fcntl.h
O_RDONLY = 0x04000000
O_WRONLY = 0x10000000
O_RDWR = O_RDONLY | O_WRONLY
O_NOFOLLOW = 0x01000000
O_RDONLY = 0x04000000
O_WRONLY = 0x10000000
O_RDWR = O_RDONLY | O_WRONLY
O_CREAT = __WASI_OFLAGS_CREAT << 12
O_TRUNC = __WASI_OFLAGS_TRUNC << 12
@@ -118,11 +119,9 @@ const (
PATH_MAX = 4096
)
//go:extern errno
var libcErrno uintptr
func getErrno() error {
return Errno(libcErrno)
// libcErrno is the errno from wasi-libc for wasip1 and the errno for libc_wasip2 for wasip2
return libcErrno
}
func (e Errno) Is(target error) bool {
@@ -195,6 +194,7 @@ const (
ENOTCONN Errno = 53 /* Socket is not connected */
ENOTDIR Errno = 54 /* Not a directory */
ENOTEMPTY Errno = 55 /* Directory not empty */
ENOTRECOVERABLE Errno = 56 /* State not recoverable */
ENOTSOCK Errno = 57 /* Socket operation on non-socket */
ESOCKTNOSUPPORT Errno = 58 /* Socket type not supported */
EOPNOTSUPP Errno = 58 /* Operation not supported on transport endpoint */
@@ -213,10 +213,15 @@ const (
ESRCH Errno = 71 /* No such process */
ESTALE Errno = 72
ETIMEDOUT Errno = 73 /* Connection timed out */
ETXTBSY Errno = 74 /* Text file busy */
EXDEV Errno = 75 /* Cross-device link */
ENOTCAPABLE Errno = 76 /* Extension: Capabilities insufficient. */
EWASIERROR Errno = 255 /* Unknown WASI error */
)
// TODO(ydnar): remove Timespec for WASI Preview 2 (seconds is uint64).
//
// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__struct_timespec.h
type Timespec struct {
Sec int32
@@ -411,6 +416,11 @@ type Utsname struct {
Domainname [65]int8
}
//go:linkname faccessat syscall.Faccessat
func faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
return ENOSYS
}
// Stub Utsname, needed because WASI pretends to be linux/arm.
func Uname(buf *Utsname) (err error)