mirror of
https://github.com/go-delve/delve.git
synced 2025-10-28 04:35:19 +08:00
proc: simplify next/step/stepout condition code
Adds a library of utility functions to generated breakpoint conditions for next, step and stepout.
This commit is contained in:
40
pkg/astutil/astutil.go
Normal file
40
pkg/astutil/astutil.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// This package contains utility functions used by pkg/proc to generate
|
||||||
|
// ast.Expr expressions.
|
||||||
|
|
||||||
|
package astutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Eql returns an expression evaluating 'x == y'.
|
||||||
|
func Eql(x, y ast.Expr) *ast.BinaryExpr {
|
||||||
|
return &ast.BinaryExpr{Op: token.EQL, X: x, Y: y}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sel returns an expression evaluating 'x.sel'.
|
||||||
|
func Sel(x ast.Expr, sel string) *ast.SelectorExpr {
|
||||||
|
return &ast.SelectorExpr{X: x, Sel: &ast.Ident{Name: sel}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PkgVar returns an expression evaluating 'pkg.v'.
|
||||||
|
func PkgVar(pkg, v string) *ast.SelectorExpr {
|
||||||
|
return &ast.SelectorExpr{X: &ast.Ident{Name: pkg}, Sel: &ast.Ident{Name: v}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int returns an expression representing the integer 'n'.
|
||||||
|
func Int(n int64) *ast.BasicLit {
|
||||||
|
return &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(n, 10)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// And returns an expression evaluating 'x && y'.
|
||||||
|
func And(x, y ast.Expr) *ast.BinaryExpr {
|
||||||
|
return &ast.BinaryExpr{Op: token.LAND, X: x, Y: y}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns an expression evaluating 'x || y'.
|
||||||
|
func Or(x, y ast.Expr) *ast.BinaryExpr {
|
||||||
|
return &ast.BinaryExpr{Op: token.LOR, X: x, Y: y}
|
||||||
|
}
|
||||||
@ -7,8 +7,8 @@ import (
|
|||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/astutil"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/reader"
|
"github.com/go-delve/delve/pkg/dwarf/reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -289,39 +289,11 @@ func sameGoroutineCondition(g *G) ast.Expr {
|
|||||||
if g == nil {
|
if g == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &ast.BinaryExpr{
|
return astutil.Eql(astutil.Sel(astutil.PkgVar("runtime", "curg"), "goid"), astutil.Int(int64(g.ID)))
|
||||||
Op: token.EQL,
|
|
||||||
X: &ast.SelectorExpr{
|
|
||||||
X: &ast.SelectorExpr{
|
|
||||||
X: &ast.Ident{Name: "runtime"},
|
|
||||||
Sel: &ast.Ident{Name: "curg"},
|
|
||||||
},
|
|
||||||
Sel: &ast.Ident{Name: "goid"},
|
|
||||||
},
|
|
||||||
Y: &ast.BasicLit{Kind: token.INT, Value: strconv.Itoa(g.ID)},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func frameoffCondition(frameoff int64) ast.Expr {
|
func frameoffCondition(frame *Stackframe) ast.Expr {
|
||||||
return &ast.BinaryExpr{
|
return astutil.Eql(astutil.PkgVar("runtime", "frameoff"), astutil.Int(frame.FrameOffset()))
|
||||||
Op: token.EQL,
|
|
||||||
X: &ast.SelectorExpr{
|
|
||||||
X: &ast.Ident{Name: "runtime"},
|
|
||||||
Sel: &ast.Ident{Name: "frameoff"},
|
|
||||||
},
|
|
||||||
Y: &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(frameoff, 10)},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func andFrameoffCondition(cond ast.Expr, frameoff int64) ast.Expr {
|
|
||||||
if cond == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &ast.BinaryExpr{
|
|
||||||
Op: token.LAND,
|
|
||||||
X: cond,
|
|
||||||
Y: frameoffCondition(frameoff),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StepOut will continue until the current goroutine exits the
|
// StepOut will continue until the current goroutine exits the
|
||||||
@ -384,7 +356,7 @@ func (dbp *Target) StepOut() error {
|
|||||||
|
|
||||||
if topframe.Ret != 0 {
|
if topframe.Ret != 0 {
|
||||||
topframe, retframe := skipAutogeneratedWrappersOut(selg, curthread, &topframe, &retframe)
|
topframe, retframe := skipAutogeneratedWrappersOut(selg, curthread, &topframe, &retframe)
|
||||||
retFrameCond := andFrameoffCondition(sameGCond, retframe.FrameOffset())
|
retFrameCond := astutil.And(sameGCond, frameoffCondition(retframe))
|
||||||
bp, err := allowDuplicateBreakpoint(dbp.SetBreakpoint(topframe.Ret, NextBreakpoint, retFrameCond))
|
bp, err := allowDuplicateBreakpoint(dbp.SetBreakpoint(topframe.Ret, NextBreakpoint, retFrameCond))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -537,7 +509,7 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sameFrameCond := andFrameoffCondition(sameGCond, topframe.FrameOffset())
|
sameFrameCond := astutil.And(sameGCond, frameoffCondition(&topframe))
|
||||||
|
|
||||||
if stepInto && !backward {
|
if stepInto && !backward {
|
||||||
err := setStepIntoBreakpoints(dbp, text, topframe, sameGCond)
|
err := setStepIntoBreakpoints(dbp, text, topframe, sameGCond)
|
||||||
@ -618,18 +590,10 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {
|
|||||||
|
|
||||||
if !topframe.Inlined {
|
if !topframe.Inlined {
|
||||||
topframe, retframe := skipAutogeneratedWrappersOut(selg, curthread, &topframe, &retframe)
|
topframe, retframe := skipAutogeneratedWrappersOut(selg, curthread, &topframe, &retframe)
|
||||||
retFrameCond := andFrameoffCondition(sameGCond, retframe.FrameOffset())
|
retFrameCond := astutil.And(sameGCond, frameoffCondition(retframe))
|
||||||
var sameOrRetFrameCond ast.Expr
|
var sameOrRetFrameCond ast.Expr
|
||||||
if sameGCond != nil {
|
if sameGCond != nil {
|
||||||
sameOrRetFrameCond = &ast.BinaryExpr{
|
sameOrRetFrameCond = astutil.And(sameGCond, astutil.Or(frameoffCondition(topframe), frameoffCondition(retframe)))
|
||||||
Op: token.LAND,
|
|
||||||
X: sameGCond,
|
|
||||||
Y: &ast.BinaryExpr{
|
|
||||||
Op: token.LOR,
|
|
||||||
X: frameoffCondition(topframe.FrameOffset()),
|
|
||||||
Y: frameoffCondition(retframe.FrameOffset()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a breakpoint on the return address for the current frame.
|
// Add a breakpoint on the return address for the current frame.
|
||||||
|
|||||||
Reference in New Issue
Block a user