diff --git a/cmd/dlv/main.go b/cmd/dlv/main.go index c5ce71d9..777e0717 100644 --- a/cmd/dlv/main.go +++ b/cmd/dlv/main.go @@ -58,24 +58,6 @@ func main() { os.Exit(0) } - start := func(name string) *proctl.DebuggedProcess { - proc := exec.Command(name) - proc.Stdout = os.Stdout - - err = proc.Start() - if err != nil { - die(1, "Could not start process:", err) - } - syscall.Kill(proc.Process.Pid, syscall.SIGSTOP) - - dbgproc, err = proctl.NewDebugProcess(proc.Process.Pid) - if err != nil { - die(1, "Could not start debugging process:", err) - } - - return dbgproc - } - switch { case run: const debugname = "debug" @@ -86,14 +68,20 @@ func main() { } defer os.Remove(debugname) - dbgproc = start("./" + debugname) - case pid != 0: - dbgproc, err = proctl.NewDebugProcess(pid) + dbgproc, err = proctl.Launch([]string{"./" + debugname}) if err != nil { - die(1, "Could not start debugging process:", err) + die(1, "Could not launch program:", err) + } + case pid != 0: + dbgproc, err = proctl.Attach(pid) + if err != nil { + die(1, "Could not attach to process:", err) } case proc != "": - dbgproc = start(proc) + dbgproc, err = proctl.Launch([]string{proc}) + if err != nil { + die(1, "Could not launch program:", err) + } } goreadline.LoadHistoryFromFile(historyFile) diff --git a/helper/helper.go b/helper/helper.go index 1daf7813..16f37490 100644 --- a/helper/helper.go +++ b/helper/helper.go @@ -30,9 +30,9 @@ func WithTestProcess(name string, t *testing.T, fn testfunc) { } defer os.Remove("./" + base) - p, err := proctl.AttachBinary("./" + base) + p, err := proctl.Launch([]string{"./" + base}) if err != nil { - t.Fatal("NewDebugProcess():", err) + t.Fatal("Launch():", err) } defer p.Process.Kill() diff --git a/proctl/proctl_linux_amd64.go b/proctl/proctl_linux_amd64.go index bace27f2..50b9d86a 100644 --- a/proctl/proctl_linux_amd64.go +++ b/proctl/proctl_linux_amd64.go @@ -80,36 +80,50 @@ func (bpe BreakPointExistsError) Error() string { return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr) } -func AttachBinary(name string) (*DebuggedProcess, error) { - proc := exec.Command(name) +func Attach(pid int) (*DebuggedProcess, error) { + return newDebugProcess(pid, true) +} + +func Launch(cmd []string) (*DebuggedProcess, error) { + proc := exec.Command(cmd[0]) + proc.Args = cmd proc.Stdout = os.Stdout + proc.SysProcAttr = &syscall.SysProcAttr{Ptrace: true} - err := proc.Start() - if err != nil { + if err := proc.Start(); err != nil { return nil, err } - dbgproc, err := NewDebugProcess(proc.Process.Pid) + var status syscall.WaitStatus + _, err := syscall.Wait4(proc.Process.Pid, &status, syscall.WALL, nil) if err != nil { - return nil, err + return nil, fmt.Errorf("waiting for target execve failed: %s", err) } - return dbgproc, nil + return newDebugProcess(proc.Process.Pid, false) } // Returns a new DebuggedProcess struct with sensible defaults. -func NewDebugProcess(pid int) (*DebuggedProcess, error) { +func newDebugProcess(pid int, attach bool) (*DebuggedProcess, error) { dbp := DebuggedProcess{ Pid: pid, Threads: make(map[int]*ThreadContext), BreakPoints: make(map[uint64]*BreakPoint), } - thread, err := dbp.AttachThread(pid) - if err != nil { - return nil, err + if attach { + thread, err := dbp.AttachThread(pid) + if err != nil { + return nil, err + } + dbp.CurrentThread = thread + } else { + thread, err := dbp.addThread(pid) + if err != nil { + return nil, err + } + dbp.CurrentThread = thread } - dbp.CurrentThread = thread proc, err := os.FindProcess(pid) if err != nil {