package asm //go:generate stringer -output load_store_string.go -type=Mode,Size // Mode for load and store operations // // msb lsb // +---+--+---+ // |MDE|sz|cls| // +---+--+---+ type Mode uint8 const modeMask OpCode = 0xe0 const ( // InvalidMode is returned by getters when invoked // on non load / store OpCodes InvalidMode Mode = 0xff // ImmMode - immediate value ImmMode Mode = 0x00 // AbsMode - immediate value + offset AbsMode Mode = 0x20 // IndMode - indirect (imm+src) IndMode Mode = 0x40 // MemMode - load from memory MemMode Mode = 0x60 // XAddMode - add atomically across processors. XAddMode Mode = 0xc0 ) // Size of load and store operations // // msb lsb // +---+--+---+ // |mde|SZ|cls| // +---+--+---+ type Size uint8 const sizeMask OpCode = 0x18 const ( // InvalidSize is returned by getters when invoked // on non load / store OpCodes InvalidSize Size = 0xff // DWord - double word; 64 bits DWord Size = 0x18 // Word - word; 32 bits Word Size = 0x00 // Half - half-word; 16 bits Half Size = 0x08 // Byte - byte; 8 bits Byte Size = 0x10 ) // Sizeof returns the size in bytes. func (s Size) Sizeof() int { switch s { case DWord: return 8 case Word: return 4 case Half: return 2 case Byte: return 1 default: return -1 } } // LoadMemOp returns the OpCode to load a value of given size from memory. func LoadMemOp(size Size) OpCode { return OpCode(LdXClass).SetMode(MemMode).SetSize(size) } // LoadMem emits `dst = *(size *)(src + offset)`. func LoadMem(dst, src Register, offset int16, size Size) Instruction { return Instruction{ OpCode: LoadMemOp(size), Dst: dst, Src: src, Offset: offset, } } // LoadImmOp returns the OpCode to load an immediate of given size. // // As of kernel 4.20, only DWord size is accepted. func LoadImmOp(size Size) OpCode { return OpCode(LdClass).SetMode(ImmMode).SetSize(size) } // LoadImm emits `dst = (size)value`. // // As of kernel 4.20, only DWord size is accepted. func LoadImm(dst Register, value int64, size Size) Instruction { return Instruction{ OpCode: LoadImmOp(size), Dst: dst, Constant: value, } } // LoadMapPtr stores a pointer to a map in dst. func LoadMapPtr(dst Register, fd int) Instruction { if fd < 0 { return Instruction{OpCode: InvalidOpCode} } return Instruction{ OpCode: LoadImmOp(DWord), Dst: dst, Src: PseudoMapFD, Constant: int64(fd), } } // LoadMapValue stores a pointer to the value at a certain offset of a map. func LoadMapValue(dst Register, fd int, offset uint32) Instruction { if fd < 0 { return Instruction{OpCode: InvalidOpCode} } fdAndOffset := (uint64(offset) << 32) | uint64(uint32(fd)) return Instruction{ OpCode: LoadImmOp(DWord), Dst: dst, Src: PseudoMapValue, Constant: int64(fdAndOffset), } } // LoadIndOp returns the OpCode for loading a value of given size from an sk_buff. func LoadIndOp(size Size) OpCode { return OpCode(LdClass).SetMode(IndMode).SetSize(size) } // LoadInd emits `dst = ntoh(*(size *)(((sk_buff *)R6)->data + src + offset))`. func LoadInd(dst, src Register, offset int32, size Size) Instruction { return Instruction{ OpCode: LoadIndOp(size), Dst: dst, Src: src, Constant: int64(offset), } } // LoadAbsOp returns the OpCode for loading a value of given size from an sk_buff. func LoadAbsOp(size Size) OpCode { return OpCode(LdClass).SetMode(AbsMode).SetSize(size) } // LoadAbs emits `r0 = ntoh(*(size *)(((sk_buff *)R6)->data + offset))`. func LoadAbs(offset int32, size Size) Instruction { return Instruction{ OpCode: LoadAbsOp(size), Dst: R0, Constant: int64(offset), } } // StoreMemOp returns the OpCode for storing a register of given size in memory. func StoreMemOp(size Size) OpCode { return OpCode(StXClass).SetMode(MemMode).SetSize(size) } // StoreMem emits `*(size *)(dst + offset) = src` func StoreMem(dst Register, offset int16, src Register, size Size) Instruction { return Instruction{ OpCode: StoreMemOp(size), Dst: dst, Src: src, Offset: offset, } } // StoreImmOp returns the OpCode for storing an immediate of given size in memory. func StoreImmOp(size Size) OpCode { return OpCode(StClass).SetMode(MemMode).SetSize(size) } // StoreImm emits `*(size *)(dst + offset) = value`. func StoreImm(dst Register, offset int16, value int64, size Size) Instruction { return Instruction{ OpCode: StoreImmOp(size), Dst: dst, Offset: offset, Constant: value, } } // StoreXAddOp returns the OpCode to atomically add a register to a value in memory. func StoreXAddOp(size Size) OpCode { return OpCode(StXClass).SetMode(XAddMode).SetSize(size) } // StoreXAdd atomically adds src to *dst. func StoreXAdd(dst, src Register, size Size) Instruction { return Instruction{ OpCode: StoreXAddOp(size), Dst: dst, Src: src, } }