From 15481872dd1f28c83f214f8e65406bbea3ec0530 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Mon, 6 Aug 2018 18:04:11 -0700 Subject: [PATCH] go --- cmd/land/go.go | 134 ++++++++++++++++++++++++++++++++++++++++++++ cmd/land/process.go | 3 + 2 files changed, 137 insertions(+) create mode 100644 cmd/land/go.go diff --git a/cmd/land/go.go b/cmd/land/go.go new file mode 100644 index 0000000..6e64f34 --- /dev/null +++ b/cmd/land/go.go @@ -0,0 +1,134 @@ +package main + +import ( + "bytes" + "crypto/rand" + "encoding/binary" + "os" + "time" +) + +func (p *Process) getInt32(addr int32) int32 { + mem := p.vm.Memory()[addr : addr+4] + + var result int32 + err := binary.Read(bytes.NewReader(mem), binary.LittleEndian, &result) + if err != nil { + panic(err) + } + + return result +} + +func (p *Process) setInt32(addr int32, val int32) { + data := make([]byte, 4) + buf := bytes.NewBuffer(data) + err := binary.Write(buf, binary.LittleEndian, val) + if err != nil { + panic(err) + } + + _, err := p.writeMem(addr, data) + if err != nil { + panic(err) + } +} + +func (p *Process) getInt64(addr int32) int64 { + mem := p.vm.Memory()[addr : addr+8] + + var result int64 + err := binary.Read(bytes.NewReader(mem), binary.LittleEndian, &result) + if err != nil { + panic(err) + } + + return result +} + +func (p *Process) setInt64(addr int32, val int64) { + data := make([]byte, 8) + buf := bytes.NewBuffer(data) + err := binary.Write(buf, binary.LittleEndian, val) + if err != nil { + panic(err) + } + + _, err := p.writeMem(addr, data) + if err != nil { + panic(err) + } +} + +// goRuntimeWasmExit implements the go runtime function runtime.wasmExit. It uses +// the Go abi. +// +// This has the effective type of: +// +// func (p *Process) goRuntimeWasmExit(code int32) +func (p *Process) goRuntimeWasmExit(sp int32) { + exitCode := p.getInt32(sp + 8) + os.Exit(int(exitCode)) +} + +// goRuntimeWasmWrite wraps the write function. +// +// This has the effective type of: +// +// func (p *Process) goRuntimeWasmWrite(fd int64, ptr int64, n int32) +func (p *Process) goRuntimeWasmWrite(sp int32) { + fd := p.getInt64(sp + 8) + ptr := p.getInt64(sp + 16) + n := p.getInt32(sp + 24) + + result := p.write(int32(fd), int32(ptr), n) + // TODO: write result to wasmWrite? + _ = result +} + +// goRuntimeNanotime implements the go runtime function runtime.nanotime. It uses +// the Go abi. +// +// This has the effective type of: +// +// func (p *Process) goRuntimeNanotime() int64 +func (p *Process) goRuntimeNanotime(sp int32) { + p.setInt64(sp+8, int64(time.Now().UnixNano())) +} + +// goRuntimeWalltime implements the go runtime function runtime.walltime. It uses +// the Go abi. +// +// This has the effective type of: +// +// func (p *Process) goRuntimeWalltime() (int64, int32) +func (p *Process) goRuntimeWalltime(sp int32) { + now := time.Now() + p.setInt64(sp+8, now.Unix()) + p.setInt32(sp+16, int32(now.Nanosecond())) +} + +// goRuntimeScheduleCallback implements the go runtime function runtime.scheduleCallback. +// It uses the Go abi and is not implemented yet. +func (p *Process) goRuntimeScheduleCallback(sp int32) { + p.setInt32(sp+16, -1) +} + +func (p *Process) goRuntimeClearScheduledCallback(sp int32) {} + +// goLoadSlice loads a Go slice out of wasm memory. It uses the the Go abi. +func (p *Process) goLoadSlice(sp int32) []byte { + arr := p.getInt64(sp) + len := p.getInt64(sp + 8) + return p.vm.Memory()[arr : arr+len] +} + +func (p *Process) goRuntimeGetRandomData(sp int32) { + data := p.goLoadSlice(sp + 8) + _, err := rand.Read(data) + if err != nil { + panic(err) + } + + p.writeMem(sp+8, data) +} diff --git a/cmd/land/process.go b/cmd/land/process.go index 6a2b2b2..c395fe4 100644 --- a/cmd/land/process.go +++ b/cmd/land/process.go @@ -25,6 +25,9 @@ type Process struct { fs afero.Fs files []afero.File name string + + // go runtime cruft + goRuntimeValues []interface{} } // NewProcess constructs a new webassembly process based on the input webassembly module as a reader.