aboutsummaryrefslogtreecommitdiffstats
path: root/prog/decodeexec.go
diff options
context:
space:
mode:
Diffstat (limited to 'prog/decodeexec.go')
-rw-r--r--prog/decodeexec.go69
1 files changed, 42 insertions, 27 deletions
diff --git a/prog/decodeexec.go b/prog/decodeexec.go
index 2113d24c7..2356e051b 100644
--- a/prog/decodeexec.go
+++ b/prog/decodeexec.go
@@ -7,6 +7,7 @@ import (
"encoding/binary"
"fmt"
"reflect"
+ "strings"
)
type ExecProg struct {
@@ -71,8 +72,8 @@ type ExecCsumChunk struct {
Size uint64
}
-func (target *Target) DeserializeExec(exec []byte) (ExecProg, error) {
- dec := &execDecoder{target: target, data: exec}
+func (target *Target) DeserializeExec(exec []byte, stats map[string]int) (ExecProg, error) {
+ dec := &execDecoder{target: target, data: exec, stats: stats}
dec.parse()
if dec.err != nil {
return ExecProg{}, dec.err
@@ -96,22 +97,23 @@ type execDecoder struct {
vars []uint64
call ExecCall
calls []ExecCall
+ stats map[string]int
}
func (dec *execDecoder) parse() {
for dec.err == nil {
- switch instr := dec.read(); instr {
+ switch instr := dec.read("instr/opcode"); instr {
case execInstrCopyin:
dec.commitCall()
dec.call.Copyin = append(dec.call.Copyin, ExecCopyin{
- Addr: dec.read() + dec.target.DataOffset,
+ Addr: dec.read("instr/copyin") + dec.target.DataOffset,
Arg: dec.readArg(),
})
case execInstrCopyout:
dec.call.Copyout = append(dec.call.Copyout, ExecCopyout{
- Index: dec.read(),
- Addr: dec.read() + dec.target.DataOffset,
- Size: dec.read(),
+ Index: dec.read("instr/copyout/index"),
+ Addr: dec.read("instr/copyout/addr") + dec.target.DataOffset,
+ Size: dec.read("instr/copyout/size"),
})
case execInstrEOF:
dec.commitCall()
@@ -126,8 +128,8 @@ func (dec *execDecoder) parse() {
return
}
dec.call.Meta = dec.target.Syscalls[instr]
- dec.call.Index = dec.read()
- for i := dec.read(); i > 0; i-- {
+ dec.call.Index = dec.read("instr/index")
+ for i := dec.read("instr/nargs"); i > 0; i-- {
switch arg := dec.readArg(); arg.(type) {
case ExecArgConst, ExecArgResult:
dec.call.Args = append(dec.call.Args, arg)
@@ -142,7 +144,7 @@ func (dec *execDecoder) parse() {
func (dec *execDecoder) readCallProps(props *CallProps) {
props.ForeachProp(func(_, _ string, value reflect.Value) {
- arg := dec.read()
+ arg := dec.read("call prop")
switch kind := value.Kind(); kind {
case reflect.Int:
value.SetInt(int64(arg))
@@ -157,11 +159,11 @@ func (dec *execDecoder) readCallProps(props *CallProps) {
}
func (dec *execDecoder) readArg() ExecArg {
- switch typ := dec.read(); typ {
+ switch typ := dec.read("arg/type"); typ {
case execArgConst:
- meta := dec.read()
+ meta := dec.read("arg/const/meta")
return ExecArgConst{
- Value: dec.read(),
+ Value: dec.read("arg/const/value"),
Size: meta & 0xff,
Format: BinaryFormat((meta >> 8) & 0xff),
BitfieldOffset: (meta >> 16) & 0xff,
@@ -176,18 +178,18 @@ func (dec *execDecoder) readArg() ExecArg {
size = 8
}
return ExecArgConst{
- Value: dec.read() + dec.target.DataOffset,
+ Value: dec.read("arg/addr") + dec.target.DataOffset,
Size: uint64(size),
}
case execArgResult:
- meta := dec.read()
+ meta := dec.read("arg/result/meta")
arg := ExecArgResult{
Size: meta & 0xff,
Format: BinaryFormat((meta >> 8) & 0xff),
- Index: dec.read(),
- DivOp: dec.read(),
- AddOp: dec.read(),
- Default: dec.read(),
+ Index: dec.read("arg/result/index"),
+ DivOp: dec.read("arg/result/divop"),
+ AddOp: dec.read("arg/result/addop"),
+ Default: dec.read("arg/result/default"),
}
for uint64(len(dec.vars)) <= arg.Index {
dec.vars = append(dec.vars, 0)
@@ -195,22 +197,23 @@ func (dec *execDecoder) readArg() ExecArg {
dec.vars[arg.Index] = arg.Default
return arg
case execArgData:
- flags := dec.read()
+ flags := dec.read("arg/data/size")
size := flags & ^execArgDataReadable
+ dec.addStat("arg/data/blob", int(size))
readable := flags&execArgDataReadable != 0
return ExecArgData{
Data: dec.readBlob(size),
Readable: readable,
}
case execArgCsum:
- size := dec.read()
- switch kind := dec.read(); kind {
+ size := dec.read("arg/csum/size")
+ switch kind := dec.read("arg/csum/kind"); kind {
case ExecArgCsumInet:
- chunks := make([]ExecCsumChunk, dec.read())
+ chunks := make([]ExecCsumChunk, dec.read("arg/csum/chunks"))
for i := range chunks {
- kind := dec.read()
- addr := dec.read()
- size := dec.read()
+ kind := dec.read("arg/csum/chunk/kind")
+ addr := dec.read("arg/csum/chunk/addr")
+ size := dec.read("arg/csum/chunk/size")
if kind == ExecArgCsumChunkData {
addr += dec.target.DataOffset
}
@@ -235,7 +238,7 @@ func (dec *execDecoder) readArg() ExecArg {
}
}
-func (dec *execDecoder) read() uint64 {
+func (dec *execDecoder) read(stat string) uint64 {
if dec.err != nil {
return 0
}
@@ -244,6 +247,7 @@ func (dec *execDecoder) read() uint64 {
dec.setErr(fmt.Errorf("exec program overflow"))
return 0
}
+ dec.addStat(stat, n)
dec.data = dec.data[n:]
return uint64(v)
}
@@ -281,3 +285,14 @@ func (dec *execDecoder) commitCall() {
dec.calls = append(dec.calls, dec.call)
dec.call = ExecCall{}
}
+
+func (dec *execDecoder) addStat(stat string, n int) {
+ if dec.stats == nil {
+ return
+ }
+ prefix := ""
+ for _, part := range strings.Split(stat, "/") {
+ dec.stats[prefix+part] += n
+ prefix += part + "/"
+ }
+}