1
2
3
4
5 package bpf
6
7 import (
8 "encoding/binary"
9 "fmt"
10 )
11
12 func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
13 return aluOpCommon(ins.Op, regA, ins.Val)
14 }
15
16 func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
17
18
19 if regX == 0 {
20 switch ins.Op {
21 case ALUOpDiv, ALUOpMod:
22 return 0, false
23 }
24 }
25
26 return aluOpCommon(ins.Op, regA, regX), true
27 }
28
29 func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
30 switch op {
31 case ALUOpAdd:
32 return regA + value
33 case ALUOpSub:
34 return regA - value
35 case ALUOpMul:
36 return regA * value
37 case ALUOpDiv:
38
39 return regA / value
40 case ALUOpOr:
41 return regA | value
42 case ALUOpAnd:
43 return regA & value
44 case ALUOpShiftLeft:
45 return regA << value
46 case ALUOpShiftRight:
47 return regA >> value
48 case ALUOpMod:
49
50 return regA % value
51 case ALUOpXor:
52 return regA ^ value
53 default:
54 return regA
55 }
56 }
57
58 func jumpIf(ins JumpIf, regA uint32) int {
59 return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val)
60 }
61
62 func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int {
63 return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX)
64 }
65
66 func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int {
67 var ok bool
68
69 switch cond {
70 case JumpEqual:
71 ok = regA == value
72 case JumpNotEqual:
73 ok = regA != value
74 case JumpGreaterThan:
75 ok = regA > value
76 case JumpLessThan:
77 ok = regA < value
78 case JumpGreaterOrEqual:
79 ok = regA >= value
80 case JumpLessOrEqual:
81 ok = regA <= value
82 case JumpBitsSet:
83 ok = (regA & value) != 0
84 case JumpBitsNotSet:
85 ok = (regA & value) == 0
86 }
87
88 if ok {
89 return int(skipTrue)
90 }
91
92 return int(skipFalse)
93 }
94
95 func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
96 offset := int(ins.Off)
97 size := ins.Size
98
99 return loadCommon(in, offset, size)
100 }
101
102 func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
103 switch ins.Dst {
104 case RegA:
105 regA = ins.Val
106 case RegX:
107 regX = ins.Val
108 }
109
110 return regA, regX
111 }
112
113 func loadExtension(ins LoadExtension, in []byte) uint32 {
114 switch ins.Num {
115 case ExtLen:
116 return uint32(len(in))
117 default:
118 panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
119 }
120 }
121
122 func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
123 offset := int(ins.Off) + int(regX)
124 size := ins.Size
125
126 return loadCommon(in, offset, size)
127 }
128
129 func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
130 offset := int(ins.Off)
131
132
133 if !inBounds(len(in), offset, 1) {
134 return 0, false
135 }
136
137
138 return uint32(in[offset]&0x0f) * 4, true
139 }
140
141 func inBounds(inLen int, offset int, size int) bool {
142 return offset+size <= inLen
143 }
144
145 func loadCommon(in []byte, offset int, size int) (uint32, bool) {
146 if !inBounds(len(in), offset, size) {
147 return 0, false
148 }
149
150 switch size {
151 case 1:
152 return uint32(in[offset]), true
153 case 2:
154 return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
155 case 4:
156 return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
157 default:
158 panic(fmt.Sprintf("invalid load size: %d", size))
159 }
160 }
161
162 func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
163 switch ins.Dst {
164 case RegA:
165 regA = regScratch[ins.N]
166 case RegX:
167 regX = regScratch[ins.N]
168 }
169
170 return regA, regX
171 }
172
173 func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
174 switch ins.Src {
175 case RegA:
176 regScratch[ins.N] = regA
177 case RegX:
178 regScratch[ins.N] = regX
179 }
180
181 return regScratch
182 }
183
View as plain text