diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-04-15 14:54:59 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-04-16 14:20:36 +0000 |
| commit | 4cd91fc0b5007710bf0f38de6319ce24c31a52e5 (patch) | |
| tree | 025210f316d065a63e680a054ab04c017ebc7315 /pkg/ipc | |
| parent | 7e9780e93983e03547322aab489429ae4a7d2fa3 (diff) | |
pkg/ipc: pass only exec encoding to Exec
Does not require passing text program to ipc.Env.Exec.
Make it possible to provide just the exec encoding.
This requires moving fallback coverage to the host
since it need the program.
Diffstat (limited to 'pkg/ipc')
| -rw-r--r-- | pkg/ipc/ipc.go | 51 |
1 files changed, 16 insertions, 35 deletions
diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index ea2e22569..417f27c24 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -247,13 +247,14 @@ func (env *Env) Close() error { } } -// Exec starts executor binary to execute program p and returns information about the execution: +// Exec starts executor binary to execute program stored in progData in exec encoding +// and returns information about the execution: // output: process output // info: per-call info // hanged: program hanged and was killed // err0: failed to start the process or bug in executor itself. -func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info *ProgInfo, hanged bool, err0 error) { - progData, err := p.SerializeForExec() +func (env *Env) ExecProg(opts *ExecOpts, progData []byte) (output []byte, info *ProgInfo, hanged bool, err0 error) { + ncalls, err := prog.ExecCallCount(progData) if err != nil { err0 = err return @@ -284,12 +285,9 @@ func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info *ProgInf return } - info, err0 = env.parseOutput(p, opts) + info, err0 = env.parseOutput(opts, ncalls) if info != nil { info.Elapsed = elapsed - if env.config.Flags&FlagSignal == 0 { - addFallbackSignal(p, info) - } } if !env.config.UseForkServer { env.cmd.close() @@ -298,6 +296,15 @@ func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info *ProgInf return } +func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info *ProgInfo, hanged bool, err0 error) { + progData, err := p.SerializeForExec() + if err != nil { + err0 = err + return + } + return env.ExecProg(opts, progData) +} + func (env *Env) ForceRestart() { if env.cmd != nil { env.cmd.close() @@ -328,36 +335,13 @@ var ( rateLimiter <-chan time.Time ) -// 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 *ProgInfo) { - callInfos := make([]prog.CallInfo, len(info.Calls)) - for i, inf := range info.Calls { - if inf.Flags&CallExecuted != 0 { - callInfos[i].Flags |= prog.CallExecuted - } - if inf.Flags&CallFinished != 0 { - callInfos[i].Flags |= prog.CallFinished - } - if inf.Flags&CallBlocked != 0 { - callInfos[i].Flags |= prog.CallBlocked - } - callInfos[i].Errno = inf.Errno - } - p.FallbackSignal(callInfos) - for i, inf := range callInfos { - info.Calls[i].Signal = inf.Signal - } -} - -func (env *Env) parseOutput(p *prog.Prog, opts *ExecOpts) (*ProgInfo, error) { +func (env *Env) parseOutput(opts *ExecOpts, ncalls int) (*ProgInfo, error) { out := env.out ncmd, ok := readUint32(&out) if !ok { return nil, fmt.Errorf("failed to read number of calls") } - info := &ProgInfo{Calls: make([]CallInfo, len(p.Calls))} + info := &ProgInfo{Calls: make([]CallInfo, ncalls)} extraParts := make([]CallInfo, 0) for i := uint32(0); i < ncmd; i++ { if len(out) < int(unsafe.Sizeof(callReply{})) { @@ -373,9 +357,6 @@ func (env *Env) parseOutput(p *prog.Prog, opts *ExecOpts) (*ProgInfo, error) { if int(reply.index) >= len(info.Calls) { return nil, fmt.Errorf("bad call %v index %v/%v", i, reply.index, len(info.Calls)) } - if num := p.Calls[reply.index].Meta.ID; int(reply.num) != num { - return nil, fmt.Errorf("wrong call %v num %v/%v", i, reply.num, num) - } inf = &info.Calls[reply.index] if inf.Flags != 0 || inf.Signal != nil { return nil, fmt.Errorf("duplicate reply for call %v/%v/%v", i, reply.index, reply.num) |
