diff --git a/pkg/cmdprof/cmdprof.go b/pkg/cmdprof/cmdprof.go new file mode 100644 index 00000000..ab0396d1 --- /dev/null +++ b/pkg/cmdprof/cmdprof.go @@ -0,0 +1,57 @@ +// Copyright 2020 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 cmdprof simplifies cpu/memory profiling for command line tools. Use as: +// flag.Parse() +// defer cmdprof.Install()() +package cmdprof + +import ( + "flag" + "fmt" + "os" + "runtime" + "runtime/pprof" +) + +var ( + flagCPUProfile = flag.String("cpuprofile", "", "write CPU profile to this file") + flagMEMProfile = flag.String("memprofile", "", "write memory profile to this file") +) + +func Install() func() { + res := func() {} + failf := func(msg string, args ...interface{}) { + fmt.Fprintf(os.Stderr, msg+"\n", args...) + os.Exit(1) + } + if *flagCPUProfile != "" { + f, err := os.Create(*flagCPUProfile) + if err != nil { + failf("failed to create cpuprofile file: %v", err) + } + if err := pprof.StartCPUProfile(f); err != nil { + failf("failed to start cpu profile: %v", err) + } + res = func() { + pprof.StopCPUProfile() + f.Close() + } + } + if *flagMEMProfile != "" { + prev := res + res = func() { + prev() + f, err := os.Create(*flagMEMProfile) + if err != nil { + failf("failed to create memprofile file: %v", err) + } + defer f.Close() + runtime.GC() + if err := pprof.WriteHeapProfile(f); err != nil { + failf("failed to write mem profile: %v", err) + } + } + } + return res +} diff --git a/sys/syz-sysgen/sysgen.go b/sys/syz-sysgen/sysgen.go index a424e148..1197a8cc 100644 --- a/sys/syz-sysgen/sysgen.go +++ b/sys/syz-sysgen/sysgen.go @@ -13,14 +13,13 @@ import ( "os" "path/filepath" "reflect" - "runtime" - "runtime/pprof" "sort" "strings" "sync" "text/template" "github.com/google/syzkaller/pkg/ast" + "github.com/google/syzkaller/pkg/cmdprof" "github.com/google/syzkaller/pkg/compiler" "github.com/google/syzkaller/pkg/hash" "github.com/google/syzkaller/pkg/osutil" @@ -29,10 +28,6 @@ import ( "github.com/google/syzkaller/sys/targets" ) -var ( - flagMemProfile = flag.String("memprofile", "", "write a memory profile to the file") -) - type SyscallData struct { Name string CallName string @@ -64,6 +59,7 @@ type ExecutorData struct { func main() { flag.Parse() + defer cmdprof.Install()() var OSList []string for OS := range targets.List { @@ -175,18 +171,6 @@ func main() { } writeExecutorSyscalls(data) - - if *flagMemProfile != "" { - f, err := os.Create(*flagMemProfile) - if err != nil { - failf("could not create memory profile: ", err) - } - runtime.GC() // get up-to-date statistics - if err := pprof.WriteHeapProfile(f); err != nil { - failf("could not write memory profile: ", err) - } - f.Close() - } } func generate(target *targets.Target, prg *compiler.Prog, consts map[string]uint64, out io.Writer) { diff --git a/tools/syz-check/check.go b/tools/syz-check/check.go index 76a52c50..490a48c3 100644 --- a/tools/syz-check/check.go +++ b/tools/syz-check/check.go @@ -31,12 +31,12 @@ import ( "os" "path/filepath" "runtime" - "runtime/pprof" "sort" "strings" "unsafe" "github.com/google/syzkaller/pkg/ast" + "github.com/google/syzkaller/pkg/cmdprof" "github.com/google/syzkaller/pkg/compiler" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/pkg/symbolizer" @@ -46,11 +46,9 @@ import ( func main() { var ( - flagOS = flag.String("os", runtime.GOOS, "OS") - flagCPUProfile = flag.String("cpuprofile", "", "write CPU profile to this file") - flagMEMProfile = flag.String("memprofile", "", "write memory profile to this file") - flagDWARF = flag.Bool("dwarf", true, "do checking based on DWARF") - flagNetlink = flag.Bool("netlink", true, "do checking of netlink policies") + flagOS = flag.String("os", runtime.GOOS, "OS") + flagDWARF = flag.Bool("dwarf", true, "do checking based on DWARF") + flagNetlink = flag.Bool("netlink", true, "do checking of netlink policies") ) arches := map[string]*string{"amd64": nil, "386": nil, "arm64": nil, "arm": nil} for arch := range arches { @@ -61,30 +59,7 @@ func main() { os.Exit(1) } flag.Parse() - if *flagCPUProfile != "" { - f, err := os.Create(*flagCPUProfile) - if err != nil { - failf("failed to create cpuprofile file: %v", err) - } - defer f.Close() - if err := pprof.StartCPUProfile(f); err != nil { - failf("failed to start cpu profile: %v", err) - } - defer pprof.StopCPUProfile() - } - if *flagMEMProfile != "" { - defer func() { - f, err := os.Create(*flagMEMProfile) - if err != nil { - failf("failed to create memprofile file: %v", err) - } - defer f.Close() - runtime.GC() - if err := pprof.WriteHeapProfile(f); err != nil { - failf("failed to write mem profile: %v", err) - } - }() - } + defer cmdprof.Install()() var warnings []Warn for arch, obj := range arches { if *obj == "" {