diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-09-15 14:15:52 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-09-15 16:02:37 +0200 |
| commit | 66393d1884cb6a6d36dcbe5ad772ae9cf8f2adad (patch) | |
| tree | a8747f057372ed2e2a451a0c0988b99f70a012dc /pkg | |
| parent | 4f60e46e498eedc0d9407d11d1078208c37d19f1 (diff) | |
pkg/compiler: don't genererate missing syscalls
We used to generate them only because manager had no idea
what arch it is testing. So syscalls numbers had to match
between all arches.
This is not needed anymore.
Also don't generate unreferenced structs/resources.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/compiler/check.go | 52 | ||||
| -rw-r--r-- | pkg/compiler/compiler.go | 2 | ||||
| -rw-r--r-- | pkg/compiler/consts.go | 21 | ||||
| -rw-r--r-- | pkg/compiler/gen.go | 19 | ||||
| -rw-r--r-- | pkg/compiler/testdata/errors2.txt | 3 | ||||
| -rw-r--r-- | pkg/host/host.go | 3 |
6 files changed, 70 insertions, 30 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index 99ac1d447..5fefeaf68 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -22,6 +22,7 @@ func (comp *compiler) check() { if comp.errors != 0 { return } + comp.checkUsed() comp.checkRecursion() comp.checkLenTargets() comp.checkConstructors() @@ -230,6 +231,52 @@ func (comp *compiler) checkLenTarget(t *ast.Type, name, target string, fields [] comp.error(t.Pos, "%v target %v does not exist", t.Ident, target) } +func (comp *compiler) checkUsed() { + for _, decl := range comp.desc.Nodes { + switch n := decl.(type) { + case *ast.Call: + if n.NR == ^uint64(0) { + break + } + for _, arg := range n.Args { + comp.checkUsedType(arg.Type, true) + } + if n.Ret != nil { + comp.checkUsedType(n.Ret, true) + } + } + } +} + +func (comp *compiler) checkUsedType(t *ast.Type, isArg bool) { + if comp.used[t.Ident] { + return + } + desc := comp.getTypeDesc(t) + if desc == typeResource { + r := comp.resources[t.Ident] + for r != nil && !comp.used[r.Name.Name] { + comp.used[r.Name.Name] = true + r = comp.resources[r.Base.Ident] + } + return + } + if desc == typeStruct { + comp.used[t.Ident] = true + s := comp.structs[t.Ident] + for _, fld := range s.Fields { + comp.checkUsedType(fld.Type, false) + } + return + } + _, args, _ := comp.getArgsBase(t, "", prog.DirIn, isArg) + for i, arg := range args { + if desc.Args[i].Type == typeArgType { + comp.checkUsedType(arg, false) + } + } +} + type structDir struct { Struct string Dir prog.Dir @@ -252,10 +299,11 @@ func (comp *compiler) checkConstructors() { for _, decl := range comp.desc.Nodes { switch n := decl.(type) { case *ast.Resource: - if !ctors[n.Name.Name] { + name := n.Name.Name + if !ctors[name] && comp.used[name] { comp.error(n.Pos, "resource %v can't be created"+ " (never mentioned as a syscall return value or output argument/field)", - n.Name.Name) + name) } } } diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index f6641f9c9..d54ac4678 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -54,6 +54,7 @@ func Compile(desc *ast.Description, consts map[string]uint64, ptrSize uint64, eh structs: make(map[string]*ast.Struct), intFlags: make(map[string]*ast.IntFlags), strFlags: make(map[string]*ast.StrFlags), + used: make(map[string]bool), structDescs: make(map[prog.StructKey]*prog.StructDesc), structNodes: make(map[*prog.StructDesc]*ast.Struct), structVarlen: make(map[string]bool), @@ -88,6 +89,7 @@ type compiler struct { structs map[string]*ast.Struct intFlags map[string]*ast.IntFlags strFlags map[string]*ast.StrFlags + used map[string]bool // contains used structs/resources structDescs map[prog.StructKey]*prog.StructDesc structNodes map[*prog.StructDesc]*ast.Struct diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go index 44c0c4f18..f64f4ed7f 100644 --- a/pkg/compiler/consts.go +++ b/pkg/compiler/consts.go @@ -128,26 +128,18 @@ func (comp *compiler) assignSyscallNumbers(consts map[string]uint64) { // Lookup in consts. str := "__NR_" + c.CallName nr, ok := consts[str] + top = append(top, decl) if ok { c.NR = nr - top = append(top, decl) continue } + c.NR = ^uint64(0) // mark as unused to not generate it name := "syscall " + c.CallName if !comp.unsupported[name] { comp.unsupported[name] = true comp.warning(c.Pos, "unsupported syscall: %v due to missing const %v", c.CallName, str) } - // TODO: we still have to preserve the syscall. - // The problem is that manager and fuzzer use syscall indexes - // to communicate enabled syscalls. If manager is built for - // amd64 and fuzzer for arm64, then they would have different - // sets of syscalls and would not agree on syscall indexes. - // Remove this once we have proper cross-OS/arch support. - // The same happens in patchConsts. - c.NR = ^uint64(0) - top = append(top, decl) case *ast.IntFlags, *ast.Resource, *ast.Struct, *ast.StrFlags: top = append(top, decl) case *ast.NewLine, *ast.Comment, *ast.Include, *ast.Incdir, *ast.Define: @@ -214,12 +206,9 @@ func (comp *compiler) patchConsts(consts map[string]uint64) { } // We have to keep partially broken resources and structs, // because otherwise their usages will error. - if c, ok := decl.(*ast.Call); !ok { - top = append(top, decl) - } else { - // See comment in assignSyscallNumbers. - c.NR = ^uint64(0) - top = append(top, decl) + top = append(top, decl) + if c, ok := decl.(*ast.Call); ok { + c.NR = ^uint64(0) // mark as unused to not generate it } } } diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go index eeeed011c..b91080db2 100644 --- a/pkg/compiler/gen.go +++ b/pkg/compiler/gen.go @@ -15,10 +15,11 @@ const sizeUnassigned = ^uint64(0) func (comp *compiler) genResources() []*prog.ResourceDesc { var resources []*prog.ResourceDesc - for _, decl := range comp.desc.Nodes { - if n, ok := decl.(*ast.Resource); ok { - resources = append(resources, comp.genResource(n)) + for name, n := range comp.resources { + if !comp.used[name] { + continue } + resources = append(resources, comp.genResource(n)) } sort.Slice(resources, func(i, j int) bool { return resources[i].Name < resources[j].Name @@ -47,7 +48,7 @@ func (comp *compiler) genResource(n *ast.Resource) *prog.ResourceDesc { func (comp *compiler) genSyscalls() []*prog.Syscall { var calls []*prog.Syscall for _, decl := range comp.desc.Nodes { - if n, ok := decl.(*ast.Call); ok { + if n, ok := decl.(*ast.Call); ok && n.NR != ^uint64(0) { calls = append(calls, comp.genSyscall(n)) } } @@ -101,10 +102,12 @@ func (comp *compiler) genStructDescs(syscalls []*prog.Syscall) []*prog.KeyedStru return false } } - structs = append(structs, &prog.KeyedStruct{ - Key: key, - Desc: desc, - }) + if comp.used[key.Name] { + structs = append(structs, &prog.KeyedStruct{ + Key: key, + Desc: desc, + }) + } return true } rec = func(t0 prog.Type) { diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt index 30dd728a2..0292aca5e 100644 --- a/pkg/compiler/testdata/errors2.txt +++ b/pkg/compiler/testdata/errors2.txt @@ -75,7 +75,8 @@ resource r105[int8] resource r106[int8] ### resource r106 can't be created (never mentioned as a syscall return value or output argument/field) resource r107[int8] ### resource r107 can't be created (never mentioned as a syscall return value or output argument/field) -foo$300(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104 +foo$300(a r100) +foo$301(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104 s300 { f1 ptr[inout, s301] diff --git a/pkg/host/host.go b/pkg/host/host.go index 993db175b..ef301e2dc 100644 --- a/pkg/host/host.go +++ b/pkg/host/host.go @@ -38,9 +38,6 @@ func DetectSupportedSyscalls(target *prog.Target) (map[*prog.Syscall]bool, error } func isSupported(kallsyms []byte, c *prog.Syscall) bool { - if c.NR == ^uint64(0) { - return false // don't even have a syscall number - } if strings.HasPrefix(c.CallName, "syz_") { return isSupportedSyzkall(c) } |
