diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 2814e09c..82ffdcd5 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -2489,14 +2489,16 @@ func TestStacktraceWithBarriers(t *testing.T) { // The original return address is saved into the stkbar slice inside the G // struct. + // In Go 1.9 stack barriers have been removed and this test must be disabled. + if ver, _ := ParseVersionString(runtime.Version()); ver.Major < 0 || ver.AfterOrEqual(GoVersion{1, 9, -1, 0, 0}) { + return + } + // In Go 1.8 stack barriers are not inserted by default, this enables them. godebugOld := os.Getenv("GODEBUG") defer os.Setenv("GODEBUG", godebugOld) os.Setenv("GODEBUG", "gcrescanstacks=1") - // TODO(aarzilli): in Go 1.9 stack barriers will be removed completely, therefore - // this test will have to be disabled - withTestProcess("binarytrees", t, func(p *Process, fixture protest.Fixture) { // We want to get a user goroutine with a stack barrier, to get that we execute the program until runtime.gcInstallStackBarrier is executed AND the goroutine it was executed onto contains a call to main.bottomUpTree _, err := setFunctionBreakpoint(p, "runtime.gcInstallStackBarrier") diff --git a/pkg/proc/stack.go b/pkg/proc/stack.go index 096cf7a2..df5cd671 100644 --- a/pkg/proc/stack.go +++ b/pkg/proc/stack.go @@ -130,8 +130,10 @@ type savedLR struct { } func newStackIterator(dbp *Process, pc, sp, bp uint64, stkbar []savedLR, stkbarPos int) *stackIterator { - stackBarrierPC := dbp.goSymTable.LookupFunc(runtimeStackBarrier).Entry - if stkbar != nil { + stackBarrierFunc := dbp.goSymTable.LookupFunc(runtimeStackBarrier) // stack barriers were removed in Go 1.9 + var stackBarrierPC uint64 + if stackBarrierFunc != nil && stkbar != nil { + stackBarrierPC = stackBarrierFunc.Entry fn := dbp.goSymTable.PCToFunc(pc) if fn != nil && fn.Name == runtimeStackBarrier { // We caught the goroutine as it's executing the stack barrier, we must diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index e9d8e899..f243d045 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -396,8 +396,14 @@ func (gvar *Variable) parseG() (*G, error) { id, _ := constant.Int64Val(gvar.fieldVariable("goid").Value) gopc, _ := constant.Int64Val(gvar.fieldVariable("gopc").Value) waitReason := constant.StringVal(gvar.fieldVariable("waitreason").Value) + stkbarVar, _ := gvar.structMember("stkbar") - stkbarPos, _ := constant.Int64Val(gvar.fieldVariable("stkbarPos").Value) + stkbarVarPosFld := gvar.fieldVariable("stkbarPos") + var stkbarPos int64 + if stkbarVarPosFld != nil { // stack barriers were removed in Go 1.9 + stkbarPos, _ = constant.Int64Val(stkbarVarPosFld.Value) + } + status, _ := constant.Int64Val(gvar.fieldVariable("atomicstatus").Value) f, l, fn := gvar.dbp.goSymTable.PCToLine(uint64(pc)) g := &G{ @@ -498,6 +504,9 @@ func (g *G) Go() Location { // Returns the list of saved return addresses used by stack barriers func (g *G) stkbar() ([]savedLR, error) { + if g.stkbarVar == nil { // stack barriers were removed in Go 1.9 + return nil, nil + } g.stkbarVar.loadValue(LoadConfig{false, 1, 0, int(g.stkbarVar.Len), 3}) if g.stkbarVar.Unreadable != nil { return nil, fmt.Errorf("unreadable stkbar: %v\n", g.stkbarVar.Unreadable)