aboutsummaryrefslogtreecommitdiffstats
path: root/prog/clone.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-10-12 10:16:57 +0200
committerDmitry Vyukov <dvyukov@google.com>2015-10-12 10:16:57 +0200
commit874c5754bb22dbf77d6b600ff91f0f4f1fc5073a (patch)
tree0075fbd088046ad5c86e6e972235701d68b3ce7c /prog/clone.go
initial commit
Diffstat (limited to 'prog/clone.go')
-rw-r--r--prog/clone.go49
1 files changed, 49 insertions, 0 deletions
diff --git a/prog/clone.go b/prog/clone.go
new file mode 100644
index 000000000..dd8e6e4db
--- /dev/null
+++ b/prog/clone.go
@@ -0,0 +1,49 @@
+// Copyright 2015 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package prog
+
+func (p *Prog) Clone() *Prog {
+ p1 := new(Prog)
+ newargs := make(map[*Arg]*Arg)
+ for _, c := range p.Calls {
+ c1 := new(Call)
+ c1.Meta = c.Meta
+ c1.Ret = c.Ret.clone(c1, newargs)
+ for _, arg := range c.Args {
+ c1.Args = append(c1.Args, arg.clone(c1, newargs))
+ }
+ p1.Calls = append(p1.Calls, c1)
+ }
+ if err := p1.validate(); err != nil {
+ panic(err)
+ }
+ return p1
+}
+
+func (arg *Arg) clone(c *Call, newargs map[*Arg]*Arg) *Arg {
+ arg1 := new(Arg)
+ *arg1 = *arg
+ arg1.Call = c
+ arg1.Data = append([]byte{}, arg.Data...)
+ switch arg.Kind {
+ case ArgPointer:
+ if arg.Res != nil {
+ arg1.Res = arg.Res.clone(c, newargs)
+ }
+ case ArgResult:
+ r := newargs[arg.Res]
+ arg1.Res = r
+ if r.Uses == nil {
+ r.Uses = make(map[*Arg]bool)
+ }
+ r.Uses[arg1] = true
+ }
+ arg1.Inner = nil
+ for _, arg2 := range arg.Inner {
+ arg1.Inner = append(arg1.Inner, arg2.clone(c, newargs))
+ }
+ arg1.Uses = nil // filled when we clone the referent
+ newargs[arg] = arg1
+ return arg1
+}