aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/ifuzz/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/ifuzz/decode.go')
-rw-r--r--pkg/ifuzz/decode.go222
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,
- }
-)