mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-26 21:00:30 +00:00
tools: add syz-expand
The syz-expand tools allows to parse a program and print it including all the default values. This is mainly useful for debugging, like doing manual program modifications while trying to come up with a reproducer for some particular kernel behavior.
This commit is contained in:
parent
1e9788a0d9
commit
2b854f96b1
3
Makefile
3
Makefile
@ -172,6 +172,9 @@ trace2syz:
|
|||||||
usbgen:
|
usbgen:
|
||||||
GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-usbgen github.com/google/syzkaller/tools/syz-usbgen
|
GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-usbgen github.com/google/syzkaller/tools/syz-usbgen
|
||||||
|
|
||||||
|
expand:
|
||||||
|
GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-expand github.com/google/syzkaller/tools/syz-expand
|
||||||
|
|
||||||
# `extract` extracts const files from various kernel sources, and may only
|
# `extract` extracts const files from various kernel sources, and may only
|
||||||
# re-generate parts of files.
|
# re-generate parts of files.
|
||||||
extract: bin/syz-extract
|
extract: bin/syz-extract
|
||||||
|
@ -25,11 +25,20 @@ func (p *Prog) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prog) Serialize() []byte {
|
func (p *Prog) Serialize() []byte {
|
||||||
|
return p.serialize(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prog) SerializeVerbose() []byte {
|
||||||
|
return p.serialize(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prog) serialize(verbose bool) []byte {
|
||||||
p.debugValidate()
|
p.debugValidate()
|
||||||
ctx := &serializer{
|
ctx := &serializer{
|
||||||
target: p.Target,
|
target: p.Target,
|
||||||
buf: new(bytes.Buffer),
|
buf: new(bytes.Buffer),
|
||||||
vars: make(map[*ResultArg]int),
|
vars: make(map[*ResultArg]int),
|
||||||
|
verbose: verbose,
|
||||||
}
|
}
|
||||||
for _, c := range p.Calls {
|
for _, c := range p.Calls {
|
||||||
ctx.call(c)
|
ctx.call(c)
|
||||||
@ -38,10 +47,11 @@ func (p *Prog) Serialize() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type serializer struct {
|
type serializer struct {
|
||||||
target *Target
|
target *Target
|
||||||
buf *bytes.Buffer
|
buf *bytes.Buffer
|
||||||
vars map[*ResultArg]int
|
vars map[*ResultArg]int
|
||||||
varSeq int
|
varSeq int
|
||||||
|
verbose bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *serializer) printf(text string, args ...interface{}) {
|
func (ctx *serializer) printf(text string, args ...interface{}) {
|
||||||
@ -91,7 +101,7 @@ func (a *PointerArg) serialize(ctx *serializer) {
|
|||||||
}
|
}
|
||||||
target := ctx.target
|
target := ctx.target
|
||||||
ctx.printf("&%v", target.serializeAddr(a))
|
ctx.printf("&%v", target.serializeAddr(a))
|
||||||
if a.Res != nil && isDefault(a.Res) && !target.isAnyPtr(a.Type()) {
|
if a.Res != nil && !ctx.verbose && isDefault(a.Res) && !target.isAnyPtr(a.Type()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.printf("=")
|
ctx.printf("=")
|
||||||
@ -136,7 +146,7 @@ func (a *GroupArg) serialize(ctx *serializer) {
|
|||||||
}
|
}
|
||||||
ctx.buf.WriteByte(delims[0])
|
ctx.buf.WriteByte(delims[0])
|
||||||
lastNonDefault := len(a.Inner) - 1
|
lastNonDefault := len(a.Inner) - 1
|
||||||
if a.fixedInnerSize() {
|
if !ctx.verbose && a.fixedInnerSize() {
|
||||||
for ; lastNonDefault >= 0; lastNonDefault-- {
|
for ; lastNonDefault >= 0; lastNonDefault-- {
|
||||||
if !isDefault(a.Inner[lastNonDefault]) {
|
if !isDefault(a.Inner[lastNonDefault]) {
|
||||||
break
|
break
|
||||||
@ -158,7 +168,7 @@ func (a *GroupArg) serialize(ctx *serializer) {
|
|||||||
|
|
||||||
func (a *UnionArg) serialize(ctx *serializer) {
|
func (a *UnionArg) serialize(ctx *serializer) {
|
||||||
ctx.printf("@%v", a.Option.Type().FieldName())
|
ctx.printf("@%v", a.Option.Type().FieldName())
|
||||||
if isDefault(a.Option) {
|
if !ctx.verbose && isDefault(a.Option) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.printf("=")
|
ctx.printf("=")
|
||||||
|
@ -46,19 +46,31 @@ func TestDefaultCallArgs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSerialize(t *testing.T) {
|
func testSerialize(t *testing.T, verbose bool) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, nil)
|
||||||
data := p.Serialize()
|
var data []byte
|
||||||
p1, err := target.Deserialize(data, NonStrict)
|
mode := NonStrict
|
||||||
|
if verbose {
|
||||||
|
data = p.SerializeVerbose()
|
||||||
|
mode = Strict
|
||||||
|
} else {
|
||||||
|
data = p.Serialize()
|
||||||
|
}
|
||||||
|
p1, err := target.Deserialize(data, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to deserialize program: %v\n%s", err, data)
|
t.Fatalf("failed to deserialize program: %v\n%s", err, data)
|
||||||
}
|
}
|
||||||
if p1 == nil {
|
if p1 == nil {
|
||||||
t.Fatalf("deserialized nil program:\n%s", data)
|
t.Fatalf("deserialized nil program:\n%s", data)
|
||||||
}
|
}
|
||||||
data1 := p1.Serialize()
|
var data1 []byte
|
||||||
|
if verbose {
|
||||||
|
data1 = p1.SerializeVerbose()
|
||||||
|
} else {
|
||||||
|
data1 = p1.Serialize()
|
||||||
|
}
|
||||||
if len(p.Calls) != len(p1.Calls) {
|
if len(p.Calls) != len(p1.Calls) {
|
||||||
t.Fatalf("different number of calls")
|
t.Fatalf("different number of calls")
|
||||||
}
|
}
|
||||||
@ -68,6 +80,14 @@ func TestSerialize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSerialize(t *testing.T) {
|
||||||
|
testSerialize(t, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSerializeVerbose(t *testing.T) {
|
||||||
|
testSerialize(t, true)
|
||||||
|
}
|
||||||
|
|
||||||
func TestVmaType(t *testing.T) {
|
func TestVmaType(t *testing.T) {
|
||||||
target, rs, iters := initRandomTargetTest(t, "test", "64")
|
target, rs, iters := initRandomTargetTest(t, "test", "64")
|
||||||
meta := target.SyscallMap["test$vma0"]
|
meta := target.SyscallMap["test$vma0"]
|
||||||
|
52
tools/syz-expand/expand.go
Normal file
52
tools/syz-expand/expand.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright 2019 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.
|
||||||
|
|
||||||
|
// Parses a program and prints it including all default values.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/google/syzkaller/prog"
|
||||||
|
_ "github.com/google/syzkaller/sys"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
flagOS = flag.String("os", runtime.GOOS, "target os")
|
||||||
|
flagArch = flag.String("arch", runtime.GOARCH, "target arch")
|
||||||
|
flagProg = flag.String("prog", "", "file with program to expand")
|
||||||
|
flagStrict = flag.Bool("strict", false, "parse input program in strict mode")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
if *flagProg == "" {
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
target, err := prog.GetTarget(*flagOS, *flagArch)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadFile(*flagProg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
mode := prog.NonStrict
|
||||||
|
if *flagStrict {
|
||||||
|
mode = prog.Strict
|
||||||
|
}
|
||||||
|
p, err := target.Deserialize(data, mode)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s", p.SerializeVerbose())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user