mirror of
https://github.com/go-delve/delve.git
synced 2025-11-02 12:59:01 +08:00
pkg/proc: tolerate absence of stack barriers in Go 1.9 (#762)
Stack barriers were removed in Go 1.9, and thus code that expected various stack-barrier-related symbols to exist does not find them. Check for their absence and do not crash when they are missing. Disable stack-barrier-handling test for 1.9 and beyond. Fixes #754.
This commit is contained in:
@ -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")
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
Reference in New Issue
Block a user