74 lines
1.9 KiB
Go
74 lines
1.9 KiB
Go
package gojs
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
|
|
"github.com/tetratelabs/wazero/api"
|
|
"github.com/tetratelabs/wazero/internal/gojs/util"
|
|
"github.com/tetratelabs/wazero/internal/wasm"
|
|
)
|
|
|
|
// Constants about memory layout. See REFERENCE.md
|
|
const (
|
|
endOfPageZero = uint32(4096) // runtime.minLegalPointer
|
|
maxArgsAndEnviron = uint32(8192) // ld.wasmMinDataAddr - runtime.minLegalPointer
|
|
wasmMinDataAddr = endOfPageZero + maxArgsAndEnviron // ld.wasmMinDataAddr
|
|
)
|
|
|
|
var le = binary.LittleEndian
|
|
|
|
// WriteArgsAndEnviron writes arguments and environment variables to memory, so
|
|
// they can be read by main, Go compiles as the function export "run".
|
|
func WriteArgsAndEnviron(mod api.Module) (argc, argv uint32, err error) {
|
|
mem := mod.Memory()
|
|
sysCtx := mod.(*wasm.ModuleInstance).Sys
|
|
args := sysCtx.Args()
|
|
environ := sysCtx.Environ()
|
|
|
|
argc = uint32(len(args))
|
|
offset := endOfPageZero
|
|
|
|
strPtr := func(val []byte, field string, i int) (ptr uint32) {
|
|
// TODO: return err and format "%s[%d], field, i"
|
|
ptr = offset
|
|
util.MustWrite(mem, field, offset, append(val, 0))
|
|
offset += uint32(len(val) + 1)
|
|
if pad := offset % 8; pad != 0 {
|
|
offset += 8 - pad
|
|
}
|
|
return
|
|
}
|
|
|
|
argvPtrLen := len(args) + 1 + len(environ) + 1
|
|
argvPtrs := make([]uint32, 0, argvPtrLen)
|
|
for i, arg := range args {
|
|
argvPtrs = append(argvPtrs, strPtr(arg, "args", i))
|
|
}
|
|
argvPtrs = append(argvPtrs, 0)
|
|
|
|
for i, env := range environ {
|
|
argvPtrs = append(argvPtrs, strPtr(env, "env", i))
|
|
}
|
|
argvPtrs = append(argvPtrs, 0)
|
|
|
|
argv = offset
|
|
|
|
stop := uint32(argvPtrLen << 3) // argvPtrLen * 8
|
|
if offset+stop >= wasmMinDataAddr {
|
|
err = errors.New("total length of command line and environment variables exceeds limit")
|
|
}
|
|
|
|
buf, ok := mem.Read(argv, stop)
|
|
if !ok {
|
|
panic("out of memory reading argvPtrs")
|
|
}
|
|
pos := uint32(0)
|
|
for _, ptr := range argvPtrs {
|
|
le.PutUint64(buf[pos:], uint64(ptr))
|
|
pos += 8
|
|
}
|
|
|
|
return
|
|
}
|