Skip to content

Commit

Permalink
service/debugger: Assume current dir for exec (go-delve#3167)
Browse files Browse the repository at this point in the history
This patch modifies the behavior of the exec subcommand such that
you don't necessarily have to write the "./" prefix when trying
to debug a precompiled binary in your working directory.

For example (given foo.test in working dir), before this change:

dlv exec foo.test

Would result in an error, forcing the user to type:

dlv exec ./foo.test

This just makes things a bit more convenient.
  • Loading branch information
derekparker authored Oct 28, 2022
1 parent 63ef73a commit b072f61
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 27 deletions.
6 changes: 1 addition & 5 deletions pkg/proc/native/proc_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package native
import (
"fmt"
"os"
"path/filepath"
"syscall"
"unsafe"

Expand All @@ -25,10 +24,7 @@ func (os *osProcessDetails) Close() {}

// Launch creates and begins debugging a new process.
func Launch(cmd []string, wd string, flags proc.LaunchFlags, _ []string, _ string, redirects [3]string) (*proc.Target, error) {
argv0Go, err := filepath.Abs(cmd[0])
if err != nil {
return nil, err
}
argv0Go := cmd[0]

env := proc.DisableAsyncPreemptEnv()

Expand Down
44 changes: 22 additions & 22 deletions service/debugger/debugger.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"go/parser"
"go/token"
"io"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -246,9 +247,11 @@ func (d *Debugger) TargetGoVersion() string {

// Launch will start a process with the given args and working directory.
func (d *Debugger) Launch(processArgs []string, wd string) (*proc.Target, error) {
if err := verifyBinaryFormat(processArgs[0]); err != nil {
fullpath, err := verifyBinaryFormat(processArgs[0])
if err != nil {
return nil, err
}
processArgs[0] = fullpath

launchFlags := proc.LaunchFlags(0)
if d.config.Foreground {
Expand Down Expand Up @@ -2259,34 +2262,31 @@ func noDebugErrorWarning(err error) error {
return err
}

func verifyBinaryFormat(exePath string) error {
f, err := os.Open(exePath)
func verifyBinaryFormat(exePath string) (string, error) {
fullpath, err := filepath.Abs(exePath)
if err != nil {
return err
return "", err
}

f, err := os.Open(fullpath)
if err != nil {
return "", err
}
defer f.Close()

switch runtime.GOOS {
case "windows":
// Make sure the binary exists and is an executable file
if filepath.Base(exePath) == exePath {
if _, err := exec.LookPath(exePath); err != nil {
return err
}
}
default:
fi, err := f.Stat()
// Skip this check on Windows.
// TODO(derekparker) exec.LookPath looks for valid Windows extensions.
// We don't create our binaries with valid extensions, even though we should.
// Skip this check for now.
if runtime.GOOS != "windows" {
_, err = exec.LookPath(fullpath)
if err != nil {
return err
}
if (fi.Mode() & 0111) == 0 {
return api.ErrNotExecutable
return "", api.ErrNotExecutable
}
}

// check that the binary format is what we expect for the host system
var exe interface{ Close() error }

var exe io.Closer
switch runtime.GOOS {
case "darwin":
exe, err = macho.NewFile(f)
Expand All @@ -2299,10 +2299,10 @@ func verifyBinaryFormat(exePath string) error {
}

if err != nil {
return api.ErrNotExecutable
return "", api.ErrNotExecutable
}
exe.Close()
return nil
return fullpath, nil
}

var attachErrorMessage = attachErrorMessageDefault
Expand Down
33 changes: 33 additions & 0 deletions service/debugger/debugger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"runtime"
"strings"
"testing"

"github.com/go-delve/delve/pkg/gobuild"
Expand Down Expand Up @@ -68,3 +69,35 @@ func TestDebugger_LaunchInvalidFormat(t *testing.T) {
t.Fatalf("expected error \"%s\" got \"%v\"", api.ErrNotExecutable, err)
}
}

func TestDebugger_LaunchCurrentDir(t *testing.T) {
fixturesDir := protest.FindFixturesDir()
testDir := filepath.Join(fixturesDir, "buildtest")
debugname := "debug"
exepath := filepath.Join(testDir, debugname)
originalPath, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
defer os.Chdir(originalPath)
defer func() {
if err := os.Remove(exepath); err != nil {
t.Fatalf("error removing executable %v", err)
}
}()
if err := gobuild.GoBuild(debugname, []string{testDir}, fmt.Sprintf("-o %s", exepath)); err != nil {
t.Fatalf("go build error %v", err)
}

os.Chdir(testDir)

d := new(Debugger)
d.config = &Config{}
_, err = d.Launch([]string{debugname}, ".")
if err == nil {
t.Fatal("expected error but none was generated")
}
if err != nil && !strings.Contains(err.Error(), "unknown backend") {
t.Fatal(err)
}
}

0 comments on commit b072f61

Please sign in to comment.