diff --git a/pkg/proc/variable_test.go b/pkg/proc/variable_test.go new file mode 100644 index 0000000000000000000000000000000000000000..892ed096a03cdd6ec16ff62b83ceddd67182dc0a --- /dev/null +++ b/pkg/proc/variable_test.go @@ -0,0 +1,45 @@ +package proc_test + +import ( + "path/filepath" + "testing" + + "github.com/derekparker/delve/pkg/proc" + protest "github.com/derekparker/delve/pkg/proc/test" +) + +func TestGoroutineCreationLocation(t *testing.T) { + protest.AllowRecording(t) + withTestProcess("goroutinestackprog", t, func(p proc.Process, fixture protest.Fixture) { + bp, err := setFunctionBreakpoint(p, "main.agoroutine") + assertNoError(err, t, "BreakByLocation()") + assertNoError(proc.Continue(p), t, "Continue()") + + gs, err := proc.GoroutinesInfo(p) + assertNoError(err, t, "GoroutinesInfo") + + for _, g := range gs { + currentLocation := g.UserCurrent() + currentFn := currentLocation.Fn + if currentFn != nil && currentFn.BaseName() == "agoroutine" { + createdLocation := g.Go() + if createdLocation.Fn == nil { + t.Fatalf("goroutine creation function is nil") + } + if createdLocation.Fn.BaseName() != "main" { + t.Fatalf("goroutine creation function has wrong name: %s", createdLocation.Fn.BaseName()) + } + if filepath.Base(createdLocation.File) != "goroutinestackprog.go" { + t.Fatalf("goroutine creation file incorrect: %s", filepath.Base(createdLocation.File)) + } + if createdLocation.Line != 20 { + t.Fatalf("goroutine creation line incorrect: %v", createdLocation.Line) + } + } + + } + + p.ClearBreakpoint(bp.Addr) + proc.Continue(p) + }) +} diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index ac3298dab1d2f355c79625ba20ff8a10d6019cb8..f5c164b3a5862d0501853be0688c63a86b673c59 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -526,7 +526,14 @@ func (g *G) UserCurrent() Location { // Go returns the location of the 'go' statement // that spawned this goroutine. func (g *G) Go() Location { - f, l, fn := g.variable.bi.PCToLine(g.GoPC) + pc := g.GoPC + fn := g.variable.bi.PCToFunc(pc) + // Backup to CALL instruction. + // Mimics runtime/traceback.go:677. + if g.GoPC > fn.Entry { + pc -= 1 + } + f, l, fn := g.variable.bi.PCToLine(pc) return Location{PC: g.GoPC, File: f, Line: l, Fn: fn} }