Extended Berkeley Packet Filter (eBPF) assembler and virtual machine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

261 lines
5.4 KiB

package ebpf
import (
"fmt"
)
type LoadConstant struct {
Dst Register
Value uint64
Size uint8
}
func (a LoadConstant) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClassLoad | sizeDoubleWord | modeImmediate,
Dst: a.Dst,
Immediate: a.Value,
}, nil
}
func (a LoadConstant) String() string {
return fmt.Sprintf("lddw %s, %#x", a.Dst, a.Value)
}
type LoadAbsolute struct {
Dst, Src Register
Value uint64
Size uint8 // Size of the load value (in bytes).
}
func (a LoadAbsolute) Assemble() (RawInstruction, error) {
var size Opcode
switch a.Size {
case 1:
size = sizeByte
case 2:
size = sizeHalfWord
case 4:
size = sizeWord
case 8:
size = sizeDoubleWord
default:
return RawInstruction{}, fmt.Errorf("ebpf: invalid load absolute size %d", a.Size)
}
return RawInstruction{
Op: opClassLoad | size | modeAbsolute,
Dst: a.Dst,
Src: a.Src,
Immediate: a.Value,
}, nil
}
func (a LoadAbsolute) String() string {
var mnemonic string
switch a.Size {
case 1:
mnemonic = "ldabsb"
case 2:
mnemonic = "ldabsh"
case 4:
mnemonic = "ldabsw"
case 8:
mnemonic = "ldabsdw"
default:
return fmt.Sprintf("# invalid LoadAbsolute dst=%s, src=%s, size=%d, value=%#x", a.Dst, a.Src, a.Size, a.Value)
}
return fmt.Sprintf("%s %s, %s, %#x", mnemonic, a.Src, a.Dst, a.Value)
}
type LoadIndirect struct {
Dst, Src Register
Value uint64
Size uint8 // Size of the load value (in bytes).
}
func (a LoadIndirect) Assemble() (RawInstruction, error) {
var size Opcode
switch a.Size {
case 1:
size = sizeByte
case 2:
size = sizeHalfWord
case 4:
size = sizeWord
case 8:
size = sizeDoubleWord
default:
return RawInstruction{}, fmt.Errorf("ebpf: invalid load indirect size %d", a.Size)
}
return RawInstruction{
Op: opClassLoad | size | modeIndirect,
Dst: a.Dst,
Src: a.Src,
Immediate: a.Value,
}, nil
}
func (a LoadIndirect) String() string {
var mnemonic string
switch a.Size {
case 1:
mnemonic = "ldindb"
case 2:
mnemonic = "ldindh"
case 4:
mnemonic = "ldindw"
case 8:
mnemonic = "ldinddw"
default:
return fmt.Sprintf("# invalid LoadIndirect dst=%s, src=%s, size=%d, value=%#x", a.Dst, a.Src, a.Size, a.Value)
}
return fmt.Sprintf("%s %s, %s, %#x", mnemonic, a.Src, a.Dst, a.Value)
}
type LoadRegister struct {
Dst, Src Register
Offset int16
Size uint8 // Size of the load value (in bytes).
}
func (a LoadRegister) Assemble() (RawInstruction, error) {
var size Opcode
switch a.Size {
case 1:
size = sizeByte
case 2:
size = sizeHalfWord
case 4:
size = sizeWord
case 8:
size = sizeDoubleWord
default:
return RawInstruction{}, fmt.Errorf("ebpf: invalid load memory size %d", a.Size)
}
return RawInstruction{
Op: opClassLoadX | size | modeMemory,
Dst: a.Dst,
Src: a.Src,
Offset: a.Offset,
}, nil
}
func (a LoadRegister) String() string {
var mnemonic string
switch a.Size {
case 1:
mnemonic = "ldxb"
case 2:
mnemonic = "ldxh"
case 4:
mnemonic = "ldxw"
case 8:
mnemonic = "ldxdw"
default:
return fmt.Sprintf("# invalid LoadRegister dst=%s, src=%s, size=%d, offset=%d", a.Dst, a.Src, a.Size, a.Offset)
}
return fmt.Sprintf("%s %s, [%s+%#x]", mnemonic, a.Dst, a.Src, a.Offset)
}
type StoreImmediate struct {
Dst Register
Offset int16
Value uint32
Size uint8
}
func (a StoreImmediate) Assemble() (RawInstruction, error) {
var size Opcode
switch a.Size {
case 1:
size = sizeByte
case 2:
size = sizeHalfWord
case 4:
size = sizeWord
case 8:
size = sizeDoubleWord
default:
return RawInstruction{}, fmt.Errorf("ebpf: invalid store immediate size %d", a.Size)
}
return RawInstruction{
Op: opClassStore | size | modeMemory,
Dst: a.Dst,
Offset: a.Offset,
Immediate: uint64(a.Value),
}, nil
}
func (a StoreImmediate) String() string {
var mnemonic, sign string
switch a.Size {
case 1:
mnemonic = "stb"
case 2:
mnemonic = "sth"
case 4:
mnemonic = "stw"
case 8:
mnemonic = "stdw"
default:
return fmt.Sprintf("# invalid StoreImmediate dst=%s, size=%d, offset=%d, value=%#x", a.Dst, a.Size, a.Offset, a.Value)
}
if a.Offset >= 0 {
sign = "+"
}
return fmt.Sprintf("%s [%s%s%#x], %#x", mnemonic, a.Dst, sign, a.Offset, a.Value)
}
type StoreRegister struct {
Dst, Src Register
Offset int16
Size uint8
}
func (a StoreRegister) Assemble() (RawInstruction, error) {
var size Opcode
switch a.Size {
case 1:
size = sizeByte
case 2:
size = sizeHalfWord
case 4:
size = sizeWord
case 8:
size = sizeDoubleWord
default:
return RawInstruction{}, fmt.Errorf("ebpf: invalid store memory size %d", a.Size)
}
return RawInstruction{
Op: opClassStoreX | size | modeMemory,
Dst: a.Dst,
Src: a.Src,
Offset: a.Offset,
}, nil
}
func (a StoreRegister) String() string {
var mnemonic string
switch a.Size {
case 1:
mnemonic = "stxb"
case 2:
mnemonic = "stxh"
case 4:
mnemonic = "stxw"
case 8:
mnemonic = "stxdw"
default:
return fmt.Sprintf("# invalid StoreRegister dst=%s, src=%s, size=%d, offset=%#x", a.Dst, a.Src, a.Size, a.Offset)
}
return fmt.Sprintf("%s [%s+%#x], %s", mnemonic, a.Dst, a.Offset, a.Src)
}
var (
_ Instruction = (*LoadConstant)(nil)
_ Instruction = (*LoadAbsolute)(nil)
_ Instruction = (*LoadIndirect)(nil)
_ Instruction = (*LoadRegister)(nil)
_ Instruction = (*StoreImmediate)(nil)
_ Instruction = (*StoreRegister)(nil)
)