diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-12-15 13:42:28 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-12-17 11:39:14 +0100 |
| commit | fea5478f4686624974d34edd8b4268d7a6af9584 (patch) | |
| tree | 08acde56db25b1a666c586401c985f3d1e4eb98e /prog/encodingexec.go | |
| parent | 431d3c90b1a4a31a6156ad1cd5fc692af3b1a314 (diff) | |
prog: add DeserializeExec
Factor out program parsing from pkg/csource.
csource code that parses program and at the same time
formats output is very messy and complex.
New aproach also allows to understand e.g.
when a call has copyout instructions which is
useful for better C source output.
Diffstat (limited to 'prog/encodingexec.go')
| -rw-r--r-- | prog/encodingexec.go | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/prog/encodingexec.go b/prog/encodingexec.go index 3c6466d7b..b89788378 100644 --- a/prog/encodingexec.go +++ b/prog/encodingexec.go @@ -4,6 +4,19 @@ // This file does serialization of programs for executor binary. // The format aims at simple parsing: binary and irreversible. +// Exec format is an sequence of uint64's which encodes a sequence of calls. +// The sequence is terminated by a speciall call execInstrEOF. +// Each call is (call ID, number of arguments, arguments...). +// Each argument is (type, size, value). +// There are 4 types of arguments: +// - execArgConst: value is const value +// - execArgResult: value is index of a call whose result we want to reference +// - execArgData: value is a binary blob (represented as ]size/8[ uint64's) +// - execArgCsum: runtime checksum calculation +// There are 2 other special calls: +// - execInstrCopyin: copies its second argument into address specified by first argument +// - execInstrCopyout: reads value at address specified by first argument (result can be referenced by execArgResult) + package prog import ( @@ -12,16 +25,16 @@ import ( ) const ( - ExecInstrEOF = ^uint64(iota) - ExecInstrCopyin - ExecInstrCopyout + execInstrEOF = ^uint64(iota) + execInstrCopyin + execInstrCopyout ) const ( - ExecArgConst = uint64(iota) - ExecArgResult - ExecArgData - ExecArgCsum + execArgConst = uint64(iota) + execArgResult + execArgData + execArgCsum ) const ( @@ -109,7 +122,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) (int, error) { return } if !IsPad(arg1.Type()) && arg1.Type().Dir() != DirOut { - w.write(ExecInstrCopyin) + w.write(execInstrCopyin) w.write(addr) w.writeArg(arg1, pid) instrSeq++ @@ -130,9 +143,9 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) (int, error) { if _, ok := arg.Type().(*CsumType); !ok { panic("csum arg is not csum type") } - w.write(ExecInstrCopyin) + w.write(execInstrCopyin) w.write(w.args[arg].Addr) - w.write(ExecArgCsum) + w.write(execArgCsum) w.write(arg.Size()) switch csumMap[arg].Kind { case CsumInet: @@ -185,7 +198,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) (int, error) { info.Idx = instrSeq instrSeq++ w.args[arg] = info - w.write(ExecInstrCopyout) + w.write(execInstrCopyout) w.write(info.Addr) w.write(arg.Size()) default: @@ -193,7 +206,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) (int, error) { } }) } - w.write(ExecInstrEOF) + w.write(execInstrEOF) if w.eof { return 0, fmt.Errorf("provided buffer is too small") } @@ -245,34 +258,34 @@ func (w *execContext) write(v uint64) { func (w *execContext) writeArg(arg Arg, pid int) { switch a := arg.(type) { case *ConstArg: - w.write(ExecArgConst) + w.write(execArgConst) w.write(a.Size()) w.write(a.Value(pid)) w.write(a.Type().BitfieldOffset()) w.write(a.Type().BitfieldLength()) case *ResultArg: if a.Res == nil { - w.write(ExecArgConst) + w.write(execArgConst) w.write(a.Size()) w.write(a.Val) w.write(0) // bit field offset w.write(0) // bit field length } else { - w.write(ExecArgResult) + w.write(execArgResult) w.write(a.Size()) w.write(uint64(w.args[a.Res].Idx)) w.write(a.OpDiv) w.write(a.OpAdd) } case *PointerArg: - w.write(ExecArgConst) + w.write(execArgConst) w.write(a.Size()) w.write(w.target.physicalAddr(arg)) w.write(0) // bit field offset w.write(0) // bit field length case *DataArg: data := a.Data() - w.write(ExecArgData) + w.write(execArgData) w.write(uint64(len(data))) padded := len(data) if pad := 8 - len(data)%8; pad != 8 { |
