aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--prog/decl_test.go35
-rw-r--r--prog/resources.go128
2 files changed, 102 insertions, 61 deletions
diff --git a/prog/decl_test.go b/prog/decl_test.go
index 0f727aa7f..ac353e66a 100644
--- a/prog/decl_test.go
+++ b/prog/decl_test.go
@@ -14,11 +14,11 @@ func TestResourceCtors(t *testing.T) {
}
testEachTarget(t, func(t *testing.T, target *Target) {
for _, c := range target.Syscalls {
- for _, res := range c.inputResources() {
- if len(target.calcResourceCtors(res.Desc.Kind, true)) == 0 {
+ for _, res := range target.inputResources(c) {
+ if len(target.calcResourceCtors(res.Kind, true)) == 0 {
t.Errorf("call %v requires input resource %v,"+
" but there are no calls that can create this resource",
- c.Name, res.Desc.Name)
+ c.Name, res.Name)
}
}
}
@@ -31,18 +31,29 @@ func TestTransitivelyEnabledCalls(t *testing.T) {
for _, c := range target.Syscalls {
calls[c] = true
}
- if trans, disabled := target.TransitivelyEnabledCalls(calls); len(disabled) != 0 {
+ enabled, disabled := target.TransitivelyEnabledCalls(calls)
+ for c, ok := range enabled {
+ if !ok {
+ t.Fatalf("syscalls %v is false in enabled map", c.Name)
+ }
+ }
+ if target.OS == "test" {
+ for c := range enabled {
+ if c.CallName == "unsupported" {
+ t.Errorf("call %v is not disabled", c.Name)
+ }
+ }
for c, reason := range disabled {
- t.Logf("disabled %v: %v", c.Name, reason)
+ if c.CallName != "unsupported" {
+ t.Errorf("call %v is disabled: %v", c.Name, reason)
+ }
}
- t.Fatalf("can't create some resource")
- } else if len(trans) != len(calls) {
- t.Fatalf("transitive syscalls are not full")
} else {
- for c, ok := range trans {
- if !ok {
- t.Fatalf("syscalls %v is false in transitive map", c.Name)
- }
+ if len(enabled) != len(target.Syscalls) {
+ t.Errorf("some calls are disabled: %v/%v", len(enabled), len(target.Syscalls))
+ }
+ for c, reason := range disabled {
+ t.Errorf("disabled %v: %v", c.Name, reason)
}
}
})
diff --git a/prog/resources.go b/prog/resources.go
index 68fbe1599..bddb158d9 100644
--- a/prog/resources.go
+++ b/prog/resources.go
@@ -7,6 +7,13 @@ import (
"fmt"
)
+// We need to support structs as resources,
+// but for now we just special-case timespec/timeval.
+var timespecRes = &ResourceDesc{
+ Name: "timespec",
+ Kind: []string{"timespec"},
+}
+
func (target *Target) calcResourceCtors(kind []string, precise bool) []*Syscall {
// Find calls that produce the necessary resources.
var metas []*Syscall
@@ -28,6 +35,11 @@ func (target *Target) calcResourceCtors(kind []string, precise bool) []*Syscall
metas = append(metas, meta)
}
}
+ if kind[0] == timespecRes.Name {
+ if c := target.SyscallMap["clock_gettime"]; c != nil {
+ metas = append(metas, c)
+ }
+ }
return metas
}
@@ -72,82 +84,100 @@ func isCompatibleResourceImpl(dst, src []string, precise bool) bool {
return true
}
-func (c *Syscall) inputResources() []*ResourceType {
- var resources []*ResourceType
+func (target *Target) inputResources(c *Syscall) []*ResourceDesc {
+ var resources []*ResourceDesc
+ ForeachType(c, func(typ Type) {
+ if typ.Dir() == DirOut {
+ return
+ }
+ switch typ1 := typ.(type) {
+ case *ResourceType:
+ if !typ1.IsOptional {
+ resources = append(resources, typ1.Desc)
+ }
+ case *StructType:
+ if target.OS == "linux" && (typ1.Name() == "timespec" || typ1.Name() == "timeval") {
+ resources = append(resources, timespecRes)
+ }
+ }
+ })
+ return resources
+}
+
+func (target *Target) outputResources(c *Syscall) []*ResourceDesc {
+ var resources []*ResourceDesc
ForeachType(c, func(typ Type) {
switch typ1 := typ.(type) {
case *ResourceType:
- if typ1.Dir() != DirOut && !typ1.IsOptional {
- resources = append(resources, typ1)
+ if typ1.Dir() != DirIn {
+ resources = append(resources, typ1.Desc)
}
}
})
+ if c.CallName == "clock_gettime" {
+ resources = append(resources, timespecRes)
+ }
return resources
}
func (target *Target) TransitivelyEnabledCalls(enabled map[*Syscall]bool) (map[*Syscall]bool, map[*Syscall]string) {
supported := make(map[*Syscall]bool)
disabled := make(map[*Syscall]string)
+ canCreate := make(map[string]bool)
+ inputResources := make(map[*Syscall][]*ResourceDesc)
for c := range enabled {
- supported[c] = true
- }
- inputResources := make(map[*Syscall][]*ResourceType)
- ctors := make(map[string][]*Syscall)
- for c := range supported {
- inputs := c.inputResources()
- inputResources[c] = inputs
- for _, res := range inputs {
- if _, ok := ctors[res.Desc.Name]; ok {
- continue
- }
- ctors[res.Desc.Name] = target.calcResourceCtors(res.Desc.Kind, true)
- }
+ inputResources[c] = target.inputResources(c)
}
for {
n := len(supported)
- haveGettime := supported[target.SyscallMap["clock_gettime"]]
- for c := range supported {
- cantCreate := ""
- var resourceCtors []*Syscall
+ for c := range enabled {
+ if supported[c] {
+ continue
+ }
+ ready := true
for _, res := range inputResources[c] {
- noctors := true
- for _, ctor := range ctors[res.Desc.Name] {
- if supported[ctor] {
- noctors = false
- break
- }
- }
- if noctors {
- cantCreate = res.Desc.Name
- resourceCtors = ctors[res.Desc.Name]
+ if !canCreate[res.Name] {
+ ready = false
break
}
}
- // We need to support structs as resources,
- // but for now we just special-case timespec/timeval.
- if cantCreate == "" && !haveGettime && target.SyscallMap["clock_gettime"] != nil {
- ForeachType(c, func(typ Type) {
- if a, ok := typ.(*StructType); ok && a.Dir() != DirOut &&
- (a.Name() == "timespec" || a.Name() == "timeval") {
- cantCreate = a.Name()
- resourceCtors = []*Syscall{target.SyscallMap["clock_gettime"]}
+ if ready {
+ supported[c] = true
+ for _, res := range target.outputResources(c) {
+ for _, kind := range res.Kind {
+ canCreate[kind] = true
}
- })
- }
- if cantCreate != "" {
- delete(supported, c)
- var ctorNames []string
- for _, ctor := range resourceCtors {
- ctorNames = append(ctorNames, ctor.Name)
}
- disabled[c] = fmt.Sprintf("no syscalls can create resource %v,"+
- " enable some syscalls that can create it %v",
- cantCreate, ctorNames)
}
}
if n == len(supported) {
break
}
}
+ ctors := make(map[string][]string)
+ for c := range enabled {
+ if supported[c] {
+ continue
+ }
+ for _, res := range inputResources[c] {
+ if canCreate[res.Name] {
+ continue
+ }
+ if ctors[res.Name] == nil {
+ var names []string
+ for _, call := range target.calcResourceCtors(res.Kind, true) {
+ names = append(names, call.Name)
+ }
+ ctors[res.Name] = names
+ }
+ disabled[c] = fmt.Sprintf("no syscalls can create resource %v,"+
+ " enable some syscalls that can create it %v",
+ res.Name, ctors[res.Name])
+ break
+ }
+ }
+ if len(enabled) != len(supported)+len(disabled) {
+ panic("lost syscalls")
+ }
return supported, disabled
}