1package main 2 3import ( 4 "bytes" 5 "flag" 6 "fmt" 7 "io" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "github.com/google/blueprint/parser" 14) 15 16var ( 17 result = make(map[string]string) 18 defaults = make(map[string]string) 19 Root = "" 20) 21 22var ( 23 exitCode = 0 24) 25 26func report(err error) { 27 fmt.Fprintln(os.Stderr, err) 28 exitCode = 2 29} 30 31func usage() { 32 usageViolation("") 33} 34 35func usageViolation(violation string) { 36 fmt.Fprintln(os.Stderr, violation) 37 fmt.Fprintln(os.Stderr, "usage: fuzzparser [flags] [path ...]") 38 flag.PrintDefaults() 39 os.Exit(2) 40} 41 42func processFile(filename string, out io.Writer) error { 43 f, err := os.Open(filename) 44 if err != nil { 45 return err 46 } 47 defer f.Close() 48 49 return processReader(filename, f, out) 50} 51 52func processReader(filename string, in io.Reader, out io.Writer) error { 53 src, err := ioutil.ReadAll(in) 54 if err != nil { 55 return err 56 } 57 58 r := bytes.NewBuffer(src) 59 file, errs := parser.ParseAndEval(filename, r, parser.NewScope(nil)) 60 61 modules := findModules(file) 62 // First collect all the defaults into a dictionary 63 for _, mod := range modules { 64 if mod.Type == "cc_defaults" { 65 default_name := "" 66 for _, prop := range mod.Map.Properties { 67 if prop.Name == "name" { 68 value := prop.Value.String() 69 default_name = value[1:strings.Index(value, "@")-1] 70 } else if prop.Name == "static_libs" || prop.Name == "shared_libs" { 71 value := prop.Value.String() 72 for strings.Index(value, "\"") > -1 { 73 value = value[strings.Index(value, "\"")+1:] 74 lib_name := value[:strings.Index(value, "\"")] 75 if _ , ok := defaults[default_name]; ok { 76 defaults[default_name] += "," + lib_name 77 } else { 78 defaults[default_name] += lib_name 79 } 80 value = value[strings.Index(value, "\"")+1:] 81 } 82 } else if prop.Name == "defaults" { 83 // Get the defaults of the default 84 value := prop.Value.String() 85 for strings.Index(value, "\"") > -1 { 86 value = value[strings.Index(value, "\"")+1:] 87 sub_default_name := value[:strings.Index(value, "\"")] 88 if _ , ok := defaults[default_name]; ok { 89 defaults[default_name] += "," + defaults[sub_default_name] 90 } else { 91 defaults[default_name] += defaults[sub_default_name] 92 } 93 value = value[strings.Index(value, "\"")+1:] 94 } 95 } else if prop.Name == "target" { 96 value := prop.Value.String() 97 if default_name == "binder_fuzz_defaults" { 98 fmt.Printf("---> target value for %s: %s\n", default_name ,value) 99 } 100 for strings.Index(value, "\"") > -1 { 101 value = value[strings.Index(value, "\"")+1:] 102 lib := value[:strings.Index(value, "\"")] 103 if _ , ok := defaults[default_name]; ok { 104 defaults[default_name] += "," + lib 105 } else { 106 defaults[default_name] += lib 107 } 108 value = value[strings.Index(value, "\"")+1:] 109 } 110 } 111 } 112 } 113 } 114 115 for _, mod := range modules { 116 if mod.Type == "cc_fuzz" { 117 fuzzer_name := "" 118 for _, prop := range mod.Map.Properties { 119 // First get the name of the fuzzer 120 if prop.Name == "name" { 121 value := prop.Value.String() 122 fuzzer_name = value[1:strings.Index(value, "@")-1] 123 } else if prop.Name == "defaults" { 124 value := prop.Value.String() 125 if strings.Index(value, "@") == 0 { 126 value = value[1:] 127 } 128 default_name := value[strings.Index(value, "[")+2: strings.Index(value, "@")-1] 129 if _, ok := result[fuzzer_name]; ok { 130 result[fuzzer_name] += "," + defaults[default_name] 131 } else { 132 result[fuzzer_name] += defaults[default_name] 133 } 134 } else if prop.Name == "static_libs" || prop.Name == "shared_libs" { 135 value := prop.Value.String() 136 for strings.Index(value, "\"") > -1 { 137 value = value[strings.Index(value, "\"")+1:] 138 lib_name := value[:strings.Index(value, "\"")] 139 if _ , ok := result[fuzzer_name]; ok { 140 result[fuzzer_name] += "," + lib_name 141 } else { 142 result[fuzzer_name] += lib_name 143 } 144 value = value[strings.Index(value, "\"")+1:] 145 } 146 } 147 } 148 } 149 } 150 151 if len(errs) > 0 { 152 for _, err := range errs { 153 fmt.Fprintln(os.Stderr, err) 154 } 155 return fmt.Errorf("%d parsing errors", len(errs)) 156 } 157 158 return err 159} 160 161func findModules(file *parser.File) (modules []*parser.Module) { 162 if file != nil { 163 for _, def := range file.Defs { 164 if module, ok := def.(*parser.Module); ok { 165 modules = append(modules, module) 166 } 167 } 168 } 169 return modules 170} 171 172func walkDir(path string) { 173 visitFile := func(path string, f os.FileInfo, err error) error { 174 if err == nil && f.Name() == "Android.bp" { 175 err = processFile(path, os.Stdout) 176 } 177 if err != nil { 178 fmt.Printf("ERROR") 179 report(err) 180 } 181 return nil 182 } 183 fmt.Printf("Parsing %s recursively...\n", path) 184 filepath.Walk(path, visitFile) 185} 186 187func main() { 188 flag.Usage = usage 189 flag.Parse() 190 191 for i := 0; i < flag.NArg(); i++ { 192 Root := flag.Arg(i) 193 fmt.Printf("Root %s\n", Root) 194 switch dir, err := os.Stat(Root); { 195 case err != nil: 196 report(err) 197 case dir.IsDir(): 198 walkDir(Root) 199 default: 200 if err := processFile(Root, os.Stdout); err != nil { 201 report(err) 202 } 203 } 204 } 205 206 fmt.Printf("-------------------------------------\n") 207 fmt.Printf("Fuzzer name -------Library name------\n") 208 if len(result) > 0 { 209 for k, v := range result { 210 if len(v) == 0 { 211 v = "NOT FOUND" 212 } 213 fmt.Printf("%s:%s\n", k, v) 214 } 215 } 216 217 os.Exit(exitCode) 218} 219