diff options
Diffstat (limited to 'prog/decodeexec.go')
| -rw-r--r-- | prog/decodeexec.go | 69 |
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 + "/" + } +} |
