github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/sys/fuchsia/fidlgen/main.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  package main
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/google/syzkaller/pkg/ast"
    14  	"github.com/google/syzkaller/pkg/compiler"
    15  	"github.com/google/syzkaller/pkg/osutil"
    16  	"github.com/google/syzkaller/pkg/tool"
    17  	"github.com/google/syzkaller/sys/fuchsia/layout"
    18  	"github.com/google/syzkaller/sys/targets"
    19  )
    20  
    21  func main() {
    22  	targetArch := os.Getenv("TARGETARCH")
    23  	target := targets.Get(targets.Fuchsia, targetArch)
    24  	if target == nil {
    25  		tool.Failf("unknown TARGETARCH %s", targetArch)
    26  	}
    27  	arch := target.KernelHeaderArch
    28  
    29  	sourceDir := os.Getenv("SOURCEDIR")
    30  	if !osutil.IsExist(sourceDir) {
    31  		tool.Failf("cannot find SOURCEDIR %s", sourceDir)
    32  	}
    33  
    34  	fidlgenPath := filepath.Join(
    35  		sourceDir,
    36  		"out",
    37  		arch,
    38  		"host_x64",
    39  		"fidlgen_syzkaller",
    40  	)
    41  	if !osutil.IsExist(fidlgenPath) {
    42  		tool.Failf("cannot find fidlgen %s", fidlgenPath)
    43  	}
    44  
    45  	var newFiles []string
    46  	for _, fidlLib := range layout.AllFidlLibraries {
    47  		jsonPath := filepath.Join(sourceDir, "out", arch, fidlLib.PathToJSONIr())
    48  		txtPathBase := strings.Replace(strings.Join(fidlLib, "_"), "^fuchsia", "fidl", 1)
    49  
    50  		txtPath := fidlgen(
    51  			fidlgenPath,
    52  			jsonPath,
    53  			txtPathBase,
    54  		)
    55  
    56  		newFiles = append(newFiles, txtPath)
    57  	}
    58  
    59  	var errorPos ast.Pos
    60  	var errorMsg string
    61  	desc := ast.ParseGlob("*.txt", func(pos ast.Pos, msg string) {
    62  		errorPos = pos
    63  		errorMsg = msg
    64  	})
    65  	if desc == nil {
    66  		tool.Failf("parsing failed at %v: %v", errorPos, errorMsg)
    67  	}
    68  
    69  	unused := make(map[ast.Node]bool)
    70  
    71  	nodes, err := compiler.CollectUnused(desc, target, nil)
    72  	if err != nil {
    73  		tool.Failf("collect unused nodes failed: %v", err)
    74  	}
    75  
    76  	for _, n := range nodes {
    77  		unused[n] = true
    78  	}
    79  
    80  	pruned := desc.Filter(func(n ast.Node) bool {
    81  		_, ok := unused[n]
    82  		return !ok
    83  	})
    84  
    85  	for _, file := range newFiles {
    86  		desc := ast.Format(pruned.Filter(func(n ast.Node) bool {
    87  			pos, _, _ := n.Info()
    88  			return pos.File == file
    89  		}))
    90  
    91  		if err := osutil.WriteFile(file, desc); err != nil {
    92  			tool.Fail(err)
    93  		}
    94  	}
    95  }
    96  
    97  func fidlgen(fidlgenPath, jsonPath, txtPathBase string) string {
    98  	if !osutil.IsExist(jsonPath) {
    99  		tool.Failf("cannot find %s", jsonPath)
   100  	}
   101  
   102  	out, err := osutil.RunCmd(time.Minute, "",
   103  		fidlgenPath,
   104  		"-json", jsonPath,
   105  		"-output-syz", txtPathBase+".syz.txt",
   106  	)
   107  	if len(out) != 0 {
   108  		fmt.Println(string(out))
   109  	}
   110  
   111  	if err != nil {
   112  		tool.Failf("fidlgen failed: %v", err)
   113  	}
   114  
   115  	return fmt.Sprintf("%s.syz.txt", txtPathBase)
   116  }