// 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" "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 // on the current step. for len(headers) != 0 { 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(headers, file) relacedSomething = true } if !relacedSomething { panic(fmt.Sprintf("can't find includes for %v", headers)) } } // 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 }()