// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package prog

import (
	"fmt"
)

type ExecProg struct {
	Calls []ExecCall
	Vars  []uint64
}

type ExecCall struct {
	Meta    *Syscall
	Index   uint64
	Args    []ExecArg
	Copyin  []ExecCopyin
	Copyout []ExecCopyout
}

type ExecCopyin struct {
	Addr uint64
	Arg  ExecArg
}

type ExecCopyout struct {
	Index uint64
	Addr  uint64
	Size  uint64
}

type ExecArg interface{} // one of ExecArg*

type ExecArgConst struct {
	Size           uint64
	Format         BinaryFormat
	Value          uint64
	BitfieldOffset uint64
	BitfieldLength uint64
	PidStride      uint64
}

type ExecArgResult struct {
	Size    uint64
	Format  BinaryFormat
	Index   uint64
	DivOp   uint64
	AddOp   uint64
	Default uint64
}

type ExecArgData struct {
	Data []byte
}

type ExecArgCsum struct {
	Size   uint64
	Kind   uint64
	Chunks []ExecCsumChunk
}

type ExecCsumChunk struct {
	Kind  uint64
	Value uint64
	Size  uint64
}

func (target *Target) DeserializeExec(exec []byte) (ExecProg, error) {
	dec := &execDecoder{target: target, data: exec}
	dec.parse()
	if dec.err != nil {
		return ExecProg{}, dec.err
	}
	if uint64(len(dec.vars)) != dec.numVars {
		return ExecProg{}, fmt.Errorf("mismatching number of vars: %v/%v",
			len(dec.vars), dec.numVars)
	}
	p := ExecProg{
		Calls: dec.calls,
		Vars:  dec.vars,
	}
	return p, nil
}

type execDecoder struct {
	target  *Target
	data    []byte
	err     error
	numVars uint64
	vars    []uint64
	call    ExecCall
	calls   []ExecCall
}

func (dec *execDecoder) parse() {
	for dec.err == nil {
		switch instr := dec.read(); instr {
		case execInstrCopyin:
			dec.commitCall()
			dec.call.Copyin = append(dec.call.Copyin, ExecCopyin{
				Addr: dec.read(),
				Arg:  dec.readArg(),
			})
		case execInstrCopyout:
			dec.call.Copyout = append(dec.call.Copyout, ExecCopyout{
				Index: dec.read(),
				Addr:  dec.read(),
				Size:  dec.read(),
			})
		default:
			dec.commitCall()
			if instr >= uint64(len(dec.target.Syscalls)) {
				dec.setErr(fmt.Errorf("bad syscall %v", instr))
				return
			}
			dec.call.Meta = dec.target.Syscalls[instr]
			dec.call.Index = dec.read()
			for i := dec.read(); i > 0; i-- {
				switch arg := dec.readArg(); arg.(type) {
				case ExecArgConst, ExecArgResult:
					dec.call.Args = append(dec.call.Args, arg)
				default:
					dec.setErr(fmt.Errorf("bad call arg %+v", arg))
					return
				}
			}
		case execInstrEOF:
			dec.commitCall()
			return
		}
	}
}

func (dec *execDecoder) readArg() ExecArg {
	switch typ := dec.read(); typ {
	case execArgConst:
		meta := dec.read()
		return ExecArgConst{
			Value:          dec.read(),
			Size:           meta & 0xff,
			Format:         BinaryFormat((meta >> 8) & 0xff),
			BitfieldOffset: (meta >> 16) & 0xff,
			BitfieldLength: (meta >> 24) & 0xff,
			PidStride:      meta >> 32,
		}
	case execArgResult:
		meta := dec.read()
		arg := ExecArgResult{
			Size:    meta & 0xff,
			Format:  BinaryFormat((meta >> 8) & 0xff),
			Index:   dec.read(),
			DivOp:   dec.read(),
			AddOp:   dec.read(),
			Default: dec.read(),
		}
		for uint64(len(dec.vars)) <= arg.Index {
			dec.vars = append(dec.vars, 0)
		}
		dec.vars[arg.Index] = arg.Default
		return arg
	case execArgData:
		return ExecArgData{
			Data: dec.readBlob(dec.read()),
		}
	case execArgCsum:
		size := dec.read()
		switch kind := dec.read(); kind {
		case ExecArgCsumInet:
			chunks := make([]ExecCsumChunk, dec.read())
			for i := range chunks {
				chunks[i] = ExecCsumChunk{
					Kind:  dec.read(),
					Value: dec.read(),
					Size:  dec.read(),
				}
			}
			return ExecArgCsum{
				Size:   size,
				Kind:   kind,
				Chunks: chunks,
			}
		default:
			dec.setErr(fmt.Errorf("unknown csum kind %v", kind))
			return nil
		}
	default:
		dec.setErr(fmt.Errorf("bad argument type %v", typ))
		return nil
	}
}

func (dec *execDecoder) read() uint64 {
	if len(dec.data) < 8 {
		dec.setErr(fmt.Errorf("exec program overflow"))
	}
	if dec.err != nil {
		return 0
	}
	var v uint64
	for i := 0; i < 8; i++ {
		v |= uint64(dec.data[i]) << uint(i*8)
	}
	dec.data = dec.data[8:]
	return v
}

func (dec *execDecoder) readBlob(size uint64) []byte {
	padded := (size + 7) / 8 * 8
	if uint64(len(dec.data)) < padded {
		dec.setErr(fmt.Errorf("exec program overflow"))
	}
	if dec.err != nil {
		return nil
	}
	data := dec.data[:size]
	dec.data = dec.data[padded:]
	return data
}

func (dec *execDecoder) setErr(err error) {
	if dec.err == nil {
		dec.err = err
	}
}

func (dec *execDecoder) commitCall() {
	if dec.call.Meta == nil {
		return
	}
	if dec.call.Index != ExecNoCopyout && dec.numVars < dec.call.Index+1 {
		dec.numVars = dec.call.Index + 1
	}
	for _, copyout := range dec.call.Copyout {
		if dec.numVars < copyout.Index+1 {
			dec.numVars = copyout.Index + 1
		}
	}
	dec.calls = append(dec.calls, dec.call)
	dec.call = ExecCall{}
}
