github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/emulator/inst.go (about) 1 package emulator 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/dylandreimerink/gobpfld/ebpf" 8 ) 9 10 // Instruction represents an eBPF instruction, as apposed to the ebpf.Instruction interface, these instruction can 11 // actually be executed by an emulator VM. 12 type Instruction interface { 13 ebpf.Instruction 14 15 Clone() Instruction 16 Execute(vm *VM) error 17 } 18 19 // Translate translates the High level instructions of the ebpf package and embeds them into instructions defined 20 // by the emulator package. The emulator instructions contain the logic to actually execute them. 21 func Translate(prog []ebpf.Instruction) ([]Instruction, error) { 22 vmProg := make([]Instruction, len(prog)) 23 24 for i, intInst := range prog { 25 var newInst Instruction 26 27 switch inst := intInst.(type) { 28 case *ebpf.Add32: 29 newInst = &Add32{Add32: *inst} 30 case *ebpf.Add64: 31 newInst = &Add64{Add64: *inst} 32 case *ebpf.Add32Register: 33 newInst = &Add32Register{Add32Register: *inst} 34 case *ebpf.Add64Register: 35 newInst = &Add64Register{Add64Register: *inst} 36 case *ebpf.And32: 37 newInst = &And32{And32: *inst} 38 case *ebpf.And64: 39 newInst = &And64{And64: *inst} 40 case *ebpf.And32Register: 41 newInst = &And32Register{And32Register: *inst} 42 case *ebpf.And64Register: 43 newInst = &And64Register{And64Register: *inst} 44 case *ebpf.ARSH32: 45 newInst = &ARSH32{ARSH32: *inst} 46 case *ebpf.ARSH64: 47 newInst = &ARSH64{ARSH64: *inst} 48 case *ebpf.ARSH32Register: 49 newInst = &ARSH32Register{ARSH32Register: *inst} 50 case *ebpf.ARSH64Register: 51 newInst = &ARSH64Register{ARSH64Register: *inst} 52 case *ebpf.AtomicAdd: 53 newInst = &AtomicAdd{AtomicAdd: *inst} 54 case *ebpf.CallBPF: 55 newInst = &CallBPF{CallBPF: *inst} 56 case *ebpf.CallHelper: 57 newInst = &CallHelper{CallHelper: *inst} 58 case *ebpf.CallHelperIndirect: 59 newInst = &CallHelperIndirect{CallHelperIndirect: *inst} 60 case *ebpf.Div32: 61 newInst = &Div32{Div32: *inst} 62 case *ebpf.Div64: 63 newInst = &Div64{Div64: *inst} 64 case *ebpf.Div32Register: 65 newInst = &Div32Register{Div32Register: *inst} 66 case *ebpf.Div64Register: 67 newInst = &Div64Register{Div64Register: *inst} 68 case *ebpf.End16ToLE: 69 newInst = &End16ToLE{End16ToLE: *inst} 70 case *ebpf.End32ToLE: 71 newInst = &End32ToLE{End32ToLE: *inst} 72 case *ebpf.End64ToLE: 73 newInst = &End64ToLE{End64ToLE: *inst} 74 case *ebpf.End16ToBE: 75 newInst = &End16ToBE{End16ToBE: *inst} 76 case *ebpf.End32ToBE: 77 newInst = &End32ToBE{End32ToBE: *inst} 78 case *ebpf.End64ToBE: 79 newInst = &End64ToBE{End64ToBE: *inst} 80 case *ebpf.Exit: 81 newInst = &Exit{Exit: *inst} 82 case *ebpf.Jump: 83 newInst = &Jump{Jump: *inst} 84 case *ebpf.JumpEqual: 85 newInst = &JumpEqual{JumpEqual: *inst} 86 case *ebpf.JumpEqual32: 87 newInst = &JumpEqual32{JumpEqual32: *inst} 88 case *ebpf.JumpEqualRegister: 89 newInst = &JumpEqualRegister{JumpEqualRegister: *inst} 90 case *ebpf.JumpEqualRegister32: 91 newInst = &JumpEqualRegister32{JumpEqualRegister32: *inst} 92 case *ebpf.JumpNotEqual: 93 newInst = &JumpNotEqual{JumpNotEqual: *inst} 94 case *ebpf.JumpNotEqual32: 95 newInst = &JumpNotEqual32{JumpNotEqual32: *inst} 96 case *ebpf.JumpNotEqualRegister: 97 newInst = &JumpNotEqualRegister{JumpNotEqualRegister: *inst} 98 case *ebpf.JumpNotEqualRegister32: 99 newInst = &JumpNotEqualRegister32{JumpNotEqualRegister32: *inst} 100 case *ebpf.JumpGreaterThanEqual: 101 newInst = &JumpGreaterThanEqual{JumpGreaterThanEqual: *inst} 102 case *ebpf.JumpGreaterThanEqual32: 103 newInst = &JumpGreaterThanEqual32{JumpGreaterThanEqual32: *inst} 104 case *ebpf.JumpGreaterThanEqualRegister: 105 newInst = &JumpGreaterThanEqualRegister{JumpGreaterThanEqualRegister: *inst} 106 case *ebpf.JumpGreaterThanEqualRegister32: 107 newInst = &JumpGreaterThanEqualRegister32{JumpGreaterThanEqualRegister32: *inst} 108 case *ebpf.JumpGreaterThan: 109 newInst = &JumpGreaterThan{JumpGreaterThan: *inst} 110 case *ebpf.JumpGreaterThan32: 111 newInst = &JumpGreaterThan32{JumpGreaterThan32: *inst} 112 case *ebpf.JumpGreaterThanRegister: 113 newInst = &JumpGreaterThanRegister{JumpGreaterThanRegister: *inst} 114 case *ebpf.JumpGreaterThanRegister32: 115 newInst = &JumpGreaterThanRegister32{JumpGreaterThanRegister32: *inst} 116 case *ebpf.JumpSignedGreaterThanOrEqual: 117 newInst = &JumpSignedGreaterThanOrEqual{JumpSignedGreaterThanOrEqual: *inst} 118 case *ebpf.JumpSignedGreaterThanOrEqual32: 119 newInst = &JumpSignedGreaterThanOrEqual32{JumpSignedGreaterThanOrEqual32: *inst} 120 case *ebpf.JumpSignedGreaterThanOrEqualRegister: 121 newInst = &JumpSignedGreaterThanOrEqualRegister{JumpSignedGreaterThanOrEqualRegister: *inst} 122 case *ebpf.JumpSignedGreaterThanOrEqualRegister32: 123 newInst = &JumpSignedGreaterThanOrEqualRegister32{JumpSignedGreaterThanOrEqualRegister32: *inst} 124 case *ebpf.JumpSignedGreaterThan: 125 newInst = &JumpSignedGreaterThan{JumpSignedGreaterThan: *inst} 126 case *ebpf.JumpSignedGreaterThan32: 127 newInst = &JumpSignedGreaterThan32{JumpSignedGreaterThan32: *inst} 128 case *ebpf.JumpSignedGreaterThanRegister: 129 newInst = &JumpSignedGreaterThanRegister{JumpSignedGreaterThanRegister: *inst} 130 case *ebpf.JumpSignedGreaterThanRegister32: 131 newInst = &JumpSignedGreaterThanRegister32{JumpSignedGreaterThanRegister32: *inst} 132 case *ebpf.JumpSignedSmallerThanOrEqual: 133 newInst = &JumpSignedSmallerThanOrEqual{JumpSignedSmallerThanOrEqual: *inst} 134 case *ebpf.JumpSignedSmallerThanOrEqual32: 135 newInst = &JumpSignedSmallerThanOrEqual32{JumpSignedSmallerThanOrEqual32: *inst} 136 case *ebpf.JumpSignedSmallerThanOrEqualRegister: 137 newInst = &JumpSignedSmallerThanOrEqualRegister{JumpSignedSmallerThanOrEqualRegister: *inst} 138 case *ebpf.JumpSignedSmallerThanOrEqualRegister32: 139 newInst = &JumpSignedSmallerThanOrEqualRegister32{JumpSignedSmallerThanOrEqualRegister32: *inst} 140 case *ebpf.JumpSignedSmallerThan: 141 newInst = &JumpSignedSmallerThan{JumpSignedSmallerThan: *inst} 142 case *ebpf.JumpSignedSmallerThan32: 143 newInst = &JumpSignedSmallerThan32{JumpSignedSmallerThan32: *inst} 144 case *ebpf.JumpSignedSmallerThanRegister: 145 newInst = &JumpSignedSmallerThanRegister{JumpSignedSmallerThanRegister: *inst} 146 case *ebpf.JumpSignedSmallerThanRegister32: 147 newInst = &JumpSignedSmallerThanRegister32{JumpSignedSmallerThanRegister32: *inst} 148 case *ebpf.LoadConstant64bit: 149 newInst = &LoadConstant64bit{LoadConstant64bit: *inst} 150 case *ebpf.LoadMemory: 151 newInst = &LoadMemory{LoadMemory: *inst} 152 case *ebpf.LoadSocketBuf: 153 newInst = &LoadSocketBuf{LoadSocketBuf: *inst} 154 case *ebpf.LoadSocketBufConstant: 155 newInst = &LoadSocketBufConstant{LoadSocketBufConstant: *inst} 156 case *ebpf.Lsh32: 157 newInst = &Lsh32{Lsh32: *inst} 158 case *ebpf.Lsh64: 159 newInst = &Lsh64{Lsh64: *inst} 160 case *ebpf.Lsh32Register: 161 newInst = &Lsh32Register{Lsh32Register: *inst} 162 case *ebpf.Lsh64Register: 163 newInst = &Lsh64Register{Lsh64Register: *inst} 164 case *ebpf.Mod32: 165 newInst = &Mod32{Mod32: *inst} 166 case *ebpf.Mod64: 167 newInst = &Mod64{Mod64: *inst} 168 case *ebpf.Mod32Register: 169 newInst = &Mod32Register{Mod32Register: *inst} 170 case *ebpf.Mod64Register: 171 newInst = &Mod64Register{Mod64Register: *inst} 172 case *ebpf.Mov32: 173 newInst = &Mov32{Mov32: *inst} 174 case *ebpf.Mov64: 175 newInst = &Mov64{Mov64: *inst} 176 case *ebpf.Mov32Register: 177 newInst = &Mov32Register{Mov32Register: *inst} 178 case *ebpf.Mov64Register: 179 newInst = &Mov64Register{Mov64Register: *inst} 180 case *ebpf.Mul32: 181 newInst = &Mul32{Mul32: *inst} 182 case *ebpf.Mul64: 183 newInst = &Mul64{Mul64: *inst} 184 case *ebpf.Mul32Register: 185 newInst = &Mul32Register{Mul32Register: *inst} 186 case *ebpf.Mul64Register: 187 newInst = &Mul64Register{Mul64Register: *inst} 188 case *ebpf.Neg32: 189 newInst = &Neg32{Neg32: *inst} 190 case *ebpf.Neg64: 191 newInst = &Neg64{Neg64: *inst} 192 case *ebpf.Nop: 193 newInst = &Nop{Nop: *inst} 194 case *ebpf.Or32: 195 newInst = &Or32{Or32: *inst} 196 case *ebpf.Or64: 197 newInst = &Or64{Or64: *inst} 198 case *ebpf.Or32Register: 199 newInst = &Or32Register{Or32Register: *inst} 200 case *ebpf.Or64Register: 201 newInst = &Or64Register{Or64Register: *inst} 202 case *ebpf.Rsh32: 203 newInst = &Rsh32{Rsh32: *inst} 204 case *ebpf.Rsh64: 205 newInst = &Rsh64{Rsh64: *inst} 206 case *ebpf.Rsh32Register: 207 newInst = &Rsh32Register{Rsh32Register: *inst} 208 case *ebpf.Rsh64Register: 209 newInst = &Rsh64Register{Rsh64Register: *inst} 210 case *ebpf.StoreMemoryConstant: 211 newInst = &StoreMemoryConstant{StoreMemoryConstant: *inst} 212 case *ebpf.StoreMemoryRegister: 213 newInst = &StoreMemoryRegister{StoreMemoryRegister: *inst} 214 case *ebpf.Sub32: 215 newInst = &Sub32{Sub32: *inst} 216 case *ebpf.Sub64: 217 newInst = &Sub64{Sub64: *inst} 218 case *ebpf.Sub32Register: 219 newInst = &Sub32Register{Sub32Register: *inst} 220 case *ebpf.Sub64Register: 221 newInst = &Sub64Register{Sub64Register: *inst} 222 case *ebpf.Xor32: 223 newInst = &Xor32{Xor32: *inst} 224 case *ebpf.Xor64: 225 newInst = &Xor64{Xor64: *inst} 226 case *ebpf.Xor32Register: 227 newInst = &Xor32Register{Xor32Register: *inst} 228 case *ebpf.Xor64Register: 229 newInst = &Xor64Register{Xor64Register: *inst} 230 default: 231 return nil, fmt.Errorf("can't translate instruction at %d of type %T", i, inst) 232 } 233 234 vmProg[i] = newInst 235 } 236 237 return vmProg, nil 238 } 239 240 func readReg(vm *VM, reg ebpf.Register) (int64, RegisterValue, error) { 241 r, err := vm.Registers.Get(reg) 242 if err != nil { 243 return 0, r, fmt.Errorf("get %s: %w", reg.String(), err) 244 } 245 246 return r.Value(), r, err 247 } 248 249 func isIMM(r RegisterValue) bool { 250 _, ok := r.(*IMMValue) 251 return ok 252 } 253 254 func sameRVType(a, b RegisterValue) bool { 255 at := reflect.TypeOf(a) 256 bt := reflect.TypeOf(b) 257 return at == bt 258 }