diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-08-18 18:38:07 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-08-18 18:47:39 +0200 |
| commit | 4802b0fb7440d76d78efc586b87ff6eea46b6b00 (patch) | |
| tree | 7a1e39eb906a18e0be375f39ec45b0679cee39c4 /sys/sysparser | |
| parent | 19b893936bebc6189c7627d56d1dc454fbd42714 (diff) | |
sys/syz-sysgen: switch to new parser
For now we just generate the old structs from the new AST.
But this allows to delete the old parser entirely.
Diffstat (limited to 'sys/sysparser')
| -rw-r--r-- | sys/sysparser/lexer.go | 329 | ||||
| -rw-r--r-- | sys/sysparser/parser.go | 100 |
2 files changed, 0 insertions, 429 deletions
diff --git a/sys/sysparser/lexer.go b/sys/sysparser/lexer.go deleted file mode 100644 index c6a0f802e..000000000 --- a/sys/sysparser/lexer.go +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2015/2016 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 sysparser - -import ( - "fmt" - "io" - "os" - "sort" - "strconv" - "strings" -) - -type Description struct { - Includes []string - Incdirs []string - Defines map[string]string - Syscalls []Syscall - Structs map[string]*Struct - Unnamed map[string][]string - Flags map[string][]string - StrFlags map[string][]string - Resources map[string]Resource -} - -type Syscall struct { - Name string - CallName string - Args [][]string - Ret []string -} - -type Struct struct { - Name string - Flds [][]string - IsUnion bool - Packed bool - Varlen bool - Align int -} - -type Resource struct { - Name string - Base string - Values []string -} - -func Parse(in io.Reader) *Description { - p := newParser(in) - var includes []string - var incdirs []string - defines := make(map[string]string) - var syscalls []Syscall - structs := make(map[string]*Struct) - unnamed := make(map[string][]string) - flags := make(map[string][]string) - strflags := make(map[string][]string) - resources := make(map[string]Resource) - var str *Struct - for p.Scan() { - if p.EOF() || p.Char() == '#' { - continue - } - if str != nil { - // Parsing a struct. - if p.Char() == '}' || p.Char() == ']' { - p.Parse(p.Char()) - for _, attr := range parseType1(p, unnamed, flags, "")[1:] { - if str.IsUnion { - switch attr { - case "varlen": - str.Varlen = true - default: - failf("unknown union %v attribute: %v", str.Name, attr) - } - } else { - switch { - case attr == "packed": - str.Packed = true - case strings.HasPrefix(attr, "align_ptr"): - str.Align = 8 // TODO: this must be target pointer size - case strings.HasPrefix(attr, "align_"): - a, err := strconv.ParseUint(attr[6:], 10, 64) - if err != nil { - failf("bad struct %v alignment %v: %v", str.Name, attr, err) - } - if a&(a-1) != 0 || a == 0 || a > 1<<30 { - failf("bad struct %v alignment %v: must be sane power of 2", str.Name, a) - } - str.Align = int(a) - default: - failf("unknown struct %v attribute: %v", str.Name, attr) - } - } - } - if str.IsUnion { - if len(str.Flds) <= 1 { - failf("union %v has only %v fields, need at least 2", str.Name, len(str.Flds)) - } - } - fields := make(map[string]bool) - for _, f := range str.Flds { - if f[0] == "parent" { - failf("struct/union %v contains reserved field 'parent'", str.Name) - } - if fields[f[0]] { - failf("duplicate field %v in struct/union %v", f[0], str.Name) - } - fields[f[0]] = true - } - structs[str.Name] = str - str = nil - } else { - p.SkipWs() - fld := []string{p.Ident()} - fld = append(fld, parseType(p, unnamed, flags)...) - str.Flds = append(str.Flds, fld) - } - } else { - name := p.Ident() - if name == "include" { - p.Parse('<') - var include []byte - for { - ch := p.Char() - if ch == '>' { - break - } - p.Parse(ch) - include = append(include, ch) - } - p.Parse('>') - includes = append(includes, string(include)) - } else if name == "define" { - key := p.Ident() - var val []byte - for !p.EOF() { - ch := p.Char() - p.Parse(ch) - val = append(val, ch) - } - if defines[key] != "" { - failf("%v define is defined multiple times", key) - } - defines[key] = fmt.Sprintf("(%s)", val) - } else if name == "resource" { - p.SkipWs() - id := p.Ident() - p.Parse('[') - base := p.Ident() - p.Parse(']') - var vals []string - if !p.EOF() && p.Char() == ':' { - p.Parse(':') - vals = append(vals, p.Ident()) - for !p.EOF() { - p.Parse(',') - vals = append(vals, p.Ident()) - } - } - if _, ok := resources[id]; ok { - failf("resource '%v' is defined multiple times", id) - } - if _, ok := structs[id]; ok { - failf("struct '%v' is redefined as resource", name) - } - resources[id] = Resource{id, base, vals} - } else if name == "incdir" { - p.Parse('"') - var incdir []byte - for { - ch := p.Char() - if ch == '"' { - break - } - p.Parse(ch) - incdir = append(incdir, ch) - } - p.Parse('"') - incdirs = append(incdirs, string(incdir)) - } else { - switch ch := p.Char(); ch { - case '(': - // syscall - p.Parse('(') - var args [][]string - for p.Char() != ')' { - arg := []string{p.Ident()} - arg = append(arg, parseType(p, unnamed, flags)...) - args = append(args, arg) - if p.Char() != ')' { - p.Parse(',') - } - } - p.Parse(')') - var ret []string - if !p.EOF() { - ret = parseType(p, unnamed, flags) - } - callName := name - if idx := strings.IndexByte(callName, '$'); idx != -1 { - callName = callName[:idx] - } - fields := make(map[string]bool) - for _, a := range args { - if fields[a[0]] { - failf("duplicate arg %v in syscall %v", a[0], name) - } - fields[a[0]] = true - } - syscalls = append(syscalls, Syscall{name, callName, args, ret}) - case '=': - // flag - p.Parse('=') - str := p.Char() == '"' - var vals []string - for { - v := p.Ident() - if str { - v = v[1 : len(v)-1] - } - vals = append(vals, v) - if p.EOF() { - break - } - p.Parse(',') - } - if str { - strflags[name] = vals - } else { - flags[name] = vals - } - case '{', '[': - p.Parse(ch) - if _, ok := structs[name]; ok { - failf("struct '%v' is defined multiple times", name) - } - if _, ok := resources[name]; ok { - failf("resource '%v' is redefined as struct", name) - } - str = &Struct{Name: name, IsUnion: ch == '['} - default: - failf("bad line (%v)", p.Str()) - } - } - } - if !p.EOF() { - failf("trailing data (%v)", p.Str()) - } - } - sort.Sort(syscallArray(syscalls)) - return &Description{ - Includes: includes, - Incdirs: incdirs, - Defines: defines, - Syscalls: syscalls, - Structs: structs, - Unnamed: unnamed, - Flags: flags, - StrFlags: strflags, - Resources: resources, - } -} - -func isIdentifier(s string) bool { - for i, c := range s { - if c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || i > 0 && (c >= '0' && c <= '9') { - continue - } - return false - } - return true -} - -func parseType(p *parser, unnamed map[string][]string, flags map[string][]string) []string { - return parseType1(p, unnamed, flags, p.Ident()) -} - -var ( - unnamedSeq int - constSeq int -) - -func parseType1(p *parser, unnamed map[string][]string, flags map[string][]string, name string) []string { - typ := []string{name} - if !p.EOF() && p.Char() == '[' { - p.Parse('[') - for { - id := p.Ident() - if p.Char() == '[' { - inner := parseType1(p, unnamed, flags, id) - id = fmt.Sprintf("unnamed%v", unnamedSeq) - unnamedSeq++ - unnamed[id] = inner - } - typ = append(typ, id) - if p.Char() == ']' { - break - } - p.Parse(',') - } - p.Parse(']') - } - if name == "const" && len(typ) > 1 { - // Create a fake flag with the const value. - id := fmt.Sprintf("const_flag_%v", constSeq) - constSeq++ - flags[id] = typ[1:2] - } - if name == "array" && len(typ) > 2 { - // Create a fake flag with the const value. - id := fmt.Sprintf("const_flag_%v", constSeq) - constSeq++ - flags[id] = typ[2:3] - } - return typ -} - -type syscallArray []Syscall - -func (a syscallArray) Len() int { return len(a) } -func (a syscallArray) Less(i, j int) bool { return a[i].Name < a[j].Name } -func (a syscallArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func failf(msg string, args ...interface{}) { - fmt.Fprintf(os.Stderr, msg+"\n", args...) - os.Exit(1) -} diff --git a/sys/sysparser/parser.go b/sys/sysparser/parser.go deleted file mode 100644 index d5021eee6..000000000 --- a/sys/sysparser/parser.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2015/2016 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 sysparser - -import ( - "bufio" - "fmt" - "io" - "os" -) - -type parser struct { - r *bufio.Scanner - s string - i int - l int -} - -func newParser(r io.Reader) *parser { - return &parser{r: bufio.NewScanner(r)} -} - -func (p *parser) Scan() bool { - if !p.r.Scan() { - if err := p.r.Err(); err != nil { - failf("failed to read input file: %v", err) - } - return false - } - p.s = p.r.Text() - p.i = 0 - p.l++ - return true -} - -func (p *parser) Str() string { - return p.s -} - -func (p *parser) EOF() bool { - return p.i == len(p.s) -} - -func (p *parser) Char() byte { - if p.EOF() { - p.failf("unexpected eof") - } - return p.s[p.i] -} - -func (p *parser) Parse(ch byte) { - if p.EOF() { - p.failf("want %s, got EOF", string(ch)) - } - if p.s[p.i] != ch { - p.failf("want '%v', got '%v'", string(ch), string(p.s[p.i])) - } - p.i++ - p.SkipWs() -} - -func (p *parser) SkipWs() { - for p.i < len(p.s) && (p.s[p.i] == ' ' || p.s[p.i] == '\t') { - p.i++ - } -} - -func (p *parser) Ident() string { - start, end := p.i, 0 - if p.Char() == '"' { - p.Parse('"') - for p.Char() != '"' { - p.i++ - } - end = p.i + 1 - p.Parse('"') - } else { - for p.i < len(p.s) && - (p.s[p.i] >= 'a' && p.s[p.i] <= 'z' || - p.s[p.i] >= 'A' && p.s[p.i] <= 'Z' || - p.s[p.i] >= '0' && p.s[p.i] <= '9' || - p.s[p.i] == '_' || p.s[p.i] == '$' || // $ is for n-way syscalls (like ptrace$peek) - p.s[p.i] == '-' || p.s[p.i] == ':') { // : is for ranged int (like int32[-3:10]) - p.i++ - } - if start == p.i { - p.failf("failed to parse identifier at pos %v", start) - } - end = p.i - } - s := p.s[start:end] - p.SkipWs() - return s -} - -func (p *parser) failf(msg string, args ...interface{}) { - fmt.Fprintf(os.Stderr, "line #%v: %v\n", p.l, p.s) - failf(msg, args...) -} |
