service/debugger: Assume current dir for exec (#3167)
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.
This commit is contained in:
parent
63ef73a0dd
commit
b072f61bf8
@ -3,7 +3,6 @@ package native
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
@ -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()
|
||||
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -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 {
|
||||
@ -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)
|
||||
@ -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
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/go-delve/delve/pkg/gobuild"
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user