mirror of
https://github.com/go-delve/delve.git
synced 2025-11-01 12:01:35 +08:00
proc: fill bi member of constants (#4026)
Fill the bi field of constant variables when we create them. This is meant to address #4021 which is caused by trying to access a member field of a variable with a nil bi. I couldn't find a way to make a constant reach that point into the code but this still looks like the most likely explanation. Fixes #4021
This commit is contained in:
committed by
GitHub
parent
2ac3573b74
commit
99ec109dd3
@ -1014,11 +1014,11 @@ func (rbpi *returnBreakpointInfo) Collect(t *Target, thread Thread) []*Variable
|
||||
|
||||
g, err := GetG(thread)
|
||||
if err != nil {
|
||||
return returnInfoError("could not get g", err, thread.ProcessMemory())
|
||||
return returnInfoError("could not get g", err, thread.BinInfo(), thread.ProcessMemory())
|
||||
}
|
||||
scope, err := GoroutineScope(t, thread)
|
||||
if err != nil {
|
||||
return returnInfoError("could not get scope", err, thread.ProcessMemory())
|
||||
return returnInfoError("could not get scope", err, thread.BinInfo(), thread.ProcessMemory())
|
||||
}
|
||||
v, err := scope.evalAST(rbpi.retFrameCond)
|
||||
if err != nil || v.Unreadable != nil || v.Kind != reflect.Bool {
|
||||
@ -1036,12 +1036,12 @@ func (rbpi *returnBreakpointInfo) Collect(t *Target, thread Thread) []*Variable
|
||||
oldSP := uint64(rbpi.spOffset + int64(g.stack.hi))
|
||||
err = fakeFunctionEntryScope(scope, rbpi.fn, oldFrameOffset, oldSP)
|
||||
if err != nil {
|
||||
return returnInfoError("could not read function entry", err, thread.ProcessMemory())
|
||||
return returnInfoError("could not read function entry", err, thread.BinInfo(), thread.ProcessMemory())
|
||||
}
|
||||
|
||||
vars, err := scope.Locals(0, "")
|
||||
if err != nil {
|
||||
return returnInfoError("could not evaluate return variables", err, thread.ProcessMemory())
|
||||
return returnInfoError("could not evaluate return variables", err, thread.BinInfo(), thread.ProcessMemory())
|
||||
}
|
||||
vars = filterVariables(vars, func(v *Variable) bool {
|
||||
return (v.Flags & VariableReturnArgument) != 0
|
||||
@ -1050,8 +1050,8 @@ func (rbpi *returnBreakpointInfo) Collect(t *Target, thread Thread) []*Variable
|
||||
return vars
|
||||
}
|
||||
|
||||
func returnInfoError(descr string, err error, mem MemoryReadWriter) []*Variable {
|
||||
v := newConstant(constant.MakeString(fmt.Sprintf("%s: %v", descr, err.Error())), mem)
|
||||
func returnInfoError(descr string, err error, bi *BinaryInfo, mem MemoryReadWriter) []*Variable {
|
||||
v := newConstant(constant.MakeString(fmt.Sprintf("%s: %v", descr, err.Error())), bi, mem)
|
||||
v.Name = "return value read error"
|
||||
return []*Variable{v}
|
||||
}
|
||||
|
||||
@ -1068,29 +1068,29 @@ func (stack *evalStack) executeOp() {
|
||||
gvar := newVariable("curg", fakeAddressUnresolv, typ, scope.BinInfo, scope.Mem)
|
||||
gvar.loaded = true
|
||||
gvar.Flags = VariableFakeAddress
|
||||
gvar.Children = append(gvar.Children, *newConstant(constant.MakeInt64(0), scope.Mem))
|
||||
gvar.Children = append(gvar.Children, *newConstant(constant.MakeInt64(0), scope.BinInfo, scope.Mem))
|
||||
gvar.Children[0].Name = "goid"
|
||||
stack.push(gvar)
|
||||
}
|
||||
|
||||
case *evalop.PushFrameoff:
|
||||
stack.push(newConstant(constant.MakeInt64(scope.frameOffset), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeInt64(scope.frameOffset), scope.BinInfo, scope.Mem))
|
||||
|
||||
case *evalop.PushRangeParentOffset:
|
||||
if scope.rangeFrames == nil {
|
||||
stack.err = scope.setupRangeFrames()
|
||||
}
|
||||
if len(scope.rangeFrames) > 0 {
|
||||
stack.push(newConstant(constant.MakeInt64(scope.rangeFrames[len(scope.rangeFrames)-2].FrameOffset()), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeInt64(scope.rangeFrames[len(scope.rangeFrames)-2].FrameOffset()), scope.BinInfo, scope.Mem))
|
||||
} else {
|
||||
stack.push(newConstant(constant.MakeInt64(0), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeInt64(0), scope.BinInfo, scope.Mem))
|
||||
}
|
||||
|
||||
case *evalop.PushThreadID:
|
||||
stack.push(newConstant(constant.MakeInt64(int64(scope.threadID)), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeInt64(int64(scope.threadID)), scope.BinInfo, scope.Mem))
|
||||
|
||||
case *evalop.PushConst:
|
||||
stack.push(newConstant(op.Value, scope.Mem))
|
||||
stack.push(newConstant(op.Value, scope.BinInfo, scope.Mem))
|
||||
|
||||
case *evalop.PushLocal:
|
||||
found := stack.pushLocal(scope, op.Name, op.Frame)
|
||||
@ -1133,7 +1133,7 @@ func (stack *evalStack) executeOp() {
|
||||
|
||||
case *evalop.PushLen:
|
||||
v := stack.peek()
|
||||
stack.push(newConstant(constant.MakeInt64(v.Len), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeInt64(v.Len), scope.BinInfo, scope.Mem))
|
||||
|
||||
case *evalop.Select:
|
||||
scope.evalStructSelector(op, stack)
|
||||
@ -1172,7 +1172,7 @@ func (stack *evalStack) executeOp() {
|
||||
return
|
||||
}
|
||||
x.loadValue(loadFullValue)
|
||||
stack.push(newConstant(x.Value, scope.Mem))
|
||||
stack.push(newConstant(x.Value, scope.BinInfo, scope.Mem))
|
||||
|
||||
case *evalop.Pop:
|
||||
stack.pop()
|
||||
@ -1335,7 +1335,7 @@ func (stack *evalStack) pushIdent(scope *EvalScope, name string) (found bool) {
|
||||
|
||||
switch name {
|
||||
case "true", "false":
|
||||
stack.push(newConstant(constant.MakeBool(name == "true"), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeBool(name == "true"), scope.BinInfo, scope.Mem))
|
||||
return true
|
||||
case "nil":
|
||||
stack.push(nilVariable)
|
||||
@ -1846,18 +1846,18 @@ func capBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) {
|
||||
}
|
||||
fallthrough
|
||||
case reflect.Array:
|
||||
return newConstant(constant.MakeInt64(arg.Len), arg.mem), nil
|
||||
return newConstant(constant.MakeInt64(arg.Len), arg.bi, arg.mem), nil
|
||||
case reflect.Slice:
|
||||
return newConstant(constant.MakeInt64(arg.Cap), arg.mem), nil
|
||||
return newConstant(constant.MakeInt64(arg.Cap), arg.bi, arg.mem), nil
|
||||
case reflect.Chan:
|
||||
arg.loadValue(loadFullValue)
|
||||
if arg.Unreadable != nil {
|
||||
return nil, arg.Unreadable
|
||||
}
|
||||
if arg.Base == 0 {
|
||||
return newConstant(constant.MakeInt64(0), arg.mem), nil
|
||||
return newConstant(constant.MakeInt64(0), arg.bi, arg.mem), nil
|
||||
}
|
||||
return newConstant(arg.Children[1].Value, arg.mem), nil
|
||||
return newConstant(arg.Children[1].Value, arg.bi, arg.mem), nil
|
||||
default:
|
||||
return nil, invalidArgErr
|
||||
}
|
||||
@ -1881,25 +1881,25 @@ func lenBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) {
|
||||
if arg.Unreadable != nil {
|
||||
return nil, arg.Unreadable
|
||||
}
|
||||
return newConstant(constant.MakeInt64(arg.Len), arg.mem), nil
|
||||
return newConstant(constant.MakeInt64(arg.Len), arg.bi, arg.mem), nil
|
||||
case reflect.Chan:
|
||||
arg.loadValue(loadFullValue)
|
||||
if arg.Unreadable != nil {
|
||||
return nil, arg.Unreadable
|
||||
}
|
||||
if arg.Base == 0 {
|
||||
return newConstant(constant.MakeInt64(0), arg.mem), nil
|
||||
return newConstant(constant.MakeInt64(0), arg.bi, arg.mem), nil
|
||||
}
|
||||
return newConstant(arg.Children[0].Value, arg.mem), nil
|
||||
return newConstant(arg.Children[0].Value, arg.bi, arg.mem), nil
|
||||
case reflect.Map:
|
||||
it := arg.mapIterator(0)
|
||||
if arg.Unreadable != nil {
|
||||
return nil, arg.Unreadable
|
||||
}
|
||||
if it == nil {
|
||||
return newConstant(constant.MakeInt64(0), arg.mem), nil
|
||||
return newConstant(constant.MakeInt64(0), arg.bi, arg.mem), nil
|
||||
}
|
||||
return newConstant(constant.MakeInt64(arg.Len), arg.mem), nil
|
||||
return newConstant(constant.MakeInt64(arg.Len), arg.bi, arg.mem), nil
|
||||
default:
|
||||
return nil, invalidArgErr
|
||||
}
|
||||
@ -1970,7 +1970,7 @@ func imagBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) {
|
||||
return nil, fmt.Errorf("invalid argument %s (type %s) to imag", astutil.ExprToString(nodeargs[0]), arg.TypeString())
|
||||
}
|
||||
|
||||
return newConstant(constant.Imag(arg.Value), arg.mem), nil
|
||||
return newConstant(constant.Imag(arg.Value), arg.bi, arg.mem), nil
|
||||
}
|
||||
|
||||
func realBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) {
|
||||
@ -1989,7 +1989,7 @@ func realBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) {
|
||||
return nil, fmt.Errorf("invalid argument %s (type %s) to real", astutil.ExprToString(nodeargs[0]), arg.TypeString())
|
||||
}
|
||||
|
||||
return newConstant(constant.Real(arg.Value), arg.mem), nil
|
||||
return newConstant(constant.Real(arg.Value), arg.bi, arg.mem), nil
|
||||
}
|
||||
|
||||
func minBuiltin(args []*Variable, nodeargs []ast.Expr) (*Variable, error) {
|
||||
@ -2121,7 +2121,7 @@ func (scope *EvalScope) evalIndex(op *evalop.Index, stack *evalStack) {
|
||||
s := constant.StringVal(idxev.Value)
|
||||
thc, err := totalHitCountByName(scope.target.Breakpoints().Logical, s)
|
||||
if err == nil {
|
||||
stack.push(newConstant(constant.MakeUint64(thc), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeUint64(thc), scope.BinInfo, scope.Mem))
|
||||
}
|
||||
stack.err = err
|
||||
return
|
||||
@ -2137,7 +2137,7 @@ func (scope *EvalScope) evalIndex(op *evalop.Index, stack *evalStack) {
|
||||
}
|
||||
thc, err := totalHitCountByID(scope.target.Breakpoints().Logical, int(n))
|
||||
if err == nil {
|
||||
stack.push(newConstant(constant.MakeUint64(thc), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeUint64(thc), scope.BinInfo, scope.Mem))
|
||||
}
|
||||
stack.err = err
|
||||
return
|
||||
@ -2371,7 +2371,7 @@ func (scope *EvalScope) evalUnary(op *evalop.Unary, stack *evalStack) {
|
||||
stack.push(r)
|
||||
return
|
||||
}
|
||||
stack.push(newConstant(rc, xv.mem))
|
||||
stack.push(newConstant(rc, xv.bi, xv.mem))
|
||||
}
|
||||
|
||||
func negotiateType(op token.Token, xv, yv *Variable) (godwarf.Type, error) {
|
||||
@ -2502,7 +2502,7 @@ func (scope *EvalScope) evalBinary(binop *evalop.Binary, stack *evalStack) {
|
||||
stack.err = err
|
||||
return
|
||||
}
|
||||
stack.push(newConstant(constant.MakeBool(v), xv.mem))
|
||||
stack.push(newConstant(constant.MakeBool(v), xv.bi, xv.mem))
|
||||
|
||||
default:
|
||||
if xv.Kind == reflect.String {
|
||||
@ -2528,7 +2528,7 @@ func (scope *EvalScope) evalBinary(binop *evalop.Binary, stack *evalStack) {
|
||||
}
|
||||
|
||||
if typ == nil {
|
||||
stack.push(newConstant(rc, xv.mem))
|
||||
stack.push(newConstant(rc, xv.bi, xv.mem))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -390,7 +390,7 @@ func (scope *EvalScope) evalCallInjectionStart(op *evalop.CallInjectionStart, st
|
||||
p.fncallForG[scope.g.ID].startThreadID = thread.ThreadID()
|
||||
|
||||
stack.fncallPush(&fncall)
|
||||
stack.push(newConstant(constant.MakeBool(!fncall.hasDebugPinner && (fncall.fn == nil || fncall.receiver != nil || fncall.closureAddr != 0)), scope.Mem))
|
||||
stack.push(newConstant(constant.MakeBool(!fncall.hasDebugPinner && (fncall.fn == nil || fncall.receiver != nil || fncall.closureAddr != 0)), scope.BinInfo, scope.Mem))
|
||||
stack.callInjectionContinue = true
|
||||
}
|
||||
|
||||
|
||||
@ -356,7 +356,7 @@ func setAsyncPreemptOff(p *Target, v int64) {
|
||||
p.asyncPreemptChanged = true
|
||||
p.asyncPreemptOff, _ = constant.Int64Val(asyncpreemptoffv.Value)
|
||||
|
||||
err = scope.setValue(asyncpreemptoffv, newConstant(constant.MakeInt64(v), scope.Mem), "")
|
||||
err = scope.setValue(asyncpreemptoffv, newConstant(constant.MakeInt64(v), scope.BinInfo, scope.Mem), "")
|
||||
if err != nil {
|
||||
logger.Warnf("could not set asyncpreemptoff %v", err)
|
||||
}
|
||||
|
||||
@ -776,8 +776,8 @@ func newVariable(name string, addr uint64, dwarfType godwarf.Type, bi *BinaryInf
|
||||
|
||||
var constantMaxInt64 = constant.MakeInt64(1<<63 - 1)
|
||||
|
||||
func newConstant(val constant.Value, mem MemoryReadWriter) *Variable {
|
||||
v := &Variable{Value: val, mem: mem, loaded: true}
|
||||
func newConstant(val constant.Value, bi *BinaryInfo, mem MemoryReadWriter) *Variable {
|
||||
v := &Variable{Value: val, mem: mem, loaded: true, bi: bi}
|
||||
switch val.Kind() {
|
||||
case constant.Int:
|
||||
v.Kind = reflect.Int
|
||||
@ -2197,47 +2197,47 @@ func (v *Variable) registerVariableTypeConv(newtyp string) (*Variable, error) {
|
||||
var child *Variable
|
||||
switch newtyp {
|
||||
case "int8":
|
||||
child = newConstant(constant.MakeInt64(int64(int8(v.reg.Bytes[i]))), v.mem)
|
||||
child = newConstant(constant.MakeInt64(int64(int8(v.reg.Bytes[i]))), v.bi, v.mem)
|
||||
child.Kind = reflect.Int8
|
||||
n = 1
|
||||
case "int16":
|
||||
child = newConstant(constant.MakeInt64(int64(int16(binary.LittleEndian.Uint16(v.reg.Bytes[i:])))), v.mem)
|
||||
child = newConstant(constant.MakeInt64(int64(int16(binary.LittleEndian.Uint16(v.reg.Bytes[i:])))), v.bi, v.mem)
|
||||
child.Kind = reflect.Int16
|
||||
n = 2
|
||||
case "int32":
|
||||
child = newConstant(constant.MakeInt64(int64(int32(binary.LittleEndian.Uint32(v.reg.Bytes[i:])))), v.mem)
|
||||
child = newConstant(constant.MakeInt64(int64(int32(binary.LittleEndian.Uint32(v.reg.Bytes[i:])))), v.bi, v.mem)
|
||||
child.Kind = reflect.Int32
|
||||
n = 4
|
||||
case "int64":
|
||||
child = newConstant(constant.MakeInt64(int64(binary.LittleEndian.Uint64(v.reg.Bytes[i:]))), v.mem)
|
||||
child = newConstant(constant.MakeInt64(int64(binary.LittleEndian.Uint64(v.reg.Bytes[i:]))), v.bi, v.mem)
|
||||
child.Kind = reflect.Int64
|
||||
n = 8
|
||||
case "uint8":
|
||||
child = newConstant(constant.MakeUint64(uint64(v.reg.Bytes[i])), v.mem)
|
||||
child = newConstant(constant.MakeUint64(uint64(v.reg.Bytes[i])), v.bi, v.mem)
|
||||
child.Kind = reflect.Uint8
|
||||
n = 1
|
||||
case "uint16":
|
||||
child = newConstant(constant.MakeUint64(uint64(binary.LittleEndian.Uint16(v.reg.Bytes[i:]))), v.mem)
|
||||
child = newConstant(constant.MakeUint64(uint64(binary.LittleEndian.Uint16(v.reg.Bytes[i:]))), v.bi, v.mem)
|
||||
child.Kind = reflect.Uint16
|
||||
n = 2
|
||||
case "uint32":
|
||||
child = newConstant(constant.MakeUint64(uint64(binary.LittleEndian.Uint32(v.reg.Bytes[i:]))), v.mem)
|
||||
child = newConstant(constant.MakeUint64(uint64(binary.LittleEndian.Uint32(v.reg.Bytes[i:]))), v.bi, v.mem)
|
||||
child.Kind = reflect.Uint32
|
||||
n = 4
|
||||
case "uint64":
|
||||
child = newConstant(constant.MakeUint64(binary.LittleEndian.Uint64(v.reg.Bytes[i:])), v.mem)
|
||||
child = newConstant(constant.MakeUint64(binary.LittleEndian.Uint64(v.reg.Bytes[i:])), v.bi, v.mem)
|
||||
child.Kind = reflect.Uint64
|
||||
n = 8
|
||||
case "float32":
|
||||
a := binary.LittleEndian.Uint32(v.reg.Bytes[i:])
|
||||
x := *(*float32)(unsafe.Pointer(&a))
|
||||
child = newConstant(constant.MakeFloat64(float64(x)), v.mem)
|
||||
child = newConstant(constant.MakeFloat64(float64(x)), v.bi, v.mem)
|
||||
child.Kind = reflect.Float32
|
||||
n = 4
|
||||
case "float64":
|
||||
a := binary.LittleEndian.Uint64(v.reg.Bytes[i:])
|
||||
x := *(*float64)(unsafe.Pointer(&a))
|
||||
child = newConstant(constant.MakeFloat64(x), v.mem)
|
||||
child = newConstant(constant.MakeFloat64(x), v.bi, v.mem)
|
||||
child.Kind = reflect.Float64
|
||||
n = 8
|
||||
default:
|
||||
@ -2253,7 +2253,7 @@ func (v *Variable) registerVariableTypeConv(newtyp string) (*Variable, error) {
|
||||
}
|
||||
n = n / 8
|
||||
}
|
||||
child = newConstant(constant.MakeString(fmt.Sprintf("%x", v.reg.Bytes[i:][:n])), v.mem)
|
||||
child = newConstant(constant.MakeString(fmt.Sprintf("%x", v.reg.Bytes[i:][:n])), v.bi, v.mem)
|
||||
}
|
||||
v.Children = append(v.Children, *child)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user