aboutsummaryrefslogtreecommitdiffstats
path: root/prog/resources.go
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 /prog/resources.go
parent9adfa8760f6ba6ed23dc7fe9eb900f8b684e0052 (diff)
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.
Diffstat (limited to 'prog/resources.go')
-rw-r--r--prog/resources.go62
1 files changed, 44 insertions, 18 deletions
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