aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/ifuzz/iset
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-11-20 19:28:53 +0100
committerDmitry Vyukov <dvyukov@google.com>2020-11-21 08:46:20 +0100
commit418476ecb925e5d58ba9c22928a4e37dc30909df (patch)
tree702468b5ca1b0df89a83d861b18eaff9ae2237c5 /pkg/ifuzz/iset
parente1dea42221c13dabdf9d4938428f1ef91863b813 (diff)
pkg/ifuzz/iset: rename ifuzzimpl to iset
ifuzzimpl is too lenghty and too clumsy on my taste (nm/vmimpl worked better b/c it's shorter and used less). I've tried to come up with something shorter and nicer. We could use "insn" as a common name for "instruction" in ifuzz, but it's a commonly used name already so would cause lots of conflicts. "iset" is somewhat descriptive, short and nice.
Diffstat (limited to 'pkg/ifuzz/iset')
-rw-r--r--pkg/ifuzz/iset/iset.go102
1 files changed, 102 insertions, 0 deletions
diff --git a/pkg/ifuzz/iset/iset.go b/pkg/ifuzz/iset/iset.go
new file mode 100644
index 000000000..46c42537d
--- /dev/null
+++ b/pkg/ifuzz/iset/iset.go
@@ -0,0 +1,102 @@
+// 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 iset ("instruction set") provides base and helper types for ifuzz arch implementations.
+package iset
+
+import (
+ "math/rand"
+)
+
+const (
+ ArchX86 = "x86"
+ ArchPowerPC = "powerpc"
+)
+
+var Arches = make(map[string]InsnSet)
+
+type (
+ Mode int
+ Type int
+)
+
+type Insn interface {
+ Info() (name string, mode Mode, pseudo, priv bool)
+ Encode(cfg *Config, r *rand.Rand) []byte
+}
+
+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
+}
+
+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
+}
+
+type MemRegion struct {
+ Start uint64
+ Size uint64
+}
+
+const (
+ ModeLong64 Mode = iota
+ ModeProt32
+ ModeProt16
+ ModeReal16
+ ModeLast
+)
+
+const (
+ TypeExec Type = iota
+ TypePriv
+ TypeUser
+ TypeAll
+ TypeLast
+)
+
+var SpecialNumbers = [...]uint64{0, 1 << 15, 1 << 16, 1 << 31, 1 << 32, 1 << 47, 1 << 47, 1 << 63}
+
+type ModeInsns [ModeLast][TypeLast][]Insn
+
+func (modeInsns *ModeInsns) Add(insn Insn) {
+ _, mode, pseudo, priv := insn.Info()
+ for m := Mode(0); m < ModeLast; m++ {
+ if mode&(1<<uint(m)) == 0 {
+ continue
+ }
+ set := &modeInsns[m]
+ if pseudo {
+ set[TypeExec] = append(set[TypeExec], insn)
+ } else if priv {
+ set[TypePriv] = append(set[TypePriv], insn)
+ set[TypeAll] = append(set[TypeAll], insn)
+ } else {
+ set[TypeUser] = append(set[TypeUser], insn)
+ set[TypeAll] = append(set[TypeAll], insn)
+ }
+ }
+}
+
+func (cfg *Config) IsCompatible(insn Insn) bool {
+ _, mode, pseudo, priv := insn.Info()
+ if cfg.Mode < 0 || cfg.Mode >= ModeLast {
+ panic("bad mode")
+ }
+ if priv && !cfg.Priv {
+ return false
+ }
+ if pseudo && !cfg.Exec {
+ return false
+ }
+ if mode&(1<<uint(cfg.Mode)) == 0 {
+ return false
+ }
+ return true
+}