We originally had a `context.Context` for anything that might be
traced, but it turned out to be only useful for lifecycle and host functions.
For instruction-scoped aspects like memory updates, a context parameter is too
fine-grained and also invisible in practice. For example, most users will use
the compiler engine, and its memory, global or table access will never use go's
context.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This removes the ability to override the current file system with Go
context, allowing us to simplify common paths and improve performance.
The context override was only used once in GitHub, in Trivy, and we
found another way to do that without it.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
At the moment, the only pre-open support we have is the file system
itself (root a.k.a. / or file-descriptor 3). We may in the future add
the ability to pre-open sockets, but in any case, this is where we are
today.
This change hardens logic around fd_preXXX functions, ensuring they only
work on actual pre-opens. This also fixes the path returned in filestat
as we sometimes returned a full path, when typically the basename is the
only part that can be returned.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
`os.DirFS` ironically doesn't implement `fs.ReadDirFS`, so we cannot
open a directory this way. This blindly attempts to open "." regardless
of if the `fs.FS` implementation is a `fs.ReadDirFS` or not, and if
successful, enforces that the file returned is a directory. If not, a
fake directory is returned.
Doing so allows real stat to be returned for root, and also a chance to
know if a filesystem configured is real or not. Later, we'll need this
to implement open flags.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Before, we didn't allow a real stat on the root file descriptor. Now,
those that pass fs.ReadDirFS will return the stat of the root file
(which is implemented by a open against ".").
This also simplifies logic as we always have a file representing root,
even if faked.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
It is likely we'll have to special-case real files in wasi, as wasi-libc
makes behavioral choices based on presence of non-zero inode data. This
adds a defensive benchmark, so that we know what our performance base
case is. This adds both real and fake file systems as both patterns are
in use today.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Right now, developing and troubleshooting wasi host functions are difficult as they are required to be WebAssembly 1.0 compatible. Specifically, they can only return a single result, and that's always used for errno. Other results are passed as out-parameters (memory offsets to write results), and their values are not very useful in practice.
This change proxies functions so that we can see their results while still keeping compatibility with wasm signatures. It uses the same approach we use in gojs (`GOOS=js GOARCH=wasm go build...`). What happens is we proxy in wasm, so that the go function implementing the ABI function has natural multi-value returned.
Specifically, we get logging like this, which is better as you can see the values returned:
```diff
- ==> wasi_snapshot_preview1.args_sizes_get(result.argc=1,result.argv_len=6)
- <== ESUCCESS
+ --> wasi_snapshot_preview1.args_sizes_get(result.argc=1,result.argv_len=6)
+ ==> wasi_snapshot_preview1.args_sizes_get.go()
+ <== (argc=2,argv_len=5,ESUCCESS)
+ <-- ESUCCESS
```
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This changes the log listener to assume a value is signed instead of
unsigned, as it leads to logs looking more correct than the other way
around. Notably, values that are often negative, such as seek offset,
look better without a lot of downside.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This implements fd_fdstat_get and furthers implementation of
fd_fdstat_get. Notably, this does the following:
* Ensures stdio are treated as character devices.
* Ensures someone can stat the root FD (4).
* Fixes encoding as we didn't clear zeros when encoding numbers.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This adds ResultNames to HostFunctionBuilder and FunctionDefinition
which helps for multi-results or special-cased ones.
End users can access result names in `FunctionDefinition.ResultNames` or
set for their own host functions via
`HostFunctionBuilder.WithResultNames`. This change adds them for all
built-in functions where result names help.
Most notably, GOOS=js uses `ProxyFunc` to allow logging when a function
returns multiple results. Before, the results were returned without
names: e.g. `11231,1` and now they are named like `n=11231,ok=1`.
We soon plan to allow more visibility in WASI, for example, logging
results that will write to memory offsets. This infrastructure makes it
possible to do that.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
While most compilers will only read args/environ once, tools like WAGI
make heavy use of environment, possibly dozens of long variables. This
optimizes both args and environ for this reason and also to setup for
optimizing other functions.
Here are the notable changes:
* eagerly coerce to byte slices instead of strings
* re-use null terminated length for writing values
* avoid loops that call mem.WriteXXX internally
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This adds an implementation of `fd_readdir` for WASI, which ensures a
very large directory is not kept in host memory until its directory is
closed.
Original implementation and test data are with thanks from @jerbob92.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
Co-authored-by: jerbob92 <jerbob92@users.noreply.github.com>