Fix crashes on Go dev.typeparams (soon to be Go main branch) (#2627)
* proc: Go 1.18 removes the _defer.siz field As of Go 1.17, the _defer.siz field is always 0 because _defer no longer stores defer call arguments at all. golang.org/cl/326062 removes it entirely for Go 1.18. Simply treat it as 0 if the field is missing from the _defer type. * proc: Go 1.18 changes _defer.fn from *funcval to func() golang.org/cl/325918 changed the type of the _defer.fn field from *funcval to func() for Go 1.18. This CL was later reverted because it caused failures in Delve, but we would like to un-revert it. Handle this change by inspecting the type of this field before decoding it.
This commit is contained in:
parent
cb73ef8f83
commit
a2b839990e
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/dwarf/frame"
|
"github.com/go-delve/delve/pkg/dwarf/frame"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||||
@ -519,11 +520,11 @@ func (it *stackIterator) loadG0SchedSP() {
|
|||||||
|
|
||||||
// Defer represents one deferred call
|
// Defer represents one deferred call
|
||||||
type Defer struct {
|
type Defer struct {
|
||||||
DwrapPC uint64 // Value of field _defer.fn.fn, the deferred function or a wrapper to it in Go 1.17 or later
|
DwrapPC uint64 // PC of the deferred function or, in Go 1.17+ a wrapper to it
|
||||||
DeferPC uint64 // PC address of instruction that added this defer
|
DeferPC uint64 // PC address of instruction that added this defer
|
||||||
SP uint64 // Value of SP register when this function was deferred (this field gets adjusted when the stack is moved to match the new stack space)
|
SP uint64 // Value of SP register when this function was deferred (this field gets adjusted when the stack is moved to match the new stack space)
|
||||||
link *Defer // Next deferred function
|
link *Defer // Next deferred function
|
||||||
argSz int64
|
argSz int64 // Always 0 in Go >=1.17
|
||||||
|
|
||||||
variable *Variable
|
variable *Variable
|
||||||
Unreadable error
|
Unreadable error
|
||||||
@ -580,8 +581,12 @@ func (d *Defer) load() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fnvar := d.variable.fieldVariable("fn").maybeDereference()
|
fnvar := d.variable.fieldVariable("fn")
|
||||||
if fnvar.Addr != 0 {
|
if fnvar.Kind == reflect.Func {
|
||||||
|
// In Go 1.18, fn is a func().
|
||||||
|
d.DwrapPC = fnvar.Base
|
||||||
|
} else if val := fnvar.maybeDereference(); val.Addr != 0 {
|
||||||
|
// In Go <1.18, fn is a *funcval.
|
||||||
fnvar = fnvar.loadFieldNamed("fn")
|
fnvar = fnvar.loadFieldNamed("fn")
|
||||||
if fnvar.Unreadable == nil {
|
if fnvar.Unreadable == nil {
|
||||||
d.DwrapPC, _ = constant.Uint64Val(fnvar.Value)
|
d.DwrapPC, _ = constant.Uint64Val(fnvar.Value)
|
||||||
@ -590,7 +595,14 @@ func (d *Defer) load() {
|
|||||||
|
|
||||||
d.DeferPC, _ = constant.Uint64Val(d.variable.fieldVariable("pc").Value)
|
d.DeferPC, _ = constant.Uint64Val(d.variable.fieldVariable("pc").Value)
|
||||||
d.SP, _ = constant.Uint64Val(d.variable.fieldVariable("sp").Value)
|
d.SP, _ = constant.Uint64Val(d.variable.fieldVariable("sp").Value)
|
||||||
d.argSz, _ = constant.Int64Val(d.variable.fieldVariable("siz").Value)
|
sizVar := d.variable.fieldVariable("siz")
|
||||||
|
if sizVar != nil {
|
||||||
|
// In Go <1.18, siz stores the number of bytes of
|
||||||
|
// defer arguments following the defer record. In Go
|
||||||
|
// 1.18, the defer record doesn't store arguments, so
|
||||||
|
// we leave this 0.
|
||||||
|
d.argSz, _ = constant.Int64Val(sizVar.Value)
|
||||||
|
}
|
||||||
|
|
||||||
linkvar := d.variable.fieldVariable("link").maybeDereference()
|
linkvar := d.variable.fieldVariable("link").maybeDereference()
|
||||||
if linkvar.Addr != 0 {
|
if linkvar.Addr != 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user