Skip to content

Commit

Permalink
proc: simplify next/step/stepout condition code
Browse files Browse the repository at this point in the history
Adds a library of utility functions to generated breakpoint conditions
for next, step and stepout.
  • Loading branch information
aarzilli authored and derekparker committed Apr 4, 2020
1 parent eac6ebe commit 7dedf1e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 44 deletions.
40 changes: 40 additions & 0 deletions pkg/astutil/astutil.go
@@ -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}
}
52 changes: 8 additions & 44 deletions pkg/proc/target_exec.go
Expand Up @@ -7,8 +7,8 @@ import (
"go/ast"
"go/token"
"path/filepath"
"strconv"

"github.com/go-delve/delve/pkg/astutil"
"github.com/go-delve/delve/pkg/dwarf/reader"
)

Expand Down Expand Up @@ -289,39 +289,11 @@ func sameGoroutineCondition(g *G) ast.Expr {
if g == nil {
return nil
}
return &ast.BinaryExpr{
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 {
return &ast.BinaryExpr{
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)},
}
return astutil.Eql(astutil.Sel(astutil.PkgVar("runtime", "curg"), "goid"), astutil.Int(int64(g.ID)))
}

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),
}
func frameoffCondition(frame *Stackframe) ast.Expr {
return astutil.Eql(astutil.PkgVar("runtime", "frameoff"), astutil.Int(frame.FrameOffset()))
}

// StepOut will continue until the current goroutine exits the
Expand Down Expand Up @@ -384,7 +356,7 @@ func (dbp *Target) StepOut() error {

if topframe.Ret != 0 {
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))
if err != nil {
return err
Expand Down Expand Up @@ -537,7 +509,7 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {
return err
}

sameFrameCond := andFrameoffCondition(sameGCond, topframe.FrameOffset())
sameFrameCond := astutil.And(sameGCond, frameoffCondition(&topframe))

if stepInto && !backward {
err := setStepIntoBreakpoints(dbp, text, topframe, sameGCond)
Expand Down Expand Up @@ -618,18 +590,10 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {

if !topframe.Inlined {
topframe, retframe := skipAutogeneratedWrappersOut(selg, curthread, &topframe, &retframe)
retFrameCond := andFrameoffCondition(sameGCond, retframe.FrameOffset())
retFrameCond := astutil.And(sameGCond, frameoffCondition(retframe))
var sameOrRetFrameCond ast.Expr
if sameGCond != nil {
sameOrRetFrameCond = &ast.BinaryExpr{
Op: token.LAND,
X: sameGCond,
Y: &ast.BinaryExpr{
Op: token.LOR,
X: frameoffCondition(topframe.FrameOffset()),
Y: frameoffCondition(retframe.FrameOffset()),
},
}
sameOrRetFrameCond = astutil.And(sameGCond, astutil.Or(frameoffCondition(topframe), frameoffCondition(retframe)))
}

// Add a breakpoint on the return address for the current frame.
Expand Down

0 comments on commit 7dedf1e

Please sign in to comment.