github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-trace2syz/parser/intermediate_types.go (about)

     1  // Copyright 2018 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package parser
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  )
    10  
    11  // TraceTree struct contains intermediate representation of trace.
    12  // If a trace is multiprocess it constructs a trace for each type.
    13  type TraceTree struct {
    14  	TraceMap map[int64]*Trace
    15  	Ptree    map[int64][]int64
    16  	RootPid  int64
    17  }
    18  
    19  // NewTraceTree initializes a TraceTree.
    20  func NewTraceTree() *TraceTree {
    21  	return &TraceTree{
    22  		TraceMap: make(map[int64]*Trace),
    23  		Ptree:    make(map[int64][]int64),
    24  	}
    25  }
    26  
    27  func (tree *TraceTree) add(call *Syscall) {
    28  	if tree.RootPid == 0 {
    29  		tree.RootPid = call.Pid
    30  	}
    31  	if tree.TraceMap[call.Pid] == nil {
    32  		tree.TraceMap[call.Pid] = new(Trace)
    33  	}
    34  	c := tree.TraceMap[call.Pid].add(call)
    35  	if c.CallName == "clone" && !c.Paused {
    36  		tree.Ptree[c.Pid] = append(tree.Ptree[c.Pid], c.Ret)
    37  	}
    38  }
    39  
    40  // Trace is just a list of system calls
    41  type Trace struct {
    42  	Calls []*Syscall
    43  }
    44  
    45  func (trace *Trace) add(call *Syscall) *Syscall {
    46  	if !call.Resumed {
    47  		trace.Calls = append(trace.Calls, call)
    48  		return call
    49  	}
    50  	lastCall := trace.Calls[len(trace.Calls)-1]
    51  	lastCall.Args = append(lastCall.Args, call.Args...)
    52  	lastCall.Paused = false
    53  	lastCall.Ret = call.Ret
    54  	return lastCall
    55  }
    56  
    57  // IrType is the intermediate representation of the strace output
    58  // Every argument of a system call should be represented in an intermediate type
    59  type IrType interface {
    60  	String() string
    61  }
    62  
    63  // Syscall struct is the IR type for any system call
    64  type Syscall struct {
    65  	CallName string
    66  	Args     []IrType
    67  	Pid      int64
    68  	Ret      int64
    69  	Paused   bool
    70  	Resumed  bool
    71  }
    72  
    73  // NewSyscall - constructor
    74  func NewSyscall(pid int64, name string, args []IrType, ret int64, paused, resumed bool) (sys *Syscall) {
    75  	return &Syscall{
    76  		CallName: name,
    77  		Args:     args,
    78  		Pid:      pid,
    79  		Ret:      ret,
    80  		Paused:   paused,
    81  		Resumed:  resumed,
    82  	}
    83  }
    84  
    85  func (s *Syscall) String() string {
    86  	buf := new(bytes.Buffer)
    87  	fmt.Fprintf(buf, "Pid: -%v-Name: -%v-", s.Pid, s.CallName)
    88  	for _, typ := range s.Args {
    89  		fmt.Fprintf(buf, "-%v-", typ)
    90  	}
    91  	fmt.Fprintf(buf, "-Ret: %d\n", s.Ret)
    92  	return buf.String()
    93  }
    94  
    95  // GroupType contains arrays and structs
    96  type GroupType struct {
    97  	Elems []IrType
    98  }
    99  
   100  func newGroupType(elems []IrType) (typ *GroupType) {
   101  	return &GroupType{Elems: elems}
   102  }
   103  
   104  // String implements IrType String()
   105  func (a *GroupType) String() string {
   106  	var buf bytes.Buffer
   107  
   108  	buf.WriteString("[")
   109  	for _, elem := range a.Elems {
   110  		buf.WriteString(elem.String())
   111  		buf.WriteString(",")
   112  	}
   113  	buf.WriteString("]")
   114  	return buf.String()
   115  }
   116  
   117  // Constant represents all evaluated expressions produced by strace
   118  // Constant types are evaluated at parse time
   119  type Constant uint64
   120  
   121  func (c Constant) String() string {
   122  	return fmt.Sprintf("%#v", c)
   123  }
   124  
   125  func (c Constant) Val() uint64 {
   126  	return uint64(c)
   127  }
   128  
   129  // BufferType contains strings
   130  type BufferType struct {
   131  	Val string
   132  }
   133  
   134  func newBufferType(val string) *BufferType {
   135  	return &BufferType{Val: val}
   136  }
   137  
   138  // String implements IrType String()
   139  func (b *BufferType) String() string {
   140  	return fmt.Sprintf("Buffer: %v with length: %v\n", b.Val, len(b.Val))
   141  }