package ebpf
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestDisassemble(t *testing.T) {
|
|
tests := []struct {
|
|
Name string
|
|
Data []byte
|
|
Want []string
|
|
}{
|
|
{
|
|
Name: "alu",
|
|
Data: mustUnhex("040100000200000004090000ffffffff0c210000000000001c210000000000002c210000000000003c210000000000004c210000000000005c210000000000006c210000000000007c2100000000000084010000000000009c21000000000000ac21000000000000bc21000000000000cc21000000000000d401000010000000d401000020000000d401000040000000dc01000010000000dc01000020000000dc01000040000000"),
|
|
Want: []string{
|
|
"add32 R1, 0x2",
|
|
"add32 R9, 0xffffffff",
|
|
"add32 R1, R2",
|
|
"sub32 R1, R2",
|
|
"mul32 R1, R2",
|
|
"div32 R1, R2",
|
|
"or32 R1, R2",
|
|
"and32 R1, R2",
|
|
"lsh32 R1, R2",
|
|
"rsh32 R1, R2",
|
|
"neg32 R1",
|
|
"mod32 R1, R2",
|
|
"xor32 R1, R2",
|
|
"mov32 R1, R2",
|
|
"arsh32 R1, R2",
|
|
"le16 R1",
|
|
"le32 R1",
|
|
"le64 R1",
|
|
"be16 R1",
|
|
"be32 R1",
|
|
"be64 R1",
|
|
},
|
|
},
|
|
/*
|
|
{
|
|
Name: "alu-bit",
|
|
Want: []string{
|
|
"mov32 R0, 0x0",
|
|
"mov32 R1, 0x1",
|
|
"mov32 R2, 0x2",
|
|
"mov32 R3, 0x3",
|
|
"mov32 R4, 0x4",
|
|
"mov32 R5, 0x5",
|
|
"mov32 R6, 0x6",
|
|
"mov32 R7, 0x7",
|
|
"mov32 R8, 0x8",
|
|
"or32 R0, R5",
|
|
"or32 R0, 0xa0",
|
|
"and32 R0, 0xa3",
|
|
"mov32 R9, 0x91",
|
|
"and32 R0, R9",
|
|
"lsh32 R0, 22",
|
|
"lsh32 R0, R8",
|
|
"rsh32 R0, 19",
|
|
"rsh32 R0, R7",
|
|
"xor32 R0, 3",
|
|
"xor32 R0, R2",
|
|
"exit",
|
|
},
|
|
},
|
|
*/
|
|
{
|
|
Name: "ja",
|
|
Data: mustUnhex("b7000000010000000500010000000000b7000000020000009500000000000000"),
|
|
Want: []string{
|
|
"mov R0, 0x1",
|
|
"ja +1",
|
|
"mov R0, 0x2",
|
|
"exit",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Name, func(t *testing.T) {
|
|
ins, err := Disassemble(test.Data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if l := len(ins); l != len(test.Want) {
|
|
t.Errorf("expected %d instructions, got %d", len(test.Want), l)
|
|
}
|
|
for i, a := range ins {
|
|
if i < len(test.Want) {
|
|
if v := a.String(); v != test.Want[i] {
|
|
t.Errorf("unexpected assembly in line %d:\ntest: %q\nwant: %q", i+1, test.Want[i], v)
|
|
}
|
|
} else {
|
|
t.Errorf("unexpected %q", a)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func mustUnhex(s string) []byte {
|
|
b, err := hex.DecodeString(s)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return b
|
|
}
|
|
|
|
type testInstruction struct {
|
|
Test Instruction
|
|
WantRaw RawInstruction
|
|
WantError string
|
|
WantString string
|
|
}
|
|
|
|
func (test testInstruction) Run(t *testing.T) {
|
|
t.Helper()
|
|
|
|
r, err := test.Test.Assemble()
|
|
if err != nil {
|
|
if test.WantError == "" {
|
|
t.Fatal(err)
|
|
return
|
|
} else if v := err.Error(); v != test.WantError {
|
|
t.Errorf("unexpected error:\nwant: %v\ntest: %v", test.WantError, err)
|
|
}
|
|
t.Log(err)
|
|
return
|
|
}
|
|
|
|
if !reflect.DeepEqual(r, test.WantRaw) {
|
|
t.Errorf("unexpected result:\nwant: %#+v\ntest: %#+v", test.WantRaw, r)
|
|
}
|
|
if v := test.Test.String(); v != test.WantString {
|
|
t.Errorf("unexpected result:\nwant: %q\ntest: %q", test.WantString, v)
|
|
} else {
|
|
t.Log(v)
|
|
}
|
|
}
|
|
|
|
type testInstructionSuite []testInstruction
|
|
|
|
func (suite testInstructionSuite) Run(t *testing.T) {
|
|
t.Helper()
|
|
for _, test := range suite {
|
|
t.Run(test.WantString, func(it *testing.T) {
|
|
test.Run(it)
|
|
})
|
|
}
|
|
}
|