github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-trace2syz/trace2syz.go (about)

     1  // Copyright 2018 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:build !codeanalysis
     5  
     6  // syz-trace2syz converts strace traces to syzkaller programs.
     7  //
     8  // Simple usage:
     9  //
    10  //	strace -o trace -a 1 -s 65500 -v -xx -f -Xraw ./a.out
    11  //	syz-trace2syz -file trace
    12  //
    13  // Intended for seed selection or debugging
    14  package main
    15  
    16  import (
    17  	"flag"
    18  	"os"
    19  	"path/filepath"
    20  	"strconv"
    21  
    22  	"github.com/google/syzkaller/pkg/db"
    23  	"github.com/google/syzkaller/pkg/log"
    24  	"github.com/google/syzkaller/pkg/osutil"
    25  	"github.com/google/syzkaller/prog"
    26  	_ "github.com/google/syzkaller/sys"
    27  	"github.com/google/syzkaller/sys/targets"
    28  	"github.com/google/syzkaller/tools/syz-trace2syz/proggen"
    29  )
    30  
    31  var (
    32  	flagFile        = flag.String("file", "", "file to parse")
    33  	flagDir         = flag.String("dir", "", "directory to parse")
    34  	flagDeserialize = flag.String("deserialize", "", "(Optional) directory to store deserialized programs")
    35  )
    36  
    37  const (
    38  	goos = targets.Linux // Target OS
    39  	arch = targets.AMD64 // Target architecture
    40  )
    41  
    42  func main() {
    43  	flag.Parse()
    44  	target := initializeTarget(goos, arch)
    45  	progs := parseTraces(target)
    46  	log.Logf(0, "successfully converted traces; generating corpus.db")
    47  	pack(progs)
    48  }
    49  
    50  func initializeTarget(os, arch string) *prog.Target {
    51  	target, err := prog.GetTarget(os, arch)
    52  	if err != nil {
    53  		log.Fatalf("failed to load target: %s", err)
    54  	}
    55  	target.ConstMap = make(map[string]uint64)
    56  	for _, c := range target.Consts {
    57  		target.ConstMap[c.Name] = c.Value
    58  	}
    59  	return target
    60  }
    61  
    62  func parseTraces(target *prog.Target) []*prog.Prog {
    63  	var ret []*prog.Prog
    64  	var names []string
    65  
    66  	if *flagFile != "" {
    67  		names = append(names, *flagFile)
    68  	} else if *flagDir != "" {
    69  		names = getTraceFiles(*flagDir)
    70  	} else {
    71  		log.Fatalf("-file or -dir must be specified")
    72  	}
    73  
    74  	deserializeDir := *flagDeserialize
    75  
    76  	totalFiles := len(names)
    77  	log.Logf(0, "parsing %v traces", totalFiles)
    78  	for i, file := range names {
    79  		log.Logf(1, "parsing file %v/%v: %v", i+1, totalFiles, filepath.Base(names[i]))
    80  		progs, err := proggen.ParseFile(file, target)
    81  		if err != nil {
    82  			log.Fatalf("%v", err)
    83  		}
    84  		ret = append(ret, progs...)
    85  		if deserializeDir != "" {
    86  			for i, p := range progs {
    87  				progName := filepath.Join(deserializeDir, filepath.Base(file)+strconv.Itoa(i))
    88  				if err := osutil.WriteFile(progName, p.Serialize()); err != nil {
    89  					log.Fatalf("failed to output file: %v", err)
    90  				}
    91  			}
    92  		}
    93  	}
    94  	return ret
    95  }
    96  
    97  func getTraceFiles(dir string) []string {
    98  	infos, err := os.ReadDir(dir)
    99  	if err != nil {
   100  		log.Fatalf("%s", err)
   101  
   102  	}
   103  	var names []string
   104  	for _, info := range infos {
   105  		name := filepath.Join(dir, info.Name())
   106  		names = append(names, name)
   107  	}
   108  	return names
   109  }
   110  
   111  func pack(progs []*prog.Prog) {
   112  	var records []db.Record
   113  	for _, prog := range progs {
   114  		records = append(records, db.Record{Val: prog.Serialize()})
   115  	}
   116  	if err := db.Create("corpus.db", 0, records); err != nil {
   117  		log.Fatalf("%v", err)
   118  	}
   119  	log.Logf(0, "finished!")
   120  }