mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	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:
		| @ -3,7 +3,6 @@ package native | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" |  | ||||||
| 	"syscall" | 	"syscall" | ||||||
| 	"unsafe" | 	"unsafe" | ||||||
|  |  | ||||||
| @ -25,10 +24,7 @@ func (os *osProcessDetails) Close() {} | |||||||
|  |  | ||||||
| // Launch creates and begins debugging a new process. | // 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) { | func Launch(cmd []string, wd string, flags proc.LaunchFlags, _ []string, _ string, redirects [3]string) (*proc.Target, error) { | ||||||
| 	argv0Go, err := filepath.Abs(cmd[0]) | 	argv0Go := cmd[0] | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	env := proc.DisableAsyncPreemptEnv() | 	env := proc.DisableAsyncPreemptEnv() | ||||||
|  |  | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"go/parser" | 	"go/parser" | ||||||
| 	"go/token" | 	"go/token" | ||||||
|  | 	"io" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| @ -246,9 +247,11 @@ func (d *Debugger) TargetGoVersion() string { | |||||||
|  |  | ||||||
| // Launch will start a process with the given args and working directory. | // Launch will start a process with the given args and working directory. | ||||||
| func (d *Debugger) Launch(processArgs []string, wd string) (*proc.Target, error) { | 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 | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | 	processArgs[0] = fullpath | ||||||
|  |  | ||||||
| 	launchFlags := proc.LaunchFlags(0) | 	launchFlags := proc.LaunchFlags(0) | ||||||
| 	if d.config.Foreground { | 	if d.config.Foreground { | ||||||
| @ -2259,34 +2262,31 @@ func noDebugErrorWarning(err error) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func verifyBinaryFormat(exePath string) error { | func verifyBinaryFormat(exePath string) (string, error) { | ||||||
| 	f, err := os.Open(exePath) | 	fullpath, err := filepath.Abs(exePath) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	f, err := os.Open(fullpath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
| 	} | 	} | ||||||
| 	defer f.Close() | 	defer f.Close() | ||||||
|  |  | ||||||
| 	switch runtime.GOOS { | 	// Skip this check on Windows. | ||||||
| 	case "windows": | 	// TODO(derekparker) exec.LookPath looks for valid Windows extensions. | ||||||
| 		// Make sure the binary exists and is an executable file | 	// We don't create our binaries with valid extensions, even though we should. | ||||||
| 		if filepath.Base(exePath) == exePath { | 	// Skip this check for now. | ||||||
| 			if _, err := exec.LookPath(exePath); err != nil { | 	if runtime.GOOS != "windows" { | ||||||
| 				return err | 		_, err = exec.LookPath(fullpath) | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	default: |  | ||||||
| 		fi, err := f.Stat() |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return "", api.ErrNotExecutable | ||||||
| 		} |  | ||||||
| 		if (fi.Mode() & 0111) == 0 { |  | ||||||
| 			return api.ErrNotExecutable |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// check that the binary format is what we expect for the host system | 	// 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 { | 	switch runtime.GOOS { | ||||||
| 	case "darwin": | 	case "darwin": | ||||||
| 		exe, err = macho.NewFile(f) | 		exe, err = macho.NewFile(f) | ||||||
| @ -2299,10 +2299,10 @@ func verifyBinaryFormat(exePath string) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return api.ErrNotExecutable | 		return "", api.ErrNotExecutable | ||||||
| 	} | 	} | ||||||
| 	exe.Close() | 	exe.Close() | ||||||
| 	return nil | 	return fullpath, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| var attachErrorMessage = attachErrorMessageDefault | var attachErrorMessage = attachErrorMessageDefault | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import ( | |||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"runtime" | 	"runtime" | ||||||
|  | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/go-delve/delve/pkg/gobuild" | 	"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) | 		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) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Derek Parker
					Derek Parker