diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2015-10-12 10:16:57 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2015-10-12 10:16:57 +0200 |
| commit | 874c5754bb22dbf77d6b600ff91f0f4f1fc5073a (patch) | |
| tree | 0075fbd088046ad5c86e6e972235701d68b3ce7c /prog/clone.go | |
initial commit
Diffstat (limited to 'prog/clone.go')
| -rw-r--r-- | prog/clone.go | 49 |
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 +} |
