cmd/dlv: do not pass "linkmode internal" for windows on go1.9 and later
go1.9 no longer needs "linkmode internal" on windows. Fixes #755 Fixes #477 Fixes #631
This commit is contained in:
parent
a17de32c23
commit
1128c26b87
@ -15,6 +15,7 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/derekparker/delve/pkg/config"
|
||||
"github.com/derekparker/delve/pkg/goversion"
|
||||
"github.com/derekparker/delve/pkg/terminal"
|
||||
"github.com/derekparker/delve/pkg/version"
|
||||
"github.com/derekparker/delve/service"
|
||||
@ -76,8 +77,11 @@ func New(docCall bool) *cobra.Command {
|
||||
conf = config.LoadConfig()
|
||||
buildFlagsDefault := ""
|
||||
if runtime.GOOS == "windows" {
|
||||
// Work-around for https://github.com/golang/go/issues/13154
|
||||
buildFlagsDefault = "-ldflags='-linkmode internal'"
|
||||
ver, _ := goversion.Installed()
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
// Work-around for https://github.com/golang/go/issues/13154
|
||||
buildFlagsDefault = "-ldflags='-linkmode internal'"
|
||||
}
|
||||
}
|
||||
|
||||
// Main dlv root command.
|
||||
|
@ -1,6 +1,7 @@
|
||||
package proc
|
||||
package goversion
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@ -13,7 +14,7 @@ type GoVersion struct {
|
||||
Minor int
|
||||
Rev int
|
||||
Beta int
|
||||
RC int
|
||||
RC int
|
||||
Proposal string
|
||||
}
|
||||
|
||||
@ -21,7 +22,8 @@ var (
|
||||
GoVer18Beta = GoVersion{1, 8, -1, 0, 0, ""}
|
||||
)
|
||||
|
||||
func ParseVersionString(ver string) (GoVersion, bool) {
|
||||
// Parse parses a go verison string
|
||||
func Parse(ver string) (GoVersion, bool) {
|
||||
var r GoVersion
|
||||
var err1, err2, err3 error
|
||||
|
||||
@ -130,3 +132,21 @@ func (v *GoVersion) AfterOrEqual(b GoVersion) bool {
|
||||
func (v *GoVersion) IsDevel() bool {
|
||||
return v.Major < 0
|
||||
}
|
||||
|
||||
const goVersionPrefix = "go version "
|
||||
|
||||
// Installed runs "go verison" and parses the output
|
||||
func Installed() (GoVersion, bool) {
|
||||
out, err := exec.Command("go", "version").CombinedOutput()
|
||||
if err != nil {
|
||||
return GoVersion{}, false
|
||||
}
|
||||
|
||||
s := string(out)
|
||||
|
||||
if !strings.HasPrefix(s, goVersionPrefix) {
|
||||
return GoVersion{}, false
|
||||
}
|
||||
|
||||
return Parse(s[len(goVersionPrefix):])
|
||||
}
|
52
pkg/goversion/version_test.go
Normal file
52
pkg/goversion/version_test.go
Normal file
@ -0,0 +1,52 @@
|
||||
package goversion
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func versionAfterOrEqual(t *testing.T, verStr string, ver GoVersion) {
|
||||
pver, ok := Parse(verStr)
|
||||
if !ok {
|
||||
t.Fatalf("Could not parse version string <%s>", verStr)
|
||||
}
|
||||
if !pver.AfterOrEqual(ver) {
|
||||
t.Fatalf("Version <%s> parsed as %v not after %v", verStr, pver, ver)
|
||||
}
|
||||
t.Logf("version string <%s> → %v", verStr, ver)
|
||||
}
|
||||
|
||||
func TestParseVersionString(t *testing.T) {
|
||||
versionAfterOrEqual(t, "go1.4", GoVersion{1, 4, 0, 0, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.5.0", GoVersion{1, 5, 0, 0, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.4.2", GoVersion{1, 4, 2, 0, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.5beta2", GoVersion{1, 5, -1, 2, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.5rc2", GoVersion{1, 5, -1, 0, 2, ""})
|
||||
versionAfterOrEqual(t, "go1.6.1 (appengine-1.9.37)", GoVersion{1, 6, 1, 0, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.8.1.typealias", GoVersion{1, 6, 1, 0, 0, ""})
|
||||
ver, ok := Parse("devel +17efbfc Tue Jul 28 17:39:19 2015 +0000 linux/amd64")
|
||||
if !ok {
|
||||
t.Fatalf("Could not parse devel version string")
|
||||
}
|
||||
if !ver.IsDevel() {
|
||||
t.Fatalf("Devel version string not correctly recognized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstalled(t *testing.T) {
|
||||
installedVersion, ok := Installed()
|
||||
if !ok {
|
||||
t.Fatalf("could not parse output of go version")
|
||||
}
|
||||
runtimeVersion, ok := Parse(runtime.Version())
|
||||
if !ok {
|
||||
t.Fatalf("could not parse output of runtime.Version() %q", runtime.Version())
|
||||
}
|
||||
|
||||
t.Logf("installed: %v", installedVersion)
|
||||
t.Logf("runtime: %v", runtimeVersion)
|
||||
|
||||
if installedVersion != runtimeVersion {
|
||||
t.Fatalf("version mismatch %#v %#v", installedVersion, runtimeVersion)
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@ import (
|
||||
"go/token"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type functionDebugInfo struct {
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/derekparker/delve/pkg/dwarf/frame"
|
||||
"github.com/derekparker/delve/pkg/goversion"
|
||||
"github.com/derekparker/delve/pkg/proc"
|
||||
"github.com/derekparker/delve/pkg/proc/gdbserial"
|
||||
"github.com/derekparker/delve/pkg/proc/native"
|
||||
@ -429,9 +430,9 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc
|
||||
func TestNextGeneral(t *testing.T) {
|
||||
var testcases []nextTest
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
testcases = []nextTest{
|
||||
{17, 19},
|
||||
{19, 20},
|
||||
@ -582,9 +583,9 @@ func TestNextFunctionReturn(t *testing.T) {
|
||||
func TestNextFunctionReturnDefer(t *testing.T) {
|
||||
var testcases []nextTest
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
testcases = []nextTest{
|
||||
{5, 6},
|
||||
{6, 9},
|
||||
@ -1062,34 +1063,6 @@ func TestContinueMulti(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func versionAfterOrEqual(t *testing.T, verStr string, ver proc.GoVersion) {
|
||||
pver, ok := proc.ParseVersionString(verStr)
|
||||
if !ok {
|
||||
t.Fatalf("Could not parse version string <%s>", verStr)
|
||||
}
|
||||
if !pver.AfterOrEqual(ver) {
|
||||
t.Fatalf("Version <%s> parsed as %v not after %v", verStr, pver, ver)
|
||||
}
|
||||
t.Logf("version string <%s> → %v", verStr, ver)
|
||||
}
|
||||
|
||||
func TestParseVersionString(t *testing.T) {
|
||||
versionAfterOrEqual(t, "go1.4", proc.GoVersion{1, 4, 0, 0, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.5.0", proc.GoVersion{1, 5, 0, 0, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.4.2", proc.GoVersion{1, 4, 2, 0, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.5beta2", proc.GoVersion{1, 5, -1, 2, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.5rc2", proc.GoVersion{1, 5, -1, 0, 2, ""})
|
||||
versionAfterOrEqual(t, "go1.6.1 (appengine-1.9.37)", proc.GoVersion{1, 6, 1, 0, 0, ""})
|
||||
versionAfterOrEqual(t, "go1.8.1.typealias", proc.GoVersion{1, 6, 1, 0, 0, ""})
|
||||
ver, ok := proc.ParseVersionString("devel +17efbfc Tue Jul 28 17:39:19 2015 +0000 linux/amd64")
|
||||
if !ok {
|
||||
t.Fatalf("Could not parse devel version string")
|
||||
}
|
||||
if !ver.IsDevel() {
|
||||
t.Fatalf("Devel version string not correctly recognized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBreakpointOnFunctionEntry(t *testing.T) {
|
||||
protest.AllowRecording(t)
|
||||
withTestProcess("testprog", t, func(p proc.Process, fixture protest.Fixture) {
|
||||
@ -1882,8 +1855,8 @@ func TestPackageVariables(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIssue149(t *testing.T) {
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
return
|
||||
}
|
||||
// setting breakpoint on break statement
|
||||
@ -2074,8 +2047,8 @@ func TestIssue509(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnsupportedArch(t *testing.T) {
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major < 0 || !ver.AfterOrEqual(proc.GoVersion{1, 6, -1, 0, 0, ""}) || ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major < 0 || !ver.AfterOrEqual(goversion.GoVersion{1, 6, -1, 0, 0, ""}) || ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
// cross compile (with -N?) works only on select versions of go
|
||||
return
|
||||
}
|
||||
@ -2184,8 +2157,8 @@ func TestStepCallPtr(t *testing.T) {
|
||||
func TestStepReturnAndPanic(t *testing.T) {
|
||||
// Tests that Step works correctly when returning from functions
|
||||
// and when a deferred function is called when panic'ing.
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
testseq("defercall", contStep, []nextTest{
|
||||
{17, 5},
|
||||
{5, 6},
|
||||
@ -2227,9 +2200,9 @@ func TestStepDeferReturn(t *testing.T) {
|
||||
func TestStepIgnorePrivateRuntime(t *testing.T) {
|
||||
// Tests that Step will ignore calls to private runtime functions
|
||||
// (such as runtime.convT2E in this case)
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
testseq("teststepprog", contStep, []nextTest{
|
||||
{21, 13},
|
||||
{13, 14},
|
||||
@ -2705,7 +2678,7 @@ func TestStacktraceWithBarriers(t *testing.T) {
|
||||
// struct.
|
||||
|
||||
// In Go 1.9 stack barriers have been removed and this test must be disabled.
|
||||
if ver, _ := proc.ParseVersionString(runtime.Version()); ver.Major < 0 || ver.AfterOrEqual(proc.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
if ver, _ := goversion.Parse(runtime.Version()); ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
|
||||
protest "github.com/derekparker/delve/pkg/proc/test"
|
||||
|
||||
"github.com/derekparker/delve/pkg/proc"
|
||||
"github.com/derekparker/delve/pkg/goversion"
|
||||
"github.com/derekparker/delve/service"
|
||||
"github.com/derekparker/delve/service/api"
|
||||
"github.com/derekparker/delve/service/rpc1"
|
||||
@ -240,9 +240,9 @@ func testnext(testcases []nextTest, initialLocation string, t *testing.T) {
|
||||
func Test1NextGeneral(t *testing.T) {
|
||||
var testcases []nextTest
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
testcases = []nextTest{
|
||||
{17, 19},
|
||||
{19, 20},
|
||||
@ -1025,8 +1025,8 @@ func Test1SkipPrologue2(t *testing.T) {
|
||||
|
||||
callme3 := findLocationHelper(t, c, "main.callme3", false, 1, 0)[0]
|
||||
callme3Z := findLocationHelper(t, c, "main.callme3:0", false, 1, 0)[0]
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVer18Beta) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVer18Beta) {
|
||||
findLocationHelper(t, c, "callme.go:19", false, 1, callme3)
|
||||
} else {
|
||||
// callme3 does not have local variables therefore the first line of the
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
|
||||
protest "github.com/derekparker/delve/pkg/proc/test"
|
||||
|
||||
"github.com/derekparker/delve/pkg/proc"
|
||||
"github.com/derekparker/delve/pkg/goversion"
|
||||
"github.com/derekparker/delve/service"
|
||||
"github.com/derekparker/delve/service/api"
|
||||
"github.com/derekparker/delve/service/rpc2"
|
||||
@ -285,9 +285,9 @@ func testnext2(testcases []nextTest, initialLocation string, t *testing.T) {
|
||||
func TestNextGeneral(t *testing.T) {
|
||||
var testcases []nextTest
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
testcases = []nextTest{
|
||||
{17, 19},
|
||||
{19, 20},
|
||||
@ -1099,8 +1099,8 @@ func TestSkipPrologue2(t *testing.T) {
|
||||
|
||||
callme3 := findLocationHelper(t, c, "main.callme3", false, 1, 0)[0]
|
||||
callme3Z := findLocationHelper(t, c, "main.callme3:0", false, 1, 0)[0]
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVer18Beta) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVer18Beta) {
|
||||
findLocationHelper(t, c, "callme.go:19", false, 1, callme3)
|
||||
} else {
|
||||
// callme3 does not have local variables therefore the first line of the
|
||||
@ -1200,8 +1200,8 @@ func TestClientServer_Issue528(t *testing.T) {
|
||||
// Was fixed in go 1.7 // Commit that fixes the issue in go:
|
||||
// f744717d1924340b8f5e5a385e99078693ad9097
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
t.Log("Test skipped")
|
||||
return
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/derekparker/delve/pkg/goversion"
|
||||
"github.com/derekparker/delve/pkg/proc"
|
||||
"github.com/derekparker/delve/pkg/proc/gdbserial"
|
||||
"github.com/derekparker/delve/pkg/proc/native"
|
||||
@ -441,8 +442,8 @@ func TestEmbeddedStruct(t *testing.T) {
|
||||
}
|
||||
assertNoError(proc.Continue(p), t, "Continue()")
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major >= 0 && !ver.AfterOrEqual(proc.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
// on go < 1.9 embedded fields had different names
|
||||
for i := range testcases {
|
||||
if testcases[i].name == "b2" {
|
||||
@ -711,8 +712,8 @@ func TestEvalExpression(t *testing.T) {
|
||||
{"tm", false, "main.truncatedMap {v: []map[string]main.astruct len: 1, cap: 1, [[...]]}", "main.truncatedMap {v: []map[string]main.astruct len: 1, cap: 1, [...]}", "main.truncatedMap", nil},
|
||||
}
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major >= 0 && !ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
for i := range testcases {
|
||||
if testcases[i].name == "iface3" {
|
||||
testcases[i].value = "interface {}(*map[string]go/constant.Value) *[]"
|
||||
@ -836,8 +837,8 @@ func TestIssue426(t *testing.T) {
|
||||
{"anoniface1", `interface { OtherFunction(int, int); SomeFunction(struct { val go/constant.Value }) }`},
|
||||
}
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major < 0 || ver.AfterOrEqual(proc.GoVersion{1, 8, -1, 0, 0, ""}) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{1, 8, -1, 0, 0, ""}) {
|
||||
testcases[2].typ = `struct { main.val go/constant.Value }`
|
||||
testcases[3].typ = `func(struct { main.i int }, interface {}, struct { main.val go/constant.Value })`
|
||||
testcases[4].typ = `struct { main.i int; main.j int }`
|
||||
@ -892,8 +893,8 @@ func TestPackageRenames(t *testing.T) {
|
||||
{"iface2iface", true, `interface {}(*interface { AMethod(int) int; AnotherMethod(int) int }) **github.com/derekparker/delve/_fixtures/vendor/dir0/pkg.SomeType {X: 4}`, "", "interface {}", nil},
|
||||
}
|
||||
|
||||
ver, _ := proc.ParseVersionString(runtime.Version())
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(proc.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
ver, _ := goversion.Parse(runtime.Version())
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 7, -1, 0, 0, ""}) {
|
||||
// Not supported on 1.6 or earlier
|
||||
return
|
||||
}
|
||||
@ -902,7 +903,7 @@ func TestPackageRenames(t *testing.T) {
|
||||
withTestProcess("pkgrenames", t, func(p proc.Process, fixture protest.Fixture) {
|
||||
assertNoError(proc.Continue(p), t, "Continue() returned an error")
|
||||
for _, tc := range testcases {
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(proc.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 9, -1, 0, 0, ""}) {
|
||||
// before 1.9 embedded struct field have fieldname == type
|
||||
if tc.name == "astruct2" {
|
||||
tc.value = `interface {}(*struct { github.com/derekparker/delve/_fixtures/vendor/dir1/pkg.SomeType; X int }) *{github.com/derekparker/delve/_fixtures/vendor/dir1/pkg.SomeType: github.com/derekparker/delve/_fixtures/vendor/dir1/pkg.SomeType {X: 1, Y: 2}, X: 10}`
|
||||
|
Loading…
Reference in New Issue
Block a user