// Copyright 2024 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 executor import ( "bytes" "embed" "fmt" "io/fs" "maps" "path" "regexp" ) //go:embed common*.h kvm*.h android/*.h var src embed.FS // CommonHeader contains all executor common headers used by pkg/csource to generate C reproducers. // All includes in common.h are transitively replaced with their contents so that it's just a single blob. var CommonHeader = func() []byte { data, err := src.ReadFile("common.h") if err != nil { panic(err) } headers := make(map[string]bool) for _, glob := range []string{"*.h", "android/*.h"} { files, err := fs.Glob(src, glob) if err != nil { panic(err) } for _, file := range files { if file == "common.h" || file == "common_ext_example.h" { continue } headers[file] = true } } // To not hardcode concrete order in which headers need to be replaced // we just iteratively try to replace whatever headers can be replaced. unused := maps.Clone(headers) for { relacedSomething := false for file := range headers { replace := []byte("#include \"" + path.Base(file) + "\"") if !bytes.Contains(data, replace) { replace = []byte("#include \"android/" + path.Base(file) + "\"") if !bytes.Contains(data, replace) { continue } } contents, err := src.ReadFile(file) if err != nil { panic(err) } data = bytes.ReplaceAll(data, replace, contents) delete(unused, file) relacedSomething = true } if !relacedSomething { break } } if len(unused) != 0 { panic(fmt.Sprintf("can't find includes for %v", unused)) } // Remove `//` comments, but keep lines which start with `//%`. for _, remove := range []string{ "(\n|^)\\s*//$", "(\n|^)\\s*//[^%].*", "\\s*//$", "\\s*//[^%].*", } { data = regexp.MustCompile(remove).ReplaceAll(data, nil) } return data }()