Add disasembler-ish - bytecode to instruction debug output
This commit is contained in:
parent
aec0564cea
commit
ac4a2bac00
@ -163,6 +163,15 @@ If `data_directory` is not set, current directory will be used.
|
||||
if `root_symbol` is not set, the symbol `root` will be used.
|
||||
|
||||
|
||||
### Disassembler
|
||||
|
||||
`go run ./dev/testdata/ <binary_file>`
|
||||
|
||||
The output from this tool is to be considered debugging output, as the assembly language isn't formalized yet.
|
||||
|
||||
In the meantime, it will at least list all the instructions, and thus validate the file.
|
||||
|
||||
|
||||
### Assembler
|
||||
|
||||
**TBD**
|
||||
|
27
go/dev/disasm/main.go
Normal file
27
go/dev/disasm/main.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
|
||||
"git.defalsify.org/festive/vm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if (len(os.Args) < 2) {
|
||||
os.Exit(1)
|
||||
}
|
||||
fp := os.Args[1]
|
||||
v, err := ioutil.ReadFile(fp)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "read error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
r, err := vm.ToString(v)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "parse error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf(r)
|
||||
}
|
93
go/vm/debug.go
Normal file
93
go/vm/debug.go
Normal file
@ -0,0 +1,93 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
|
||||
func ToString(b []byte) (string, error) {
|
||||
var s string
|
||||
running := true
|
||||
for running {
|
||||
op, bb, err := opSplit(b)
|
||||
b = bb
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
opString := OpcodeString[op]
|
||||
if opString == "" {
|
||||
return "", fmt.Errorf("unknown opcode: %v", op)
|
||||
}
|
||||
s += opString
|
||||
|
||||
switch op {
|
||||
case CATCH:
|
||||
r, n, m, bb, err := ParseCatch(b)
|
||||
b = bb
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
vv := 0
|
||||
if m {
|
||||
vv = 1
|
||||
}
|
||||
s = fmt.Sprintf("%s %s %v %v # invertmatch=%v", s, r, n, vv, m)
|
||||
case CROAK:
|
||||
n, m, bb, err := ParseCroak(b)
|
||||
b = bb
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
vv := 0
|
||||
if m {
|
||||
vv = 1
|
||||
}
|
||||
s = fmt.Sprintf("%s %v %v # invertmatch=%v", s, n, vv, m)
|
||||
case LOAD:
|
||||
r, n, bb, err := ParseLoad(b)
|
||||
b = bb
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s = fmt.Sprintf("%s %s %v", s, r, n)
|
||||
case RELOAD:
|
||||
r, bb, err := ParseReload(b)
|
||||
b = bb
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s = fmt.Sprintf("%s %s", s, r)
|
||||
case MAP:
|
||||
r, bb, err := ParseMap(b)
|
||||
b = bb
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s = fmt.Sprintf("%s %s", s, r)
|
||||
case MOVE:
|
||||
r, bb, err := ParseMove(b)
|
||||
b = bb
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s = fmt.Sprintf("%s %s", s, r)
|
||||
case INCMP:
|
||||
r, v, bb, err := ParseInCmp(b)
|
||||
b = bb
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s = fmt.Sprintf("%s %s %s", s, r, v)
|
||||
case HALT:
|
||||
b, err = ParseHalt(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
s += "\n"
|
||||
if len(b) == 0 {
|
||||
running = false
|
||||
}
|
||||
}
|
||||
return s, nil
|
||||
}
|
114
go/vm/debug_test.go
Normal file
114
go/vm/debug_test.go
Normal file
@ -0,0 +1,114 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
var b []byte
|
||||
var r string
|
||||
var expect string
|
||||
var err error
|
||||
|
||||
b = NewLine(nil, CATCH, []string{"xyzzy"}, []byte{0x0d}, []uint8{1})
|
||||
r, err = ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect = "CATCH xyzzy 13 1 # invertmatch=true\n"
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
|
||||
b = NewLine(nil, CROAK, nil, []byte{0x0d}, []uint8{1})
|
||||
r, err = ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect = "CROAK 13 1 # invertmatch=true\n"
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
|
||||
b = NewLine(nil, LOAD, []string{"foo"}, []byte{0x0a}, nil)
|
||||
r, err = ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect = "LOAD foo 10\n"
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
|
||||
b = NewLine(nil, RELOAD, []string{"bar"}, nil, nil)
|
||||
r, err = ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect = "RELOAD bar\n"
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
|
||||
b = NewLine(nil, MAP, []string{"inky_pinky"}, nil, nil)
|
||||
r, err = ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect = "MAP inky_pinky\n"
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
|
||||
b = NewLine(nil, MOVE, []string{"blinky_clyde"}, nil, nil)
|
||||
r, err = ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect = "MOVE blinky_clyde\n"
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
|
||||
b = NewLine(nil, HALT, nil, nil, nil)
|
||||
r, err = ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect = "HALT\n"
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
|
||||
b = NewLine(nil, INCMP, []string{"13", "baz"}, nil, nil)
|
||||
r, err = ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect = "INCMP 13 baz\n"
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToStringMultiple(t *testing.T) {
|
||||
b := NewLine(nil, INCMP, []string{"1", "foo"}, nil, nil)
|
||||
b = NewLine(b, INCMP, []string{"2", "bar"}, nil, nil)
|
||||
b = NewLine(b, CATCH, []string{"aiee"}, []byte{0x02, 0x9a}, []uint8{0})
|
||||
b = NewLine(b, LOAD, []string{"inky"}, []byte{0x2a}, nil)
|
||||
b = NewLine(b, HALT, nil, nil, nil)
|
||||
r, err := ToString(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect := `INCMP 1 foo
|
||||
INCMP 2 bar
|
||||
CATCH aiee 666 0 # invertmatch=false
|
||||
LOAD inky 42
|
||||
HALT
|
||||
`
|
||||
if r != expect {
|
||||
t.Fatalf("expected:\n\t%v\ngot:\n\t%v", expect, r)
|
||||
}
|
||||
}
|
@ -17,3 +17,17 @@ const (
|
||||
INCMP = 8
|
||||
_MAX = 8
|
||||
)
|
||||
|
||||
var (
|
||||
OpcodeString = map[Opcode]string{
|
||||
NOOP: "NOOP",
|
||||
CATCH: "CATCH",
|
||||
CROAK: "CROAK",
|
||||
LOAD: "LOAD",
|
||||
RELOAD: "RELOAD",
|
||||
MAP: "MAP",
|
||||
MOVE: "MOVE",
|
||||
HALT: "HALT",
|
||||
INCMP: "INCMP",
|
||||
}
|
||||
)
|
||||
|
@ -19,13 +19,11 @@ import (
|
||||
func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
|
||||
running := true
|
||||
for running {
|
||||
log.Printf("code before 0x%x", b)
|
||||
op, bb, err := opSplit(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
b = bb
|
||||
log.Printf("code after 0x%x", b)
|
||||
switch op {
|
||||
case CATCH:
|
||||
b, err = RunCatch(b, st, rs, ctx)
|
||||
@ -41,7 +39,6 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
|
||||
b, err = RunMove(b, st, rs, ctx)
|
||||
case INCMP:
|
||||
b, err = RunInCmp(b, st, rs, ctx)
|
||||
log.Printf("bb %v", b)
|
||||
case HALT:
|
||||
b, err = RunHalt(b, st, rs, ctx)
|
||||
return b, err
|
||||
@ -51,7 +48,6 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
log.Printf("aa %v", b)
|
||||
if len(b) == 0 {
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"git.defalsify.org/festive/state"
|
||||
)
|
||||
|
||||
func Parse(b []byte) (Opcode, []byte, error) {
|
||||
func ParseOp(b []byte) (Opcode, []byte, error) {
|
||||
op, b, err := opSplit(b)
|
||||
if err != nil {
|
||||
return NOOP, b, err
|
||||
|
Loading…
Reference in New Issue
Block a user