diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-08-18 16:38:41 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-08-18 17:04:12 +0200 |
| commit | 19b893936bebc6189c7627d56d1dc454fbd42714 (patch) | |
| tree | 2c58dca1528c2e7d05cbe6ca49fd34a3f802a681 /pkg/compiler | |
| parent | 41bbf437e1e843fd3ab5603ec4c2eb4a42dca76f (diff) | |
sys/syz-extract: switch to the new parser
Diffstat (limited to 'pkg/compiler')
| -rw-r--r-- | pkg/compiler/compiler.go | 65 | ||||
| -rw-r--r-- | pkg/compiler/compiler_test.go | 59 |
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]] +} +` |
