Commit Graph

455 Commits

Author SHA1 Message Date
Crypt Keeper
713e187796 fs: extracts syscallfs.ReaderAtOffset for WASI and gojs (#1037)
This extracts a utility `syscallfs.ReaderAtOffset()` to allow WASI and
gojs to re-use the same logic to implement `syscall.Pread`.

What's different than before is that if WASI passes multiple iovecs an
emulated `ReaderAt` will seek to the read position on each call to
`Read` vs once per loop. This was a design decision to keep the call
sites compatible between files that implement ReaderAt and those that
emulate them with Seeker (e.g. avoid the need for a read-scoped closer/
defer function). The main use case for emulation is `embed.file`, whose
seek function is cheap, so there's little performance impact to this.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-15 17:30:45 -08:00
Nuno Cruces
59076bccf5 fs: Adds fd_sync (#1026)
Signed-off-by: Nuno Cruces <ncruces@users.noreply.github.com>
2023-01-14 07:16:14 +08:00
Crypt Keeper
105cdcdef7 cli: rewrites compositeFS to syscallfs and adds read-only (:ro) mounts (#1030)
This rewrites compositeFS to syscallfs.FS following wasi-sdk preopen
rules. Notably, this allows use of read-only mounts now.

For example,
```bash
$ GOOS=js GOARCH=wasm bin/go test -c -o template.wasm text/template
$ wazero run -mount=src/text/template:/ -mount=/tmp:/tmp template.wasm -test.v
=== RUN   TestExecute
--- PASS: TestExecute (0.07s)
--snip--
```

This is the first step to native WASI handling of multiple pre-opens.
After this change, it is still the case that there's only one pre-open
FD visible to wasm. A later change will make it possible for WASI to see
multiple pre-opens while `GOOS=js` which doesn't use preopens, remains
on a rootFS.

A future PR may need to add a CLI flag to disable escaping directories,
(e.g. make ../.. EINVAL), similar to `fs.FS` in Go. The simplest way to
allow this is to use a host-side RootFS even in WASI, and wrap that with
a `syscallfs` filename filter.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-13 15:50:11 +08:00
Takeshi Yoneda
2df84c679c ci: adds -skip flag to the race tests (#1023)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-11 12:23:09 +09:00
Crypt Keeper
3fc5392570 fs: fixes windows fstest.FS and consolidates more (#1019)
This works around a known glitch in windows where directory entry stat
doesn't match its corresponding file stat (namely times don't). It
consolidates more test files, in the process, to ensure we are more
likely to trigger issues like this earlier.

Future work will finish the last couple places where we still use go's
fstest.MapFS internally, as well introduce stat tests at the syscallfs
abstraction: right now, most tests are still only defined in WASI.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-10 14:12:18 +08:00
Takeshi Yoneda
b63d4e6dcd Deletes namespace API (#1018)
Formerly, we introduced `wazero.Namespace` to help avoid module name or import conflicts while still sharing the runtime's compilation cache. Now that we've introduced `CompilationCache` `wazero.Namespace` is no longer necessary. By removing it, we reduce the conceptual load on end users as well internal complexity. Since most users don't use namespace, the change isn't very impactful.

Users who are only trying to avoid module name conflict can generate a name like below instead of using multiple runtimes:

```go
moduleName := fmt.Sprintf("%d", atomic.AddUint64(&m.instanceCounter, 1))
module, err := runtime.InstantiateModule(ctx, compiled, config.WithName(moduleName))
```

For `HostModuleBuilder` users, we no longer take `Namespace` as the last parameter of `Instantiate` method: 

```diff
 	// log to the console.
 	_, err := r.NewHostModuleBuilder("env").
 		NewFunctionBuilder().WithFunc(logString).Export("log").
-		Instantiate(ctx, r)
+		Instantiate(ctx)
 	if err != nil {
 		log.Panicln(err)
 	}
```


The following is an example diff a use of namespace can use to keep compilation cache while also ensuring their modules don't conflict:

```diff

 func useMultipleRuntimes(ctx context.Context, cache) {
-	r := wazero.NewRuntime(ctx)
+	cache := wazero.NewCompilationCache()
 
 	for i := 0; i < N; i++ {
-		// Create a new namespace to instantiate modules into.
-		ns := r.NewNamespace(ctx) // Note: this is closed when the Runtime is
+		r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().WithCompilationCache(cache))
 
 		// Instantiate a new "env" module which exports a stateful function.
 		_, err := r.NewHostModuleBuilder("env").
```

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-10 14:11:46 +09:00
Crypt Keeper
f1fdeb2565 fs: fixes timebomb on or'd flags with O_RDONLY (#1017)
@achille-roussel mentioned on chat that we have an accident waiting to
happen. This fixes it and backfills the missing test.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-10 08:51:10 +08:00
Takeshi Yoneda
35500f9b85 Introduces Cache API (#1016)
This introduces the new API wazero.Cache interface which can be passed to wazero.RuntimeConfig. 
Users can configure this to share the underlying compilation cache across multiple wazero.Runtime. 
And along the way, this deletes the experimental file cache API as it's replaced by this new API.

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
Co-authored-by: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com>
2023-01-10 09:32:42 +09:00
Adrian Cole
70b87165e7 Skips broken tests from accidental push
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-09 16:47:38 +08:00
Adrian Cole
e1a8ed5a84 Adds fstest and ensures syscallfs implementations pass it
This consolidates test files and ensures our various implementations of
`syscallfs.FS` pass `fstest.TestFS`.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-09 16:21:06 +08:00
Crypt Keeper
8f0967e0e8 fs: Adds tests to prove we allow fs.FS to create new files (#1015)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-09 12:31:02 +08:00
Takeshi Yoneda
e90e1985f3 Moves more func inst fields to comptime objects (#927)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-09 12:25:02 +09:00
Takeshi Yoneda
8e78f3fb04 compiler: deletes function.stackPointerCeil to reduce memory size per instance (#1012)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-06 15:44:57 +09:00
Takeshi Yoneda
6eb1e5d9fb arm64: fixes runtimeValueType for i32.wrap_i64 (#1011)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-06 14:28:48 +09:00
Crypt Keeper
bedde6dc7a Clarifies at semantics and preopen semantics in WASI (#1009)
This adds FS.Path which holds the pre-open path currently only used in
WASI. It also fixes a TODO where we didn't know for sure if the FD
parameter for `path_` functions must always be a pre-open. The TL;DR; is
that usually it is, but it may not be (e.g. in our zig-cc example we can
see any directory FD, not just pre-opens).

Finally, this fixes a bug in our path resolution where we mistook paths
like "foo/foo" for "foo" because we only considered basenames instead of
the full path from the pre-open root.

This also makes pre-open directory lookup lazy because I noticed in
Trivy specifically, this is unnecessary for us to do eagerly, as they
change the FS at runtime per-call. In other words, any value from init
time is invalid later.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-05 18:59:55 +08:00
Crypt Keeper
b90158cdf5 gojs: backfills reference count tests (#1006)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-04 16:20:08 +08:00
Crypt Keeper
f8a33cef8d logging: avoids logging activity to stdio file descriptors (#1007)
This avoids logging activity on stdio file descriptors, in order to help
make troubleshooting easier. Usually, there isn't an issue in these, yet
wasm panics are harder to read if there is also logging of the ..
logging.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-04 16:04:40 +08:00
Takeshi Yoneda
3ab7e4b36d Ensures user-defined primitive types are usable in host func signatures (#1005)
Ensure primitive types are usable in host func signatures

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-04 15:32:32 +08:00
Crypt Keeper
83e4b66659 Consolidates internal code to syscallfs (#1003)
This consolidates internal code to syscallfs, which removes the fs.FS
specific path rules, except when adapting one to syscallfs. For example,
this allows the underlying filesystem to decide if relative paths are
supported or not, as well any EINVAL related concerns.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-04 13:53:53 +08:00
Takeshi Yoneda
846575d0fa interpreter: removes unneeded fields from func instances (#1004)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-04 11:50:49 +09:00
Crypt Keeper
65c7d9dd1b gojs: stubs all remaining filesystem calls to ENOSYS (#1001)
This stubs all remaining syscalls for `GOARCH=wasm GOOS=js` to return
ENOSYS, instead of panic'ing. This allows us to see the parameters it
receives.

For example:
```
==> go.syscall/js.valueCall(fs.truncate(path=/tmp/_Go_TestTruncate135754730,length=0))
<== (err=function not implemented,ok=false)
```

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-03 15:54:29 +08:00
Takeshi Yoneda
ef3937ffed Simplifies spectest initialization (#1000)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-03 13:22:14 +09:00
Crypt Keeper
8c5106b942 Ensures writes aren't allowed when opening for read (#999)
This masks interfaces returned by `fs.File` so that we don't
accidentally allow writes when opened for reading. This also adds
`syscall.NewReadFS` which can enforce read-only access in general, such
as would be ideal for tests that try to read files from the host root
filesystem (e.g. /etc/passwd).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-03 12:17:37 +08:00
Takeshi Yoneda
d29b6b011c cache: fixes deadlock in version mismatch (#998)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-03 12:17:12 +09:00
Crypt Keeper
4197caa05b Ensures 32-bit platforms build (#996)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-02 11:03:23 +09:00
Crypt Keeper
94491fef0b Implements rename in GOOS=js and WASI (#991)
This implements rename, which is the last function needed to pass TinyGo
os package tests:

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-31 16:37:28 +08:00
Crypt Keeper
c9868d89cb Removes internal dependency on fs.FS (#987)
As noted in slack, we are unlikley to long term use fs.FS internally.
This ensures we attempt to cast to syscallfs.FS for all I/O by panicing
on fs.Open.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-31 13:27:54 +08:00
Takeshi Yoneda
2045f71363 enginetest: fixes panic om memory def (#989)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-31 14:27:04 +09:00
Crypt Keeper
da3aa7a5ad Adds ExportedFunctionDefinitions and ExportedMemoryDefinitions (#986)
This adds ExportedFunctionDefinitions and ExportedMemoryDefinitions to
api.Module so that those who can't access CompileModule can see them.

Fixes #839

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-31 13:11:37 +08:00
Takeshi Yoneda
e7018d19ff compiler: force moduleContext initialization after Go function calls (#988)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-31 14:05:30 +09:00
Crypt Keeper
efc72de1e6 gojs: implements timeout events (#984)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-31 08:26:32 +08:00
Crypt Keeper
67cc6d3779 compilationcache: uses version-specific subdirectory (#982)
This makes the version, arch, os tuple into a subdirectory to help
troubleshooting and cache management in general. The version is left
inside the binary key regardless.

Note: when installing via `go install ./cmd/wazero/...` the version ends
up as `dev`. This helps make that obvious. For example.

```bash
$ wazero version
dev
$ ./build/tinygo test -target wasi -c -o os.wasm os
$ wazero run -cachedir=$HOME/.wazero -mount=.:/ -env=HOME=.  os.wasm -test.v
$ find $HOME/.wazero
/Users/adrian/.wazero
/Users/adrian/.wazero/wazero-dev-amd64-darwin
/Users/adrian/.wazero/wazero-dev-amd64-darwin/1f149f4bf475a33023ce33302780bee29ec08e89bd57cfbdf639c65c6009f1a4
```

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-31 07:01:57 +08:00
Achille
1db5433154 add internal/sys.FileTable (#975)
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2022-12-31 06:34:25 +08:00
Crypt Keeper
4495979cf0 wasi: fixes open flags (#981)
This fixes and backfills tests for open flags, notably O_CREAT. I
verified this with TinyGo tests, which now proceed when attempting to
create new files.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-30 19:32:18 +08:00
Crypt Keeper
9a4a372642 renames writefs to syscallfs and implements utimes in gojs (#979)
This renames the internal writefs package to syscallfs as it is largely
dependent on syscall signatures. This also implements utimes in gojs.
WASI will be a follow-up change as it requires more infrastructure.
Notably, we also need non-TinyGo tests because TinyGo doesn't yet
support os.Chtimes or corresponding syscalls.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-30 14:18:06 +08:00
Crypt Keeper
6d53a0033a wasi: implements path_(create|remove)_directory path_unlink_file (#976)
This implements path_(create|remove)_directory path_unlink_file in wasi, particularly needed to use TinyGo tests to verify our interpretation of WASI. Use of this requires the experimental `writefs.DirFS`.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-30 07:30:21 +08:00
Crypt Keeper
62be68dfc5 writefs: require ENOTEMPTY (#974)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-29 17:29:47 +08:00
Crypt Keeper
3f578ddac3 fs: splits unlink and rmdir from remove (#973)
This splits unlink and rmdir from remove, as it is not only more precise
in GOOS=js, but it is also needed to implement wasi. I verified this
works by running go unit tests with logging.

```
==> go.syscall/js.valueCall(fs.open(name=/tmp/TestErrIsNotExist1062486353,flags=,perm=----------))
<== (err=<nil>,fd=10)
==> go.syscall/js.valueCall(fs.fstat(fd=10))
<== (err=<nil>,stat={isDir=true,mode=-rwx------,size=96,mtimeMs=1672285985206})
==> go.syscall/js.valueCall(fs.readdir(name=/tmp/TestErrIsNotExist1062486353))
<== (err=<nil>,dirents=&{[001]})
==> go.syscall/js.valueCall(fs.unlink(path=/tmp/TestErrIsNotExist1062486353/001))
<== (err=is a directory,ok=true)
==> go.syscall/js.valueCall(fs.rmdir(path=/tmp/TestErrIsNotExist1062486353/001))
<== (err=<nil>,ok=false)
```

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-29 15:39:45 +08:00
Crypt Keeper
07a814a105 Exposes experimental writefs.DirFS, but hides implementation (#972)
The type we use to expose write operations is still evolving. It might
be a single writefs.FS interface, or similar to go where we have an
interface per feature (e.g. writefs.MkdirFS). These choices are all
implementation details for DirFS and won't be settled before the end of
the month version cutoff. Instead, this only exposes the ability to
create a DirFS, not an arbitrary implementation of writefs.FS. This does
so by making `writefs.FS` an internal type.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-29 10:39:04 +08:00
Crypt Keeper
64a4ab3ba5 wasi: unexports errno and re-uses constants for logging (#971)
We originally exported WASI errno as we originally supported invoking
host functions directly (e.g. without a guest). This was an invalid call
pattern, and we removed that. However, we left the errnos exported even
though the caller of a guest won't ever see them. This prevented us from
re-using them cleanly in features such as logging.

This moves all constants including function names and flag enums
internal so that there is less duplication between logging and
implementation of wasi functions. This also helps in reference searches,
as we can analyze uses of a particular function name.

The only constant left exported is the module name, as there's a use
case for that (overriding implementations via FunctionBuilder).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-29 09:42:10 +08:00
Crypt Keeper
15dc3d7d37 Adds experimental write support and implements on gojs (#970)
This adds writefs.FS, allowing functions to create and delete files.
This begins by implementing them on `GOARCH=js GOOS=wasm`. The current
status is a lot farther than before, even if completing write on WASI is
left for a later PR (possibly by another volunteer).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-28 19:49:46 +08:00
Crypt Keeper
921df7e7a6 cli: adds -hostlogging=filesystem for diagnosing problems (#966)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-28 11:38:24 +08:00
Crypt Keeper
d874ebbe48 logging: reformats wasi filesystem logs to display paths (#965)
This uses logging infrastructure introduced in #938 to show
paths and certain result parameters. While further tuning is expected,
the main thing this does is show which paths are affected by syscalls.

Signed-off-by: Adrian Cole <adrian@tetrate.io>

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-27 19:11:01 +08:00
Crypt Keeper
9dfe87531e logging: extracts utilities to read parameters and results from memory (#938)
This changes the listener signature to accept context and calling
module, so that all possible parameters and results can be logged. This
also changes the logging listener to make parameters visible when
logging results.

This infrastructure supports some helpful use cases, such as logging
WASI result parameters, such as the prestat path, which is only knowable
after the function has been called. The context parameter supposed
reading results of gojs functions, which are stored host-side in a go
context object.

Future pull requests will complete this as well backfill unit tests.
This is raised independently mainly to keep the PR size down of the
upcoming filesystem logger.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-27 16:08:25 +08:00
Crypt Keeper
5751bd758c gojs: extracts parameter names into a pseudo name section (#963)
`GOARCH=wasm GOOS=js` defines parameter names in go source, and they are
indirectly related to the wasm parameter "sp". This creates a pseudo
name section so that we can access the parameter names. The alternative
would be adding a hack to normal FunctionDefinition, only used for gojs.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-27 14:09:20 +08:00
Crypt Keeper
1ad900d179 gojs: refactors GOOS and GOARCH specific code into their own packages (#959)
This refactors GOOS and GOARCH specific code into their own packages.
This allows logging interceptors to be built without cyclic package
dependencies.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-27 08:45:43 +08:00
Takeshi Yoneda
a1706eb05c asm(arm64): fixes stack pointer add/sub for large consts (#962)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-26 16:26:23 +09:00
Takeshi Yoneda
69688468f8 asm(arm64): adds UDF instruction (#961)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-26 15:58:35 +09:00
Takeshi Yoneda
3d70c85032 asm(arm64): adds support for stack pointer manipulation (#960)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-26 10:07:13 +09:00
Takeshi Yoneda
6b9d119a7b doc: document why it's safe against async preemption (#957)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-23 13:38:55 +09:00