-
Notifications
You must be signed in to change notification settings - Fork 1
/
intermediate_types.go
141 lines (120 loc) · 3.11 KB
/
intermediate_types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// 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))
}