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.
 
 

66 lines
1.6 KiB

package ebpf
import (
"encoding/binary"
"fmt"
)
type ByteSwap struct {
Dst Register
ByteOrder binary.ByteOrder
Size uint8
}
// Assemble implements the Instruction Assemble method.
func (a ByteSwap) Assemble() (RawInstruction, error) {
var source Opcode
if a.ByteOrder == binary.BigEndian {
source = aluSourceX
}
switch a.Size {
case 16, 32, 64:
return RawInstruction{
Op: opClassALU | source | Opcode(aluOpByteSwap),
Dst: a.Dst,
Immediate: uint64(a.Size),
}, nil
default:
return RawInstruction{}, fmt.Errorf("ebpf: invalid byte swap size %d", a.Size)
}
}
func (a ByteSwap) String() string {
if a.ByteOrder == binary.LittleEndian {
return fmt.Sprintf("le%d %s", a.Size, a.Dst)
}
return fmt.Sprintf("be%d %s", a.Size, a.Dst)
}
func (a ByteSwap) CString() string {
var endian = "le"
if a.ByteOrder == binary.BigEndian {
endian = "be"
}
return fmt.Sprintf("%s = hto%s%d(%s)", a.Dst, endian, a.Size, a.Dst)
}
func (a ByteSwap) Swap(value uint64) uint64 {
switch {
case a.Size == 16 && a.ByteOrder == binary.LittleEndian:
return uint64(htole16(uint16(value)))
case a.Size == 32 && a.ByteOrder == binary.LittleEndian:
return uint64(htole32(uint32(value)))
case a.Size == 64 && a.ByteOrder == binary.LittleEndian:
return htole64(value)
case a.Size == 16 && a.ByteOrder == binary.BigEndian:
return uint64(htobe16(uint16(value)))
case a.Size == 32 && a.ByteOrder == binary.BigEndian:
return uint64(htobe32(uint32(value)))
case a.Size == 64 && a.ByteOrder == binary.BigEndian:
return htobe64(value)
default:
return value
}
}
var _ Instruction = (*ByteSwap)(nil)