提交 79e0f543 编写于 作者: A Alessandro Arzilli 提交者: Derek Parker

cmd/dlv: add Go version check (#1533)

Before doing anything check that the version of Go is compatible with
the current version of Delve.
This will improve the error message in the case that  another change as
disruptive as Go1.11 dwarf compression, happens.
上级 2cadddd7
......@@ -28,6 +28,7 @@ Pass flags to the program you are debugging using `--`, for example:
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -28,6 +28,7 @@ dlv attach pid [executable]
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -23,6 +23,7 @@ dlv connect addr
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -29,6 +29,7 @@ dlv core <executable> <core>
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -34,6 +34,7 @@ dlv debug [package]
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -29,6 +29,7 @@ dlv exec <path/to/binary>
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -27,6 +27,7 @@ dlv replay [trace directory]
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -23,6 +23,7 @@ dlv run
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -34,6 +34,7 @@ dlv test [package]
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -38,6 +38,7 @@ dlv trace [package] regexp
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -23,6 +23,7 @@ dlv version
rr Uses mozilla rr (https://github.com/mozilla/rr).
(default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "localhost:0")
......
......@@ -49,6 +49,11 @@ var (
// Backend selection
Backend string
// CheckGoVersion is true if the debugger should check the version of Go
// used to compile the executable and refuse to work on incompatible
// versions.
CheckGoVersion bool
// RootCommand is the root of the command tree.
RootCommand *cobra.Command
......@@ -117,6 +122,7 @@ Defaults to "debugger" when logging is enabled with --log.`)
lldb Uses lldb-server or debugserver.
rr Uses mozilla rr (https://github.com/mozilla/rr).
`)
RootCommand.PersistentFlags().BoolVarP(&CheckGoVersion, "check-go-version", "", true, "Checks that the version of Go in use is compatible with Delve.")
// 'attach' subcommand.
attachCommand := &cobra.Command{
......@@ -389,12 +395,13 @@ func traceCmd(cmd *cobra.Command, args []string) {
// Create and start a debug server
server := rpccommon.NewServer(&service.Config{
Listener: listener,
ProcessArgs: processArgs,
AttachPid: traceAttachPid,
APIVersion: 2,
WorkingDir: WorkingDir,
Backend: Backend,
Listener: listener,
ProcessArgs: processArgs,
AttachPid: traceAttachPid,
APIVersion: 2,
WorkingDir: WorkingDir,
Backend: Backend,
CheckGoVersion: CheckGoVersion,
})
if err := server.Run(); err != nil {
fmt.Fprintln(os.Stderr, err)
......@@ -598,6 +605,7 @@ func execute(attachPid int, processArgs []string, conf *config.Config, coreFile
CoreFile: coreFile,
Foreground: Headless,
DebugInfoDirectories: conf.DebugInfoDirectories,
CheckGoVersion: CheckGoVersion,
DisconnectChan: disconnectChan,
})
......
package goversion
import (
"fmt"
)
var (
minSupportedVersionOfGoMinor = 10
maxSupportedVersionOfGoMinor = 12
goTooOldErr = fmt.Errorf("Version of Go is too old for this version of Delve (minimum supported version 1.%d, suppress this error with --check-go-version=false)", minSupportedVersionOfGoMinor)
dlvTooOldErr = fmt.Errorf("Version of Delve is too old for this version of Go (maximum supported version 1.%d, suppress this error with --check-go-version=false)", maxSupportedVersionOfGoMinor)
)
// Compatible checks that the version specified in the producer string is compatible with
// this version of delve.
func Compatible(producer string) error {
ver := parseProducer(producer)
if ver.IsDevel() {
return nil
}
if !ver.AfterOrEqual(GoVersion{1, minSupportedVersionOfGoMinor, -1, 0, 0, ""}) {
return goTooOldErr
}
if ver.AfterOrEqual(GoVersion{1, maxSupportedVersionOfGoMinor + 1, -1, 0, 0, ""}) {
return dlvTooOldErr
}
return nil
}
......@@ -167,12 +167,17 @@ const producerVersionPrefix = "Go cmd/compile "
// ProducerAfterOrEqual checks that the DW_AT_producer version is
// major.minor or a later version, or a development version.
func ProducerAfterOrEqual(producer string, major, minor int) bool {
if strings.HasPrefix(producer, producerVersionPrefix) {
producer = producer[len(producerVersionPrefix):]
}
ver, _ := Parse(producer)
ver := parseProducer(producer)
if ver.IsDevel() {
return true
}
return ver.AfterOrEqual(GoVersion{major, minor, -1, 0, 0, ""})
}
func parseProducer(producer string) GoVersion {
if strings.HasPrefix(producer, producerVersionPrefix) {
producer = producer[len(producerVersionPrefix):]
}
ver, _ := Parse(producer)
return ver
}
......@@ -39,6 +39,11 @@ type Config struct {
// Foreground lets target process access stdin.
Foreground bool
// CheckGoVersion is true if the debugger should check the version of Go
// used to compile the executable and refuse to work on incompatible
// versions.
CheckGoVersion bool
// DisconnectChan will be closed by the server when the client disconnects
DisconnectChan chan<- struct{}
}
......@@ -68,6 +68,11 @@ type Config struct {
// DebugInfoDirectories is the list of directories to look for
// when resolving external debug info files.
DebugInfoDirectories []string
// CheckGoVersion is true if the debugger should check the version of Go
// used to compile the executable and refuse to work on incompatible
// versions.
CheckGoVersion bool
}
// New creates a new Debugger. ProcessArgs specify the commandline arguments for the
......@@ -111,6 +116,10 @@ func New(config *Config, processArgs []string) (*Debugger, error) {
return nil, err
}
d.target = p
if err := d.checkGoVersion(); err != nil {
d.target.Detach(true)
return nil, err
}
default:
d.log.Infof("launching process with args: %v", d.processArgs)
......@@ -123,10 +132,25 @@ func New(config *Config, processArgs []string) (*Debugger, error) {
return nil, err
}
d.target = p
if err := d.checkGoVersion(); err != nil {
d.target.Detach(true)
return nil, err
}
}
return d, nil
}
func (d *Debugger) checkGoVersion() error {
if !d.config.CheckGoVersion {
return nil
}
producer := d.target.BinInfo().Producer()
if producer == "" {
return nil
}
return goversion.Compatible(producer)
}
// Launch will start a process with the given args and working directory.
func (d *Debugger) Launch(processArgs []string, wd string) (proc.Process, error) {
switch d.config.Backend {
......
......@@ -122,6 +122,7 @@ func (s *ServerImpl) Run() error {
Backend: s.config.Backend,
Foreground: s.config.Foreground,
DebugInfoDirectories: s.config.DebugInfoDirectories,
CheckGoVersion: s.config.CheckGoVersion,
},
s.config.ProcessArgs); err != nil {
return err
......
......@@ -60,9 +60,10 @@ func withTestClient2Extended(name string, t *testing.T, fn func(c service.Client
}
fixture := protest.BuildFixture(name, buildFlags)
server := rpccommon.NewServer(&service.Config{
Listener: listener,
ProcessArgs: []string{fixture.Path},
Backend: testBackend,
Listener: listener,
ProcessArgs: []string{fixture.Path},
Backend: testBackend,
CheckGoVersion: true,
})
if err := server.Run(); err != nil {
t.Fatal(err)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册