github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/ifuzz/x86/x86.go (about)

     1  // Copyright 2017 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  //go:generate bash -c "go run gen/gen.go gen/all-enc-instructions.txt > generated/insns.go"
     5  
     6  // Package x86 allows to generate and mutate x86 machine code.
     7  package x86
     8  
     9  import (
    10  	"math/rand"
    11  
    12  	"github.com/google/syzkaller/pkg/ifuzz/iset"
    13  )
    14  
    15  type Insn struct {
    16  	Name      string
    17  	Extension string
    18  
    19  	Mode   iset.Mode // bitmask of compatible modes
    20  	Priv   bool      // CPL=0
    21  	Pseudo bool      // pseudo instructions can consist of several real instructions
    22  
    23  	Opcode      []byte
    24  	Prefix      []byte
    25  	Suffix      []byte
    26  	Modrm       bool
    27  	Mod         int8
    28  	Reg         int8 // -6 - segment register, -8 - control register
    29  	Rm          int8
    30  	Srm         bool // register is embed in the first byte
    31  	NoSibDisp   bool // no SIB/disp even if modrm says otherwise
    32  	Imm         int8 // immediate size, -1 - immediate size, -2 - address size, -3 - operand size
    33  	Imm2        int8
    34  	NoRepPrefix bool
    35  	No66Prefix  bool
    36  	Rexw        int8 // 1 must be set, -1 must not be set
    37  	Mem32       bool // instruction always references 32-bit memory operand, 0x67 is illegal
    38  	Mem16       bool // instruction always references 16-bit memory operand
    39  
    40  	Vex        byte
    41  	VexMap     byte
    42  	VexL       int8
    43  	VexNoR     bool
    44  	VexP       int8
    45  	Avx2Gather bool
    46  
    47  	generator func(cfg *iset.Config, r *rand.Rand) []byte // for pseudo instructions
    48  }
    49  
    50  type InsnSet struct {
    51  	modeInsns iset.ModeInsns
    52  	Insns     []*Insn
    53  }
    54  
    55  func Register(insns []*Insn) {
    56  	if len(insns) == 0 {
    57  		panic("no instructions")
    58  	}
    59  	insnset := &InsnSet{
    60  		Insns: append(insns, pseudo...),
    61  	}
    62  	for _, insn := range insnset.Insns {
    63  		insnset.modeInsns.Add(insn)
    64  	}
    65  	iset.Arches[iset.ArchX86] = insnset
    66  }
    67  
    68  func (insnset *InsnSet) GetInsns(mode iset.Mode, typ iset.Type) []iset.Insn {
    69  	return insnset.modeInsns[mode][typ]
    70  }
    71  
    72  func (insn *Insn) Info() (string, iset.Mode, bool, bool) {
    73  	return insn.Name, insn.Mode, insn.Pseudo, insn.Priv
    74  }
    75  
    76  func generateArg(cfg *iset.Config, r *rand.Rand, size int) []byte {
    77  	v := iset.GenerateInt(cfg, r, size)
    78  	arg := make([]byte, size)
    79  	for i := 0; i < size; i++ {
    80  		arg[i] = byte(v)
    81  		v >>= 8
    82  	}
    83  	return arg
    84  }