diff --git a/pkg/astutil/astutil.go b/pkg/astutil/astutil.go new file mode 100644 index 0000000000..6d861826b7 --- /dev/null +++ b/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} +} diff --git a/pkg/proc/target_exec.go b/pkg/proc/target_exec.go index 5b0fa9051b..8890ae8671 100644 --- a/pkg/proc/target_exec.go +++ b/pkg/proc/target_exec.go @@ -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" ) @@ -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 @@ -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 @@ -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) @@ -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.