-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wasys: standalone/unsafe program runner
- Loading branch information
Showing
10 changed files
with
1,429 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Copyright (c) 2018 Timo Savola. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package main | ||
|
||
func exec(textBase, stackLimit, memoryBase, memoryLimit, memoryGrowLimit, stackPtr uintptr) | ||
|
||
func callSys() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright (c) 2018 Timo Savola. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
#include "textflag.h" | ||
|
||
// func exec(textBase, stackLimit, memoryBase, memoryLimit, memoryGrowLimit, stackPtr uintptr) | ||
TEXT ·exec(SB),NOSPLIT,$0-48 | ||
MOVQ textBase+0(FP), R12 | ||
MOVQ stackLimit+8(FP), R13 | ||
MOVQ memoryBase+16(FP), R14 | ||
MOVQ memoryLimit+24(FP), R15 | ||
MOVQ memoryGrowLimit+32(FP), BX | ||
MOVQ stackPtr+40(FP), CX | ||
|
||
LEAQ traphandler<>(SB), AX | ||
MOVQ AX, M0 // trap handler | ||
MOVQ BX, M1 // memory grow limit | ||
MOVQ CX, SP // stack ptr | ||
|
||
XORL AX, AX | ||
XORL BX, BX | ||
XORL CX, CX | ||
XORL BP, BP | ||
XORL SI, SI | ||
XORL DI, DI | ||
XORL R8, R8 | ||
XORL R9, R9 // suspend flag | ||
|
||
MOVQ R12, DX | ||
ADDQ $16, DX // init code after trap trampoline | ||
JMP DX | ||
|
||
TEXT traphandler<>(SB),NOSPLIT,$0 | ||
CMPL AX, $0 // exit trap (lower 32 bits) | ||
JE exittrap | ||
ADDL $100, AX // 100 + trap id | ||
JMP sysexit | ||
|
||
exittrap: | ||
SHRQ $32, AX // exit code (higher 32 bits) | ||
sysexit: | ||
MOVL AX, DI | ||
MOVL $231, AX // exit_group syscall | ||
SYSCALL | ||
|
||
TEXT ·callSys(SB),NOSPLIT,$0 | ||
MOVQ R8, R9 // arg 6 (suspend flag) | ||
MOVQ DI, R8 // arg 5 | ||
MOVQ SI, R10 // arg 4 | ||
MOVQ BP, DX // arg 3 | ||
MOVQ BX, SI // arg 2 | ||
MOVQ CX, DI // arg 1 | ||
SYSCALL | ||
XORL R9, R9 // suspend flag | ||
RET |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
// Copyright (c) 2018 Timo Savola. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package main | ||
|
||
//go:generate go run ../../internal/cmd/syscalls/generate.go | ||
|
||
import ( | ||
"bytes" | ||
"flag" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"reflect" | ||
"syscall" | ||
"unsafe" | ||
|
||
"github.com/tsavola/wag" | ||
"github.com/tsavola/wag/types" | ||
) | ||
|
||
var ( | ||
verbose = false | ||
) | ||
|
||
var importFuncs = make(map[string]uint64) | ||
|
||
type env struct{} | ||
|
||
func (*env) ImportFunction(module, field string, sig types.Function) (variadic bool, absAddr uint64, err error) { | ||
if verbose { | ||
log.Printf("import %s%s", field, sig) | ||
} | ||
|
||
if module != "env" { | ||
err = fmt.Errorf("imported function's module is unknown: %s %s", module, field) | ||
return | ||
} | ||
|
||
absAddr = importFuncs[field] | ||
if absAddr == 0 { | ||
err = fmt.Errorf("imported function not supported: %s %s", module, field) | ||
return | ||
} | ||
|
||
return | ||
} | ||
|
||
func (*env) ImportGlobal(module, field string, t types.T) (valueBits uint64, err error) { | ||
err = fmt.Errorf("imported global not supported: %s %s", module, field) | ||
return | ||
} | ||
|
||
type fixedBuf struct { | ||
b []byte | ||
} | ||
|
||
func (f *fixedBuf) Bytes() []byte { return f.b } | ||
func (f *fixedBuf) Grow(n int) {} | ||
func (f *fixedBuf) Len() int { return len(f.b) } | ||
|
||
func (f *fixedBuf) Write(b []byte) (n int, err error) { | ||
offset := len(f.b) | ||
n = len(b) | ||
f.b = f.b[:len(f.b)+n] | ||
copy(f.b[offset:], b) | ||
return | ||
} | ||
|
||
func (f *fixedBuf) WriteByte(b byte) (err error) { | ||
offset := len(f.b) | ||
f.b = f.b[:offset+1] | ||
f.b[offset] = b | ||
return | ||
} | ||
|
||
func makeMem(size int, extraProt, extraFlags int) (mem []byte, err error) { | ||
if size > 0 { | ||
mem, err = syscall.Mmap(-1, 0, size, syscall.PROT_READ|syscall.PROT_WRITE|extraProt, syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS|extraFlags) | ||
} | ||
return | ||
} | ||
|
||
func memAddr(mem []byte) uintptr { | ||
return (*reflect.SliceHeader)(unsafe.Pointer(&mem)).Data | ||
} | ||
|
||
func main() { | ||
log.SetFlags(0) | ||
|
||
flag.Usage = func() { | ||
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] wasmfile\n\n", os.Args[0]) | ||
fmt.Fprintf(flag.CommandLine.Output(), "Options:\n") | ||
flag.PrintDefaults() | ||
} | ||
|
||
var ( | ||
textSize = 128 * 1024 * 1024 | ||
roDataSize = 4 * 1024 * 1024 | ||
stackSize = 64 * 1024 | ||
entrySymbol = "main" | ||
) | ||
|
||
flag.BoolVar(&verbose, "v", verbose, "verbose logging") | ||
flag.IntVar(&textSize, "textsize", textSize, "maximum program text size") | ||
flag.IntVar(&roDataSize, "rodatasize", roDataSize, "maximum read-only data size") | ||
flag.IntVar(&stackSize, "stacksize", stackSize, "call stack size") | ||
flag.StringVar(&entrySymbol, "func", entrySymbol, "function to run") | ||
flag.Parse() | ||
|
||
if flag.NArg() != 1 { | ||
flag.Usage() | ||
os.Exit(2) | ||
} | ||
filename := flag.Arg(0) | ||
|
||
prog, err := ioutil.ReadFile(filename) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
roDataMem, err := makeMem(roDataSize, 0, syscall.MAP_32BIT) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
roDataAddr := memAddr(roDataMem) | ||
|
||
textMem, err := makeMem(textSize, syscall.PROT_EXEC, 0) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
textAddr := memAddr(textMem) | ||
textBuf := &fixedBuf{textMem[:0]} | ||
|
||
m := wag.Module{ | ||
EntrySymbol: entrySymbol, | ||
EntryArgs: make([]uint64, 2), | ||
} | ||
err = m.Load(bytes.NewReader(prog), &env{}, textBuf, roDataMem, int32(roDataAddr), nil) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
if err := syscall.Mprotect(roDataMem, syscall.PROT_READ); err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
if err := syscall.Mprotect(textMem, syscall.PROT_EXEC); err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
data, memoryOffset := m.Data() | ||
initMemorySize, growMemorySize := m.MemoryLimits() | ||
globalsMemoryMem, err := makeMem(memoryOffset+int(growMemorySize), 0, 0) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
copy(globalsMemoryMem, data) | ||
memoryAddr := memAddr(globalsMemoryMem) + uintptr(memoryOffset) | ||
initMemoryEnd := memoryAddr + uintptr(initMemorySize) | ||
growMemoryEnd := memoryAddr + uintptr(growMemorySize) | ||
|
||
stackMem, err := makeMem(stackSize, 0, syscall.MAP_STACK) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
stackAddr := memAddr(stackMem) | ||
stackEnd := stackAddr + uintptr(stackSize) | ||
|
||
exec(textAddr, stackAddr, memoryAddr, initMemoryEnd, growMemoryEnd, stackEnd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
// Generated by internal/cmd/syscalls/generate.go | ||
|
||
package main | ||
|
||
func importRead() uint64 | ||
func importWrite() uint64 | ||
func importOpen() uint64 | ||
func importClose() uint64 | ||
func importLseek() uint64 | ||
func importPread() uint64 | ||
func importPwrite() uint64 | ||
func importAccess() uint64 | ||
func importPipe() uint64 | ||
func importDup() uint64 | ||
func importDup2() uint64 | ||
func importGetpid() uint64 | ||
func importSendfile() uint64 | ||
func importShutdown() uint64 | ||
func importSocketpair() uint64 | ||
func importFlock() uint64 | ||
func importFsync() uint64 | ||
func importFdatasync() uint64 | ||
func importTruncate() uint64 | ||
func importFtruncate() uint64 | ||
func importGetcwd() uint64 | ||
func importChdir() uint64 | ||
func importFchdir() uint64 | ||
func importRename() uint64 | ||
func importMkdir() uint64 | ||
func importRmdir() uint64 | ||
func importCreat() uint64 | ||
func importLink() uint64 | ||
func importUnlink() uint64 | ||
func importSymlink() uint64 | ||
func importReadlink() uint64 | ||
func importChmod() uint64 | ||
func importFchmod() uint64 | ||
func importChown() uint64 | ||
func importFchown() uint64 | ||
func importLchown() uint64 | ||
func importUmask() uint64 | ||
func importGetuid() uint64 | ||
func importGetgid() uint64 | ||
func importVhangup() uint64 | ||
func importSync() uint64 | ||
func importGettid() uint64 | ||
func importTime() uint64 | ||
func importPosixFadvise() uint64 | ||
func importExit() uint64 | ||
func importInotifyInit() uint64 | ||
func importInotifyAddWatch() uint64 | ||
func importInotifyRmWatch() uint64 | ||
func importOpenat() uint64 | ||
func importMkdirat() uint64 | ||
func importFchownat() uint64 | ||
func importUnlinkat() uint64 | ||
func importRenameat() uint64 | ||
func importLinkat() uint64 | ||
func importSymlinkat() uint64 | ||
func importReadlinkat() uint64 | ||
func importFchmodat() uint64 | ||
func importFaccessat() uint64 | ||
func importSplice() uint64 | ||
func importTee() uint64 | ||
func importSyncFileRange() uint64 | ||
func importFallocate() uint64 | ||
func importEventfd() uint64 | ||
func importDup3() uint64 | ||
func importPipe2() uint64 | ||
|
||
func init() { | ||
importFuncs["read"] = importRead() | ||
importFuncs["write"] = importWrite() | ||
importFuncs["open"] = importOpen() | ||
importFuncs["close"] = importClose() | ||
importFuncs["lseek"] = importLseek() | ||
importFuncs["pread"] = importPread() | ||
importFuncs["pwrite"] = importPwrite() | ||
importFuncs["access"] = importAccess() | ||
importFuncs["pipe"] = importPipe() | ||
importFuncs["dup"] = importDup() | ||
importFuncs["dup2"] = importDup2() | ||
importFuncs["getpid"] = importGetpid() | ||
importFuncs["sendfile"] = importSendfile() | ||
importFuncs["shutdown"] = importShutdown() | ||
importFuncs["socketpair"] = importSocketpair() | ||
importFuncs["flock"] = importFlock() | ||
importFuncs["fsync"] = importFsync() | ||
importFuncs["fdatasync"] = importFdatasync() | ||
importFuncs["truncate"] = importTruncate() | ||
importFuncs["ftruncate"] = importFtruncate() | ||
importFuncs["getcwd"] = importGetcwd() | ||
importFuncs["chdir"] = importChdir() | ||
importFuncs["fchdir"] = importFchdir() | ||
importFuncs["rename"] = importRename() | ||
importFuncs["mkdir"] = importMkdir() | ||
importFuncs["rmdir"] = importRmdir() | ||
importFuncs["creat"] = importCreat() | ||
importFuncs["link"] = importLink() | ||
importFuncs["unlink"] = importUnlink() | ||
importFuncs["symlink"] = importSymlink() | ||
importFuncs["readlink"] = importReadlink() | ||
importFuncs["chmod"] = importChmod() | ||
importFuncs["fchmod"] = importFchmod() | ||
importFuncs["chown"] = importChown() | ||
importFuncs["fchown"] = importFchown() | ||
importFuncs["lchown"] = importLchown() | ||
importFuncs["umask"] = importUmask() | ||
importFuncs["getuid"] = importGetuid() | ||
importFuncs["getgid"] = importGetgid() | ||
importFuncs["vhangup"] = importVhangup() | ||
importFuncs["sync"] = importSync() | ||
importFuncs["gettid"] = importGettid() | ||
importFuncs["time"] = importTime() | ||
importFuncs["posix_fadvise"] = importPosixFadvise() | ||
importFuncs["_exit"] = importExit() | ||
importFuncs["inotify_init"] = importInotifyInit() | ||
importFuncs["inotify_add_watch"] = importInotifyAddWatch() | ||
importFuncs["inotify_rm_watch"] = importInotifyRmWatch() | ||
importFuncs["openat"] = importOpenat() | ||
importFuncs["mkdirat"] = importMkdirat() | ||
importFuncs["fchownat"] = importFchownat() | ||
importFuncs["unlinkat"] = importUnlinkat() | ||
importFuncs["renameat"] = importRenameat() | ||
importFuncs["linkat"] = importLinkat() | ||
importFuncs["symlinkat"] = importSymlinkat() | ||
importFuncs["readlinkat"] = importReadlinkat() | ||
importFuncs["fchmodat"] = importFchmodat() | ||
importFuncs["faccessat"] = importFaccessat() | ||
importFuncs["splice"] = importSplice() | ||
importFuncs["tee"] = importTee() | ||
importFuncs["sync_file_range"] = importSyncFileRange() | ||
importFuncs["fallocate"] = importFallocate() | ||
importFuncs["eventfd"] = importEventfd() | ||
importFuncs["dup3"] = importDup3() | ||
importFuncs["pipe2"] = importPipe2() | ||
} |
Oops, something went wrong.