From e19cbcefa9f14ea2d57656153245ca37d83cb676 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 20 Jun 2018 10:06:12 +0200 Subject: [PATCH] proc,command: fix optimized function warning in 1.9 A user complained on the mailing list about having continuous "optimized function warnings" on non-optimized functions when using 1.9. This commit fixes the problem by disabling optimized function detection on 1.9 and earlier (where it's impossible) and adds a test so we don't break it again in the future. --- pkg/proc/proc_test.go | 18 ++++++++++++++++++ pkg/proc/test/support.go | 11 ++++++++--- pkg/proc/types.go | 5 +++-- pkg/terminal/command_test.go | 28 +++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index c4cccaa2..07499387 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -3844,3 +3844,21 @@ func TestStepOutReturn(t *testing.T) { } }) } + +func TestOptimizationCheck(t *testing.T) { + withTestProcess("continuetestprog", t, func(p proc.Process, fixture protest.Fixture) { + fn := p.BinInfo().LookupFunc["main.main"] + if fn.Optimized() { + t.Fatalf("main.main is optimized") + } + }) + + if goversion.VersionAfterOrEqual(runtime.Version(), 1, 10) { + withTestProcessArgs("continuetestprog", t, ".", []string{}, protest.EnableOptimization|protest.EnableInlining, func(p proc.Process, fixture protest.Fixture) { + fn := p.BinInfo().LookupFunc["main.main"] + if !fn.Optimized() { + t.Fatalf("main.main is not optimized") + } + }) + } +} diff --git a/pkg/proc/test/support.go b/pkg/proc/test/support.go index bf095d87..0d2bf858 100644 --- a/pkg/proc/test/support.go +++ b/pkg/proc/test/support.go @@ -56,6 +56,7 @@ const ( LinkStrip BuildFlags = 1 << iota EnableCGOOptimization EnableInlining + EnableOptimization EnableDWZCompression ) @@ -94,10 +95,14 @@ func BuildFixture(name string, flags BuildFlags) Fixture { if flags&LinkStrip != 0 { buildFlags = append(buildFlags, "-ldflags=-s") } - gcflags := "-gcflags=-N -l" - if flags&EnableInlining != 0 { - gcflags = "-gcflags=-N" + gcflagsv := []string{} + if flags&EnableInlining == 0 { + gcflagsv = append(gcflagsv, "-l") } + if flags&EnableOptimization == 0 { + gcflagsv = append(gcflagsv, "-N") + } + gcflags := "-gcflags=" + strings.Join(gcflagsv, " ") buildFlags = append(buildFlags, gcflags, "-o", tmpfile) if *EnableRace { buildFlags = append(buildFlags, "-race") diff --git a/pkg/proc/types.go b/pkg/proc/types.go index 2c23ed35..d9b41f11 100644 --- a/pkg/proc/types.go +++ b/pkg/proc/types.go @@ -22,6 +22,7 @@ import ( "github.com/derekparker/delve/pkg/dwarf/line" "github.com/derekparker/delve/pkg/dwarf/op" "github.com/derekparker/delve/pkg/dwarf/reader" + "github.com/derekparker/delve/pkg/goversion" "github.com/derekparker/delve/pkg/logflags" ) @@ -223,10 +224,10 @@ func (bi *BinaryInfo) loadDebugInfoMaps(debugLineBytes []byte, wg *sync.WaitGrou cu.lineInfo.LogSuppressedErrors(logflags.DebugLineErrors()) } cu.producer, _ = entry.Val(dwarf.AttrProducer).(string) - if cu.isgo { + if cu.isgo && cu.producer != "" { semicolon := strings.Index(cu.producer, ";") if semicolon < 0 { - cu.optimized = true + cu.optimized = goversion.ProducerAfterOrEqual(cu.producer, 1, 10) } else { cu.optimized = !strings.Contains(cu.producer[semicolon:], "-N") || !strings.Contains(cu.producer[semicolon:], "-l") cu.producer = cu.producer[:semicolon] diff --git a/pkg/terminal/command_test.go b/pkg/terminal/command_test.go index 6e09db59..40b742d0 100644 --- a/pkg/terminal/command_test.go +++ b/pkg/terminal/command_test.go @@ -96,6 +96,10 @@ func (ft *FakeTerminal) AssertExecError(cmdstr, tgterr string) { } func withTestTerminal(name string, t testing.TB, fn func(*FakeTerminal)) { + withTestTerminalBuildFlags(name, t, 0, fn) +} + +func withTestTerminalBuildFlags(name string, t testing.TB, buildFlags test.BuildFlags, fn func(*FakeTerminal)) { if testBackend == "rr" { test.MustHaveRecordingAllowed(t) } @@ -107,7 +111,7 @@ func withTestTerminal(name string, t testing.TB, fn func(*FakeTerminal)) { defer listener.Close() server := rpccommon.NewServer(&service.Config{ Listener: listener, - ProcessArgs: []string{test.BuildFixture(name, 0).Path}, + ProcessArgs: []string{test.BuildFixture(name, buildFlags).Path}, Backend: testBackend, }, false) if err := server.Run(); err != nil { @@ -801,3 +805,25 @@ func TestStepOutReturn(t *testing.T) { } }) } + +func TestOptimizationCheck(t *testing.T) { + withTestTerminal("continuetestprog", t, func(term *FakeTerminal) { + term.MustExec("break main.main") + out := term.MustExec("continue") + t.Logf("output %q", out) + if strings.Contains(out, optimizedFunctionWarning) { + t.Fatal("optimized function warning") + } + }) + + if goversion.VersionAfterOrEqual(runtime.Version(), 1, 10) { + withTestTerminalBuildFlags("continuetestprog", t, test.EnableOptimization|test.EnableInlining, func(term *FakeTerminal) { + term.MustExec("break main.main") + out := term.MustExec("continue") + t.Logf("output %q", out) + if !strings.Contains(out, optimizedFunctionWarning) { + t.Fatal("optimized function warning missing") + } + }) + } +}