aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/ifuzz/ifuzzimpl/ifuzzimpl.go')
-rw-r--r--pkg/ifuzz/ifuzzimpl/ifuzzimpl.go180
1 files changed, 59 insertions, 121 deletions
diff --git a/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go b/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go
index f1ea64f37..71485172c 100644
--- a/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go
+++ b/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go
@@ -4,142 +4,80 @@
package ifuzzimpl
import (
- "github.com/google/syzkaller/pkg/ifuzz"
"math/rand"
)
-var (
- Types = make(map[string]ifuzz.InsnSet)
+const (
+ ArchX86 = "x86"
+ ArchPowerPC = "powerpc"
)
-func Register(arch string, insns ifuzz.InsnSet) {
- Types[arch] = insns
-}
+var Arches = make(map[string]InsnSet)
-// ModeInsns returns list of all instructions for the given mode.
-func ModeInsns(cfg *ifuzz.Config) []ifuzz.Insn {
- insnset := Types[cfg.Arch]
- if cfg.Mode < 0 || cfg.Mode >= ifuzz.ModeLast {
- panic("bad mode")
- }
- var insns []ifuzz.Insn
- insns = append(insns, insnset.GetInsns(cfg.Mode, ifuzz.TypeUser)...)
- if cfg.Priv {
- insns = append(insns, insnset.GetInsns(cfg.Mode, ifuzz.TypePriv)...)
- if cfg.Exec {
- insns = append(insns, insnset.GetInsns(cfg.Mode, ifuzz.TypeExec)...)
- }
- }
- return insns
+type (
+ Mode int
+ Type int
+)
+
+type Insn interface {
+ GetName() string
+ GetMode() int
+ GetPseudo() bool
+ GetPriv() bool
+ IsCompatible(cfg *Config) bool
+ Encode(cfg *Config, r *rand.Rand) []byte
}
-func Generate(cfg *ifuzz.Config, r *rand.Rand) []byte {
- var text []byte
- for i := 0; i < cfg.Len; i++ {
- insn := randInsn(cfg, r)
- text = append(text, insn.Encode(cfg, r)...)
- }
- return text
+type InsnSet interface {
+ GetInsns(mode Mode, typ Type) []Insn
+ Decode(mode Mode, text []byte) (int, error)
+ DecodeExt(mode Mode, text []byte) (int, error) // XED, to keep ifuzz_test happy
}
-func Mutate(cfg *ifuzz.Config, r *rand.Rand, text []byte) []byte {
- insns := split(cfg, text)
- retry := false
- for stop := false; !stop || retry || len(insns) == 0; stop = r.Intn(2) == 0 {
- retry = false
- switch x := r.Intn(100); {
- case x < 10 && len(insns) != 0:
- // Delete instruction.
- i := r.Intn(len(insns))
- copy(insns[i:], insns[i+1:])
- insns = insns[:len(insns)-1]
- case x < 40 && len(insns) != 0:
- // Replace instruction with another.
- insn := randInsn(cfg, r)
- text1 := insn.Encode(cfg, r)
- i := r.Intn(len(insns))
- insns[i] = text1
- case x < 70 && len(insns) != 0:
- // Mutate instruction.
- i := r.Intn(len(insns))
- text1 := insns[i]
- for stop := false; !stop || len(text1) == 0; stop = r.Intn(2) == 0 {
- switch x := r.Intn(100); {
- case x < 5 && len(text1) != 0:
- // Delete byte.
- pos := r.Intn(len(text1))
- copy(text1[pos:], text1[pos+1:])
- text1 = text1[:len(text1)-1]
- case x < 40 && len(text1) != 0:
- // Replace a byte.
- pos := r.Intn(len(text1))
- text1[pos] = byte(r.Intn(256))
- case x < 70 && len(text1) != 0:
- // Flip a bit.
- pos := r.Intn(len(text1))
- text1[pos] ^= 1 << byte(r.Intn(8))
- default:
- // Insert a byte.
- pos := r.Intn(len(text1) + 1)
- text1 = append(text1, 0)
- copy(text1[pos+1:], text1[pos:])
- text1[pos] = byte(r.Intn(256))
- }
- }
- insns[i] = text1
- case len(insns) < cfg.Len:
- // Insert a new instruction.
- insn := randInsn(cfg, r)
- text1 := insn.Encode(cfg, r)
- i := r.Intn(len(insns) + 1)
- insns = append(insns, nil)
- copy(insns[i+1:], insns[i:])
- insns[i] = text1
- default:
- retry = true
- }
- }
- text = nil
- for _, insn := range insns {
- text = append(text, insn...)
- }
- return text
+type Config struct {
+ Arch string
+ Len int // number of instructions to generate
+ Mode Mode // one of ModeXXX
+ Priv bool // generate CPL=0 instructions (x86), HV/!PR mode (PPC)
+ Exec bool // generate instructions sequences interesting for execution
+ MemRegions []MemRegion // generated instructions will reference these regions
}
-func randInsn(cfg *ifuzz.Config, r *rand.Rand) ifuzz.Insn {
- insnset := Types[cfg.Arch]
- var insns []ifuzz.Insn
- if cfg.Priv && cfg.Exec {
- insns = insnset.GetInsns(cfg.Mode, r.Intn(3))
- } else if cfg.Priv {
- insns = insnset.GetInsns(cfg.Mode, r.Intn(2))
- } else {
- insns = insnset.GetInsns(cfg.Mode, ifuzz.TypeUser)
- }
- return insns[r.Intn(len(insns))]
+type MemRegion struct {
+ Start uint64
+ Size uint64
}
-func split(cfg *ifuzz.Config, text []byte) [][]byte {
- insnset := Types[cfg.Arch]
- text = append([]byte{}, text...)
- var insns [][]byte
- var bad []byte
- for len(text) != 0 {
- n, err := insnset.Decode(cfg.Mode, text)
- if err != nil || n == 0 {
- bad = append(bad, text[0])
- text = text[1:]
- continue
- }
- if bad != nil {
- insns = append(insns, bad)
- bad = nil
- }
- insns = append(insns, text[:n])
- text = text[n:]
+const (
+ ModeLong64 Mode = iota
+ ModeProt32
+ ModeProt16
+ ModeReal16
+ ModeLast
+)
+
+const (
+ TypeExec Type = iota
+ TypePriv
+ TypeUser
+ TypeAll
+ TypeLast
+)
+
+// ModeInsns returns list of all instructions for the given mode.
+func ModeInsns(cfg *Config) []Insn {
+ insnset := Arches[cfg.Arch]
+ if cfg.Mode < 0 || cfg.Mode >= ModeLast {
+ panic("bad mode")
}
- if bad != nil {
- insns = append(insns, bad)
+ insns := insnset.GetInsns(cfg.Mode, TypeUser)
+ if cfg.Priv {
+ insns = append(insns, insnset.GetInsns(cfg.Mode, TypePriv)...)
+ if cfg.Exec {
+ insns = append(insns, insnset.GetInsns(cfg.Mode, TypeExec)...)
+ }
}
return insns
}
+
+var SpecialNumbers = [...]uint64{0, 1 << 15, 1 << 16, 1 << 31, 1 << 32, 1 << 47, 1 << 47, 1 << 63}