This repository has been archived by the owner on Aug 31, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
kernel.go
215 lines (178 loc) · 5.75 KB
/
kernel.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ftrace
import (
"strings"
"github.com/google/traceout/ftrace/cparse"
)
type kernelFunc func(cparse.EvalContext, []cparse.Value) cparse.Value
var kernelFunctions = map[string]kernelFunc{
"__print_flags": printFlags,
"__print_symbolic": printSymbolic,
"__get_str": getString,
"__printk_pf": printkFunctionPointer,
"__printk_pF": printkFunctionPointerOffset,
"__printk_pk": printkKernelSymbol,
/* TODO:
__print_symbolic
__print_hex
__get_dynamic_array?
*/
}
var kernelConstants = map[string]int{
/* soft irq types */
"HI_SOFTIRQ": 0,
"TIMER_SOFTIRQ": 1,
"NET_TX_SOFTIRQ": 2,
"NET_RX_SOFTIRQ": 3,
"BLOCK_SOFTIRQ": 4,
"BLOCK_IOPOLL_SOFTIRQ": 5,
"TASKLET_SOFTIRQ": 6,
"SCHED_SOFTIRQ": 7,
"HRTIMER_SOFTIRQ": 8,
"RCU_SOFTIRQ": 9,
/* tlb flush types */
"TLB_FLUSH_ON_TASK_SWITCH": 0,
"TLB_REMOTE_SHOOTDOWN": 1,
"TLB_LOCAL_SHOOTDOWN": 2,
"TLB_LOCAL_MM_SHOOTDOWN": 3,
}
var kernelTypes = map[string]string{
"gfp_t": "unsigned int",
}
func printFlags(ctx cparse.EvalContext, args []cparse.Value) cparse.Value {
if len(args) < 3 {
return cparse.NewValueError("expected at least 3 arguments to __print_flags")
}
if !args[0].IsInt() {
return cparse.NewValueError("expected integer as first argument to __print_flags")
}
v := args[0].AsInt()
if !args[1].IsString() {
return cparse.NewValueError("expected string as second argument to __print_flags")
}
delim := args[1].AsString()
first := true
ret := ""
for _, f := range args[2:] {
if !f.IsList() {
return cparse.NewValueError("expected list as argument to __print_flags")
}
l := f.AsList()
if len(l) != 2 {
return cparse.NewValueError("expected list of two elements as argument to __print_flags")
}
if !l[0].IsInt() {
return cparse.NewValueError("expected first element of list to be int as argument to __print_flags")
}
if !l[1].IsString() {
return cparse.NewValueError("expected second element of list to be string as argument to __print_flags")
}
if (v & l[0].AsInt()) != 0 {
if first {
ret = l[1].AsString()
first = false
} else {
ret += delim + l[1].AsString()
}
}
}
return cparse.NewValueString(ret)
}
func printSymbolic(ctx cparse.EvalContext, args []cparse.Value) cparse.Value {
if len(args) < 2 {
return cparse.NewValueError("expected at least 2 arguments to __print_symbolic")
}
if !args[0].IsInt() {
return cparse.NewValueError("expected integer as first argument to __print_symbolic")
}
v := args[0].AsInt()
for _, f := range args[1:] {
if !f.IsList() {
return cparse.NewValueError("expected list as argument to __print_symbolic ")
}
l := f.AsList()
if len(l) != 2 {
return cparse.NewValueError("expected list of two elements as argument to __print_symbolic")
}
if !l[0].IsInt() {
return cparse.NewValueError("expected first element of list to be int as argument to __print_symbolic, got " + l[0].Dump())
}
if !l[1].IsString() {
return cparse.NewValueError("expected second element of list to be string as argument to __print_symbolic")
}
if v == l[0].AsInt() {
return cparse.NewValueString(l[1].AsString())
}
}
return cparse.NewValueString("")
}
func getString(ctx cparse.EvalContext, args []cparse.Value) cparse.Value {
e := ctx.(Event)
if len(args) != 1 {
return cparse.NewValueError("expected 1 argument to __get_str")
}
if !args[0].IsInt() {
return cparse.NewValueError("expected integer as first argument to __get_str")
}
i := int(args[0].AsInt())
offset := i & 0xffff
length := i >> 16
if offset > len(e.contents)-1 {
return cparse.NewValueError("__get_str offset %d too large", offset)
}
if offset+length > len(e.contents) {
return cparse.NewValueError("__get_str length %d too large", length)
}
s := string(e.contents[offset : offset+length])
zero := strings.IndexByte(s, 0)
if zero != -1 {
s = s[:zero]
}
return cparse.NewValueString(s)
}
func printkFunctionPointer(ctx cparse.EvalContext, args []cparse.Value) cparse.Value {
e := ctx.(Event)
if len(args) != 1 {
return cparse.NewValueError("expected 1 argument to __printk_pf")
}
if !args[0].IsInt() {
return cparse.NewValueError("expected integer as first argument to __printk_pf")
}
addr := uint64(args[0].AsInt())
return cparse.NewValueString(e.ftrace.kernelSymbol(addr))
}
func printkFunctionPointerOffset(ctx cparse.EvalContext, args []cparse.Value) cparse.Value {
e := ctx.(Event)
if len(args) != 1 {
return cparse.NewValueError("expected 1 argument to __printk_pf")
}
if !args[0].IsInt() {
return cparse.NewValueError("expected integer as first argument to __printk_pf")
}
addr := uint64(args[0].AsInt())
// TODO: find function before addr, print offset
return cparse.NewValueString(e.ftrace.kernelSymbol(addr))
}
func printkKernelSymbol(ctx cparse.EvalContext, args []cparse.Value) cparse.Value {
e := ctx.(Event)
if len(args) != 1 {
return cparse.NewValueError("expected 1 argument to __printk_pf")
}
if !args[0].IsInt() {
return cparse.NewValueError("expected integer as first argument to __printk_pf")
}
addr := uint64(args[0].AsInt())
return cparse.NewValueString(e.ftrace.kernelSymbol(addr))
}