diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2018-06-21 11:03:53 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-06-22 16:40:45 +0200 |
| commit | c31f96a8c65c0757078ea77218905c73fc1068d4 (patch) | |
| tree | fc68a43058ed05e9604514c67240f6a4fa0b25ed /pkg/ipc | |
| parent | 14e6c472f54ac36d5bdfe451371c619953eb0a17 (diff) | |
executor: rework fallback coverage
We have fallback coverage implmentation for freebsd.
1. It's broken after some recent changes.
2. We need it for fuchsia, windows, akaros, linux too.
3. It's painful to work with C code.
Move fallback coverage to ipc package,
fix it and provide for all OSes.
Diffstat (limited to 'pkg/ipc')
| -rw-r--r-- | pkg/ipc/ipc.go | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index 5619f16de..871401164 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -157,8 +157,9 @@ func DefaultConfig() (*Config, *ExecOpts, error) { } type CallInfo struct { - Signal []uint32 // feedback signal, filled if FlagSignal is set - Cover []uint32 // per-call coverage, filled if FlagSignal is set and cover == true, + Executed bool + Signal []uint32 // feedback signal, filled if FlagSignal is set + Cover []uint32 // per-call coverage, filled if FlagSignal is set and cover == true, //if dedup == false, then cov effectively contains a trace, otherwise duplicates are removed Comps prog.CompMap // per-call comparison operands Errno int // call errno (0 if the call was successful) @@ -310,10 +311,26 @@ func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info []CallIn if env.out != nil { info, err0 = env.readOutCoverage(p) + if info != nil { + addFallbackSignal(p, info) + } } return } +// addFallbackSignal computes simple fallback signal in cases we don't have real coverage signal. +// We use syscall number or-ed with returned errno value as signal. +// At least this gives us all combinations of syscall+errno. +func addFallbackSignal(p *prog.Prog, info []CallInfo) { + for i, call := range p.Calls { + inf := &info[i] + if !inf.Executed || len(inf.Signal) != 0 { + continue + } + inf.Signal = []uint32{uint32(call.Meta.ID)<<16 | uint32(inf.Errno)&0x3ff} + } +} + func (env *Env) readOutCoverage(p *prog.Prog) (info []CallInfo, err0 error) { out := ((*[1 << 28]uint32)(unsafe.Pointer(&env.out[0])))[:len(env.out)/int(unsafe.Sizeof(uint32(0)))] readOut := func(v *uint32) bool { @@ -377,6 +394,7 @@ func (env *Env) readOutCoverage(p *prog.Prog) (info []CallInfo, err0 error) { return } c := p.Calls[callIndex] + info[callIndex].Executed = true if num := c.Meta.ID; uint32(num) != callNum { err0 = fmt.Errorf("executor %v: failed to read output coverage:"+ " record %v call %v: expect syscall %v, got %v, executed %v (cov: %v)", |
