aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2019-08-21 20:05:22 +0200
committerDmitry Vyukov <dvyukov@google.com>2019-08-30 12:51:28 -0700
commitbcd7bcc2968d1db4d4eb16c50afa76bdcffb6302 (patch)
tree4cea13908fbf66515279c53e21bdcb672d10e01e
parent9adfa8760f6ba6ed23dc7fe9eb900f8b684e0052 (diff)
downloadsyzkaller-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.go2
-rw-r--r--prog/resources.go62
-rw-r--r--prog/target.go3
-rw-r--r--prog/types.go6
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 {