cmd,proc,terminal,debugger: Support default file descriptor redirects

Adds features to support default file descriptor redirects for the
target process:

1. A new command line flag '--redirect' and '-r' are added to specify
   file redirects for the target process
2. New syntax is added to the 'restart' command to specify file
   redirects.
3. Interactive instances will check if stdin/stdout and stderr are
   terminals and print a helpful error message if they aren't.
This commit is contained in:
aarzilli
2020-08-21 16:14:02 +02:00
committed by Alessandro Arzilli
parent f90134eb4d
commit 7555d1c063
43 changed files with 766 additions and 271 deletions

View File

@ -117,6 +117,9 @@ type Config struct {
// ExecuteKind contains the kind of the executed program.
ExecuteKind ExecuteKind
// Redirects specifies redirect rules for stdin, stdout and stderr
Redirects [3]string
}
// New creates a new Debugger. ProcessArgs specify the commandline arguments for the
@ -221,16 +224,16 @@ func (d *Debugger) Launch(processArgs []string, wd string) (*proc.Target, error)
}
switch d.config.Backend {
case "native":
return native.Launch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories, d.config.TTY)
return native.Launch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories, d.config.TTY, d.config.Redirects)
case "lldb":
return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories, d.config.TTY))
return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories, d.config.TTY, d.config.Redirects))
case "rr":
if d.target != nil {
// restart should not call us if the backend is 'rr'
panic("internal error: call to Launch with rr backend and target already exists")
}
run, stop, err := gdbserial.RecordAsync(processArgs, wd, false)
run, stop, err := gdbserial.RecordAsync(processArgs, wd, false, d.config.Redirects)
if err != nil {
return nil, err
}
@ -265,9 +268,9 @@ func (d *Debugger) Launch(processArgs []string, wd string) (*proc.Target, error)
case "default":
if runtime.GOOS == "darwin" {
return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories, d.config.TTY))
return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories, d.config.TTY, d.config.Redirects))
}
return native.Launch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories, d.config.TTY)
return native.Launch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories, d.config.TTY, d.config.Redirects)
default:
return nil, fmt.Errorf("unknown backend %q", d.config.Backend)
}
@ -409,7 +412,7 @@ func (d *Debugger) detach(kill bool) error {
// If the target process is a recording it will restart it from the given
// position. If pos starts with 'c' it's a checkpoint ID, otherwise it's an
// event number. If resetArgs is true, newArgs will replace the process args.
func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []string, rebuild bool) ([]api.DiscardedBreakpoint, error) {
func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []string, newRedirects [3]string, rebuild bool) ([]api.DiscardedBreakpoint, error) {
d.targetMutex.Lock()
defer d.targetMutex.Unlock()
@ -437,6 +440,7 @@ func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []
}
if resetArgs {
d.processArgs = append([]string{d.processArgs[0]}, newArgs...)
d.config.Redirects = newRedirects
}
var p *proc.Target
var err error
@ -460,7 +464,7 @@ func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []
}
if recorded {
run, stop, err2 := gdbserial.RecordAsync(d.processArgs, d.config.WorkingDir, false)
run, stop, err2 := gdbserial.RecordAsync(d.processArgs, d.config.WorkingDir, false, d.config.Redirects)
if err2 != nil {
return nil, err2
}