diff options
Diffstat (limited to 'pkg/ifuzz/decode.go')
| -rw-r--r-- | pkg/ifuzz/decode.go | 222 |
1 files changed, 0 insertions, 222 deletions
diff --git a/pkg/ifuzz/decode.go b/pkg/ifuzz/decode.go deleted file mode 100644 index 7fecf312c..000000000 --- a/pkg/ifuzz/decode.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2017 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -package ifuzz - -import ( - "fmt" -) - -// Decode decodes instruction length for the given mode. -// It can have falsely decode incorrect instructions, -// but should not fail to decode correct instructions. -// nolint: gocyclo, nestif, gocognit, funlen -func Decode(mode int, text []byte) (int, error) { - if len(text) == 0 { - return 0, fmt.Errorf("zero-length instruction") - } - prefixes := prefixes32 - var operSize, immSize, dispSize, addrSize int - switch mode { - case ModeLong64: - operSize, immSize, dispSize, addrSize = 4, 4, 4, 8 - prefixes = prefixes64 - case ModeProt32: - operSize, immSize, dispSize, addrSize = 4, 4, 4, 4 - case ModeProt16, ModeReal16: - operSize, immSize, dispSize, addrSize = 2, 2, 2, 2 - default: - panic("bad mode") - } - prefixLen := 0 - var decodedPrefixes []byte - vex := false - if len(text) > 1 { - // There are only 2 32-bit instructions that look like VEX-prefixed but are actually not: LDS, LES. - // They always reference memory (mod!=3), but all VEX instructions have "mod=3" where LDS/LES would have mod. - if (text[0] == 0xc4 || text[0] == 0xc5) && (mode == ModeLong64 || text[1]&0xc0 == 0xc0) { - vex = true - } - // There is only one instruction that looks like XOP-prefixed but is actually not: POP. - // It always has reg=0, but all XOP instructions have "reg!=0" where POP would have reg. - if text[0] == 0x8f && text[1]&0x38 != 0 { - vex = true - } - } - var vexMap byte - if vex { - prefixLen = 3 - if text[0] == 0xc5 { - prefixLen = 2 - vexMap = 1 // V0F - } - if len(text) < prefixLen { - return 0, fmt.Errorf("bad VEX/XOP prefix") - } - if prefixLen == 3 { - vexMap = text[1] & 0x1f - } - text = text[prefixLen:] - } else { - decodedPrefixes = text - operSize1, immSize1, dispSize1, addrSize1 := operSize, immSize, dispSize, addrSize - for len(text) != 0 && prefixes[text[0]] { - switch text[0] { - case 0x66: - if immSize == 4 { - immSize1 = 2 - operSize1 = 2 - } else if immSize == 2 { - immSize1 = 4 - operSize1 = 4 - } - case 0x67: - if addrSize == 8 { - addrSize1 = 4 - } else if addrSize == 4 { - dispSize1 = 2 - addrSize1 = 2 - } else if addrSize == 2 { - dispSize1 = 4 - addrSize1 = 4 - } - } - if text[0] & ^byte(7) == 0x48 { - operSize1 = 8 - immSize1 = 4 - } - text = text[1:] - prefixLen++ - } - operSize, immSize, dispSize, addrSize = operSize1, immSize1, dispSize1, addrSize1 - decodedPrefixes = decodedPrefixes[:prefixLen] - if len(text) == 0 { - return 0, fmt.Errorf("no opcode, only prefixes") - } - } -nextInsn: - for _, insn := range modeInsns[mode][typeAll] { - if vex != (insn.Vex != 0) { - continue nextInsn - } - if vex && insn.VexMap != vexMap { - continue nextInsn - } - if insn.NoRepPrefix || insn.No66Prefix { - for _, p := range decodedPrefixes { - if len(insn.Prefix) != 0 && insn.Prefix[0] == p { - continue - } - switch p { - case 0xf2, 0xf3: - if insn.NoRepPrefix { - continue nextInsn - } - case 0x66: - if insn.No66Prefix { - continue nextInsn - } - } - } - } - text1 := text - for i, v := range insn.Opcode { - if len(text1) == 0 { - continue nextInsn - } - b := text1[0] - if insn.Srm && i == len(insn.Opcode)-1 { - b &^= 7 - } - if b != v { - continue nextInsn - } - text1 = text1[1:] - } - if insn.Modrm { - if len(text1) == 0 { - continue nextInsn - } - modrm := text1[0] - text1 = text1[1:] - mod := modrm >> 6 - rm := modrm & 7 - if !insn.NoSibDisp { - disp := 0 - if addrSize == 2 { - if mod == 1 { - disp = 1 - } else if mod == 2 || mod == 0 && rm == 6 { - disp = 2 - } - } else { - var sibbase byte - if mod != 3 && rm == 4 { - if len(text1) == 0 { - continue nextInsn - } - sib := text1[0] - text1 = text1[1:] - sibbase = sib & 7 - } - if mod == 1 { - disp = 1 - } else if mod == 2 || mod == 0 && rm == 5 || mod == 0 && sibbase == 5 { - disp = dispSize - } - } - if disp != 0 { - if len(text1) < disp { - continue nextInsn - } - text1 = text1[disp:] - } - } - } - immLen := 0 - for _, imm := range []int8{insn.Imm, insn.Imm2} { - switch imm { - case -1: - immLen += immSize - case -2: - immLen += addrSize - case -3: - immLen += operSize - default: - immLen += int(imm) - } - } - if immLen != 0 { - if len(text1) < immLen { - continue nextInsn - } - text1 = text1[immLen:] - } - for _, v := range insn.Suffix { - if len(text1) == 0 || text1[0] != v { - continue nextInsn - } - text1 = text1[1:] - } - return prefixLen + len(text) - len(text1), nil - } - return 0, fmt.Errorf("unknown instruction") -} - -var XedDecode func(mode int, text []byte) (int, error) - -var ( - prefixes32 = map[byte]bool{ - 0x2E: true, 0x3E: true, 0x26: true, 0x64: true, 0x65: true, - 0x36: true, 0x66: true, 0x67: true, 0xF3: true, 0xF2: true, - 0xF0: true, - } - prefixes64 = map[byte]bool{ - 0x2E: true, 0x3E: true, 0x26: true, 0x64: true, 0x65: true, - 0x36: true, 0x66: true, 0x67: true, 0xF3: true, 0xF2: true, - 0xF0: true, 0x40: true, 0x41: true, 0x42: true, 0x43: true, - 0x44: true, 0x45: true, 0x46: true, 0x47: true, 0x48: true, - 0x49: true, 0x4a: true, 0x4b: true, 0x4c: true, 0x4d: true, - 0x4e: true, 0x4f: true, - } -) |
