github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/executor/embed.go (about)

     1  // Copyright 2024 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 executor
     5  
     6  import (
     7  	"bytes"
     8  	"embed"
     9  	"fmt"
    10  	"io/fs"
    11  	"maps"
    12  	"path"
    13  	"regexp"
    14  )
    15  
    16  //go:embed common*.h kvm*.h android/*.h
    17  var src embed.FS
    18  
    19  // CommonHeader contains all executor common headers used by pkg/csource to generate C reproducers.
    20  // All includes in common.h are transitively replaced with their contents so that it's just a single blob.
    21  var CommonHeader = func() []byte {
    22  	data, err := src.ReadFile("common.h")
    23  	if err != nil {
    24  		panic(err)
    25  	}
    26  	headers := make(map[string]bool)
    27  	for _, glob := range []string{"*.h", "android/*.h"} {
    28  		files, err := fs.Glob(src, glob)
    29  		if err != nil {
    30  			panic(err)
    31  		}
    32  		for _, file := range files {
    33  			if file == "common.h" || file == "common_ext_example.h" {
    34  				continue
    35  			}
    36  			headers[file] = true
    37  		}
    38  	}
    39  	// To not hardcode concrete order in which headers need to be replaced
    40  	// we just iteratively try to replace whatever headers can be replaced.
    41  	unused := maps.Clone(headers)
    42  	for {
    43  		relacedSomething := false
    44  		for file := range headers {
    45  			replace := []byte("#include \"" + path.Base(file) + "\"")
    46  			if !bytes.Contains(data, replace) {
    47  				replace = []byte("#include \"android/" + path.Base(file) + "\"")
    48  				if !bytes.Contains(data, replace) {
    49  					continue
    50  				}
    51  			}
    52  			contents, err := src.ReadFile(file)
    53  			if err != nil {
    54  				panic(err)
    55  			}
    56  			data = bytes.ReplaceAll(data, replace, contents)
    57  			delete(unused, file)
    58  			relacedSomething = true
    59  		}
    60  		if !relacedSomething {
    61  			break
    62  		}
    63  	}
    64  	if len(unused) != 0 {
    65  		panic(fmt.Sprintf("can't find includes for %v", unused))
    66  	}
    67  	// Remove `//` comments, but keep lines which start with `//%`.
    68  	for _, remove := range []string{
    69  		"(\n|^)\\s*//$",
    70  		"(\n|^)\\s*//[^%].*",
    71  		"\\s*//$",
    72  		"\\s*//[^%].*",
    73  	} {
    74  		data = regexp.MustCompile(remove).ReplaceAll(data, nil)
    75  	}
    76  	return data
    77  }()