diff options
author | Andrey Konovalov <andreyknvl@google.com> | 2019-08-21 20:05:22 +0200 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2019-08-30 12:51:28 -0700 |
commit | bcd7bcc2968d1db4d4eb16c50afa76bdcffb6302 (patch) | |
tree | 4cea13908fbf66515279c53e21bdcb672d10e01e | |
parent | 9adfa8760f6ba6ed23dc7fe9eb900f8b684e0052 (diff) | |
download | syzkaller-bcd7bcc2968d1db4d4eb16c50afa76bdcffb6302.tar.gz |
prog: speed up resource ctors detection
When we build a list of resource constructors we over and over iterate through
all types in a syscall to find resource types. Speed it up by iterating only
once to build a list of constructors for each resource and then reuse it.
This significantly speeds up syz-exeprog startup time on Raspberry Pi Zero.
-rw-r--r-- | prog/decl_test.go | 2 | ||||
-rw-r--r-- | prog/resources.go | 62 | ||||
-rw-r--r-- | prog/target.go | 3 | ||||
-rw-r--r-- | prog/types.go | 6 |
4 files changed, 53 insertions, 20 deletions
diff --git a/prog/decl_test.go b/prog/decl_test.go index bf6bec4d1..f999ae589 100644 --- a/prog/decl_test.go +++ b/prog/decl_test.go @@ -15,7 +15,7 @@ func TestResourceCtors(t *testing.T) { testEachTarget(t, func(t *testing.T, target *Target) { expectFail := false for _, res := range target.Resources { - if len(target.calcResourceCtors(res.Kind, true)) == 0 != expectFail { + if len(target.calcResourceCtors(res, true)) == 0 != expectFail { t.Errorf("resource %v can't be created", res.Name) } } diff --git a/prog/resources.go b/prog/resources.go index d935beb7a..08002ec27 100644 --- a/prog/resources.go +++ b/prog/resources.go @@ -14,33 +14,59 @@ var timespecRes = &ResourceDesc{ Kind: []string{"timespec"}, } -func (target *Target) calcResourceCtors(kind []string, precise bool) []*Syscall { - // Find calls that produce the necessary resources. +func (target *Target) calcResourceCtors(res *ResourceDesc, precise bool) []*Syscall { var metas []*Syscall - for _, meta := range target.Syscalls { - // Recurse into arguments to see if there is an out/inout arg of necessary type. - ok := false + for _, ctor := range res.Ctors { + if !precise || ctor.Precise { + metas = append(metas, target.Syscalls[ctor.Call]) + } + } + if res.Kind[0] == timespecRes.Name { + if c := target.SyscallMap["clock_gettime"]; c != nil { + metas = append(metas, c) + } + } + return metas +} + +func (target *Target) populateResourceCtors() { + // Find resources that are created by each call. + callsResources := make([][]*ResourceDesc, len(target.Syscalls)) + for call, meta := range target.Syscalls { ForeachType(meta, func(typ Type) { - if ok { - return - } switch typ1 := typ.(type) { case *ResourceType: - if typ1.Dir() != DirIn && isCompatibleResourceImpl(kind, typ1.Desc.Kind, precise) { - ok = true + if typ1.Dir() != DirIn { + callsResources[call] = append(callsResources[call], typ1.Desc) } } }) - if ok { - metas = append(metas, meta) - } } - if kind[0] == timespecRes.Name { - if c := target.SyscallMap["clock_gettime"]; c != nil { - metas = append(metas, c) + + // Populate resource ctors accounting for resource compatibility. + for _, res := range target.Resources { + for call, callResources := range callsResources { + preciseOk := false + impreciseOk := false + for _, callRes := range callResources { + if preciseOk && impreciseOk { + break + } + if isCompatibleResourceImpl(res.Kind, callRes.Kind, true) { + preciseOk = true + } + if isCompatibleResourceImpl(res.Kind, callRes.Kind, false) { + impreciseOk = true + } + } + if preciseOk { + res.Ctors = append(res.Ctors, ResourceCtor{call, true}) + } + if impreciseOk { + res.Ctors = append(res.Ctors, ResourceCtor{call, false}) + } } } - return metas } // isCompatibleResource returns true if resource of kind src can be passed as an argument of kind dst. @@ -172,7 +198,7 @@ func (target *Target) TransitivelyEnabledCalls(enabled map[*Syscall]bool) (map[* } if ctors[res.Name] == nil { var names []string - for _, call := range target.calcResourceCtors(res.Kind, true) { + for _, call := range target.calcResourceCtors(res, true) { names = append(names, call.Name) } ctors[res.Name] = names diff --git a/prog/target.go b/prog/target.go index da9b3255c..d02a3dd37 100644 --- a/prog/target.go +++ b/prog/target.go @@ -168,9 +168,10 @@ func (target *Target) initTarget() { }) } + target.populateResourceCtors() target.resourceCtors = make(map[string][]*Syscall) for _, res := range target.Resources { - target.resourceCtors[res.Name] = target.calcResourceCtors(res.Kind, false) + target.resourceCtors[res.Name] = target.calcResourceCtors(res, false) } initAnyTypes(target) } diff --git a/prog/types.go b/prog/types.go index 7f9569483..c36dc076c 100644 --- a/prog/types.go +++ b/prog/types.go @@ -132,6 +132,12 @@ type ResourceDesc struct { Type Type Kind []string Values []uint64 + Ctors []ResourceCtor +} + +type ResourceCtor struct { + Call int // Index in Target.Syscalls + Precise bool } type ResourceType struct { |