blob: 516f9462b9fbc184e565f32c1e0d98e0d5d1b4e0 [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package bpf
6
7import (
8 "encoding/binary"
9 "fmt"
10)
11
12func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
13 return aluOpCommon(ins.Op, regA, ins.Val)
14}
15
16func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
17 // Guard against division or modulus by zero by terminating
18 // the program, as the OS BPF VM does
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
29func 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 // Division by zero not permitted by NewVM and aluOpX checks
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 // Modulus by zero not permitted by NewVM and aluOpX checks
50 return regA % value
51 case ALUOpXor:
52 return regA ^ value
53 default:
54 return regA
55 }
56}
57
58func jumpIf(ins JumpIf, value uint32) int {
59 var ok bool
60 inV := uint32(ins.Val)
61
62 switch ins.Cond {
63 case JumpEqual:
64 ok = value == inV
65 case JumpNotEqual:
66 ok = value != inV
67 case JumpGreaterThan:
68 ok = value > inV
69 case JumpLessThan:
70 ok = value < inV
71 case JumpGreaterOrEqual:
72 ok = value >= inV
73 case JumpLessOrEqual:
74 ok = value <= inV
75 case JumpBitsSet:
76 ok = (value & inV) != 0
77 case JumpBitsNotSet:
78 ok = (value & inV) == 0
79 }
80
81 if ok {
82 return int(ins.SkipTrue)
83 }
84
85 return int(ins.SkipFalse)
86}
87
88func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
89 offset := int(ins.Off)
90 size := int(ins.Size)
91
92 return loadCommon(in, offset, size)
93}
94
95func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
96 switch ins.Dst {
97 case RegA:
98 regA = ins.Val
99 case RegX:
100 regX = ins.Val
101 }
102
103 return regA, regX
104}
105
106func loadExtension(ins LoadExtension, in []byte) uint32 {
107 switch ins.Num {
108 case ExtLen:
109 return uint32(len(in))
110 default:
111 panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
112 }
113}
114
115func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
116 offset := int(ins.Off) + int(regX)
117 size := int(ins.Size)
118
119 return loadCommon(in, offset, size)
120}
121
122func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
123 offset := int(ins.Off)
124
125 if !inBounds(len(in), offset, 0) {
126 return 0, false
127 }
128
129 // Mask off high 4 bits and multiply low 4 bits by 4
130 return uint32(in[offset]&0x0f) * 4, true
131}
132
133func inBounds(inLen int, offset int, size int) bool {
134 return offset+size <= inLen
135}
136
137func loadCommon(in []byte, offset int, size int) (uint32, bool) {
138 if !inBounds(len(in), offset, size) {
139 return 0, false
140 }
141
142 switch size {
143 case 1:
144 return uint32(in[offset]), true
145 case 2:
146 return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
147 case 4:
148 return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
149 default:
150 panic(fmt.Sprintf("invalid load size: %d", size))
151 }
152}
153
154func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
155 switch ins.Dst {
156 case RegA:
157 regA = regScratch[ins.N]
158 case RegX:
159 regX = regScratch[ins.N]
160 }
161
162 return regA, regX
163}
164
165func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
166 switch ins.Src {
167 case RegA:
168 regScratch[ins.N] = regA
169 case RegX:
170 regScratch[ins.N] = regX
171 }
172
173 return regScratch
174}