aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-08-18 16:38:41 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-08-18 17:04:12 +0200
commit19b893936bebc6189c7627d56d1dc454fbd42714 (patch)
tree2c58dca1528c2e7d05cbe6ca49fd34a3f802a681 /pkg/compiler
parent41bbf437e1e843fd3ab5603ec4c2eb4a42dca76f (diff)
sys/syz-extract: switch to the new parser
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/compiler.go65
-rw-r--r--pkg/compiler/compiler_test.go59
2 files changed, 124 insertions, 0 deletions
diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go
new file mode 100644
index 000000000..7892661fa
--- /dev/null
+++ b/pkg/compiler/compiler.go
@@ -0,0 +1,65 @@
+// Copyright 2017 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 compiler
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "github.com/google/syzkaller/pkg/ast"
+)
+
+// ExtractConsts returns list of literal constants and other info required const value extraction.
+func ExtractConsts(top []interface{}) (consts, includes, incdirs []string, defines map[string]string) {
+ constMap := make(map[string]bool)
+ defines = make(map[string]string)
+
+ ast.Walk(top, func(n1 interface{}) {
+ switch n := n1.(type) {
+ case *ast.Include:
+ includes = append(includes, n.File.Value)
+ case *ast.Incdir:
+ incdirs = append(incdirs, n.Dir.Value)
+ case *ast.Define:
+ v := fmt.Sprint(n.Value.Value)
+ switch {
+ case n.Value.CExpr != "":
+ v = n.Value.CExpr
+ case n.Value.Ident != "":
+ v = n.Value.Ident
+ }
+ defines[n.Name.Name] = v
+ constMap[n.Name.Name] = true
+ case *ast.Call:
+ if !strings.HasPrefix(n.CallName, "syz_") {
+ constMap["__NR_"+n.CallName] = true
+ }
+ case *ast.Type:
+ if n.Ident == "const" && len(n.Args) > 0 {
+ constMap[n.Args[0].Ident] = true
+ }
+ if n.Ident == "array" && len(n.Args) > 1 {
+ constMap[n.Args[1].Ident] = true
+ }
+ case *ast.Int:
+ constMap[n.Ident] = true
+ }
+ })
+
+ consts = toArray(constMap)
+ return
+}
+
+func toArray(m map[string]bool) []string {
+ delete(m, "")
+ var res []string
+ for v := range m {
+ if v != "" {
+ res = append(res, v)
+ }
+ }
+ sort.Strings(res)
+ return res
+}
diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go
new file mode 100644
index 000000000..13ed97b4c
--- /dev/null
+++ b/pkg/compiler/compiler_test.go
@@ -0,0 +1,59 @@
+// Copyright 2017 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 compiler
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/google/syzkaller/pkg/ast"
+)
+
+func TestExtractConsts(t *testing.T) {
+ top, ok := ast.Parse([]byte(extractConstsInput), "test", nil)
+ if !ok {
+ t.Fatalf("failed to parse input")
+ }
+ consts, includes, incdirs, defines := ExtractConsts(top)
+ wantConsts := []string{"CONST1", "CONST2", "CONST3", "CONST4", "CONST5",
+ "CONST6", "CONST7", "__NR_bar", "__NR_foo"}
+ if !reflect.DeepEqual(consts, wantConsts) {
+ t.Fatalf("got consts:\n%q\nwant:\n%q", consts, wantConsts)
+ }
+ wantIncludes := []string{"foo/bar.h", "bar/foo.h"}
+ if !reflect.DeepEqual(includes, wantIncludes) {
+ t.Fatalf("got includes:\n%q\nwant:\n%q", includes, wantIncludes)
+ }
+ wantIncdirs := []string{"/foo", "/bar"}
+ if !reflect.DeepEqual(incdirs, wantIncdirs) {
+ t.Fatalf("got incdirs:\n%q\nwant:\n%q", incdirs, wantIncdirs)
+ }
+ wantDefines := map[string]string{
+ "CONST1": "1",
+ "CONST2": "FOOBAR + 1",
+ }
+ if !reflect.DeepEqual(defines, wantDefines) {
+ t.Fatalf("got defines:\n%q\nwant:\n%q", defines, wantDefines)
+ }
+}
+
+const extractConstsInput = `
+include <foo/bar.h>
+incdir </foo>
+include <bar/foo.h>
+incdir </bar>
+
+flags = CONST3, CONST2, CONST1
+
+define CONST1 1
+define CONST2 FOOBAR + 1
+
+foo(x const[CONST4]) ptr[out, array[int32, CONST5]]
+bar$BAR()
+
+str {
+ f1 const[CONST6, int32]
+ f2 array[array[int8, CONST7]]
+}
+`