blob: 8414a2b6549c19b9dc8d98acf93cca73eeddf15c [file] [log] [blame]
package main
import (
"bytes"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/google/blueprint/parser"
)
var (
result = make(map[string]string)
defaults = make(map[string]string)
Root = ""
)
var (
exitCode = 0
)
func report(err error) {
fmt.Fprintln(os.Stderr, err)
exitCode = 2
}
func usage() {
usageViolation("")
}
func usageViolation(violation string) {
fmt.Fprintln(os.Stderr, violation)
fmt.Fprintln(os.Stderr, "usage: fuzzparser [flags] [path ...]")
flag.PrintDefaults()
os.Exit(2)
}
func processFile(filename string, out io.Writer) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
return processReader(filename, f, out)
}
func processReader(filename string, in io.Reader, out io.Writer) error {
src, err := ioutil.ReadAll(in)
if err != nil {
return err
}
r := bytes.NewBuffer(src)
file, errs := parser.ParseAndEval(filename, r, parser.NewScope(nil))
modules := findModules(file)
// First collect all the defaults into a dictionary
for _, mod := range modules {
if mod.Type == "cc_defaults" {
default_name := ""
for _, prop := range mod.Map.Properties {
if prop.Name == "name" {
value := prop.Value.String()
default_name = value[1:strings.Index(value, "@")-1]
} else if prop.Name == "static_libs" || prop.Name == "shared_libs" {
value := prop.Value.String()
for strings.Index(value, "\"") > -1 {
value = value[strings.Index(value, "\"")+1:]
lib_name := value[:strings.Index(value, "\"")]
if _ , ok := defaults[default_name]; ok {
defaults[default_name] += "," + lib_name
} else {
defaults[default_name] += lib_name
}
value = value[strings.Index(value, "\"")+1:]
}
} else if prop.Name == "defaults" {
// Get the defaults of the default
value := prop.Value.String()
for strings.Index(value, "\"") > -1 {
value = value[strings.Index(value, "\"")+1:]
sub_default_name := value[:strings.Index(value, "\"")]
if _ , ok := defaults[default_name]; ok {
defaults[default_name] += "," + defaults[sub_default_name]
} else {
defaults[default_name] += defaults[sub_default_name]
}
value = value[strings.Index(value, "\"")+1:]
}
} else if prop.Name == "target" {
value := prop.Value.String()
if default_name == "binder_fuzz_defaults" {
fmt.Printf("---> target value for %s: %s\n", default_name ,value)
}
for strings.Index(value, "\"") > -1 {
value = value[strings.Index(value, "\"")+1:]
lib := value[:strings.Index(value, "\"")]
if _ , ok := defaults[default_name]; ok {
defaults[default_name] += "," + lib
} else {
defaults[default_name] += lib
}
value = value[strings.Index(value, "\"")+1:]
}
}
}
}
}
for _, mod := range modules {
if mod.Type == "cc_fuzz" {
fuzzer_name := ""
for _, prop := range mod.Map.Properties {
// First get the name of the fuzzer
if prop.Name == "name" {
value := prop.Value.String()
fuzzer_name = value[1:strings.Index(value, "@")-1]
} else if prop.Name == "defaults" {
value := prop.Value.String()
if strings.Index(value, "@") == 0 {
value = value[1:]
}
default_name := value[strings.Index(value, "[")+2: strings.Index(value, "@")-1]
if _, ok := result[fuzzer_name]; ok {
result[fuzzer_name] += "," + defaults[default_name]
} else {
result[fuzzer_name] += defaults[default_name]
}
} else if prop.Name == "static_libs" || prop.Name == "shared_libs" {
value := prop.Value.String()
for strings.Index(value, "\"") > -1 {
value = value[strings.Index(value, "\"")+1:]
lib_name := value[:strings.Index(value, "\"")]
if _ , ok := result[fuzzer_name]; ok {
result[fuzzer_name] += "," + lib_name
} else {
result[fuzzer_name] += lib_name
}
value = value[strings.Index(value, "\"")+1:]
}
}
}
}
}
if len(errs) > 0 {
for _, err := range errs {
fmt.Fprintln(os.Stderr, err)
}
return fmt.Errorf("%d parsing errors", len(errs))
}
return err
}
func findModules(file *parser.File) (modules []*parser.Module) {
if file != nil {
for _, def := range file.Defs {
if module, ok := def.(*parser.Module); ok {
modules = append(modules, module)
}
}
}
return modules
}
func walkDir(path string) {
visitFile := func(path string, f os.FileInfo, err error) error {
if err == nil && f.Name() == "Android.bp" {
err = processFile(path, os.Stdout)
}
if err != nil {
fmt.Printf("ERROR")
report(err)
}
return nil
}
fmt.Printf("Parsing %s recursively...\n", path)
filepath.Walk(path, visitFile)
}
func main() {
flag.Usage = usage
flag.Parse()
for i := 0; i < flag.NArg(); i++ {
Root := flag.Arg(i)
fmt.Printf("Root %s\n", Root)
switch dir, err := os.Stat(Root); {
case err != nil:
report(err)
case dir.IsDir():
walkDir(Root)
default:
if err := processFile(Root, os.Stdout); err != nil {
report(err)
}
}
}
fmt.Printf("-------------------------------------\n")
fmt.Printf("Fuzzer name -------Library name------\n")
if len(result) > 0 {
for k, v := range result {
if len(v) == 0 {
v = "NOT FOUND"
}
fmt.Printf("%s:%s\n", k, v)
}
}
os.Exit(exitCode)
}