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