blob: 17dda668bc8bca11800301b988397ab6a02a7d51 [file] [log] [blame]
// Copyright 2018 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 parser
import (
"bytes"
"fmt"
)
// TraceTree struct contains intermediate representation of trace.
// If a trace is multiprocess it constructs a trace for each type.
type TraceTree struct {
TraceMap map[int64]*Trace
Ptree map[int64][]int64
RootPid int64
}
// NewTraceTree initializes a TraceTree.
func NewTraceTree() *TraceTree {
return &TraceTree{
TraceMap: make(map[int64]*Trace),
Ptree: make(map[int64][]int64),
}
}
func (tree *TraceTree) add(call *Syscall) {
if tree.RootPid == 0 {
tree.RootPid = call.Pid
}
if tree.TraceMap[call.Pid] == nil {
tree.TraceMap[call.Pid] = new(Trace)
}
c := tree.TraceMap[call.Pid].add(call)
if c.CallName == "clone" && !c.Paused {
tree.Ptree[c.Pid] = append(tree.Ptree[c.Pid], c.Ret)
}
}
// Trace is just a list of system calls
type Trace struct {
Calls []*Syscall
}
func (trace *Trace) add(call *Syscall) *Syscall {
if !call.Resumed {
trace.Calls = append(trace.Calls, call)
return call
}
lastCall := trace.Calls[len(trace.Calls)-1]
lastCall.Args = append(lastCall.Args, call.Args...)
lastCall.Paused = false
lastCall.Ret = call.Ret
return lastCall
}
// IrType is the intermediate representation of the strace output
// Every argument of a system call should be represented in an intermediate type
type IrType interface {
String() string
}
// Syscall struct is the IR type for any system call
type Syscall struct {
CallName string
Args []IrType
Pid int64
Ret int64
Paused bool
Resumed bool
}
// NewSyscall - constructor
func NewSyscall(pid int64, name string, args []IrType, ret int64, paused, resumed bool) (sys *Syscall) {
return &Syscall{
CallName: name,
Args: args,
Pid: pid,
Ret: ret,
Paused: paused,
Resumed: resumed,
}
}
func (s *Syscall) String() string {
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "Pid: -%v-Name: -%v-", s.Pid, s.CallName)
for _, typ := range s.Args {
fmt.Fprintf(buf, "-%v-", typ)
}
fmt.Fprintf(buf, "-Ret: %d\n", s.Ret)
return buf.String()
}
// GroupType contains arrays and structs
type GroupType struct {
Elems []IrType
}
func newGroupType(elems []IrType) (typ *GroupType) {
return &GroupType{Elems: elems}
}
// String implements IrType String()
func (a *GroupType) String() string {
var buf bytes.Buffer
buf.WriteString("[")
for _, elem := range a.Elems {
buf.WriteString(elem.String())
buf.WriteString(",")
}
buf.WriteString("]")
return buf.String()
}
// Constant represents all evaluated expressions produced by strace
// Constant types are evaluated at parse time
type Constant uint64
func (c Constant) String() string {
return fmt.Sprintf("%#v", c)
}
func (c Constant) Val() uint64 {
return uint64(c)
}
// BufferType contains strings
type BufferType struct {
Val string
}
func newBufferType(val string) *BufferType {
return &BufferType{Val: val}
}
// String implements IrType String()
func (b *BufferType) String() string {
return fmt.Sprintf("Buffer: %v with length: %v\n", b.Val, len(b.Val))
}