proc: step into unexported runtime funcs when already inside runtime (#2061)
Normally we don't step into unexported runtime functions because the compiler is free to insert them into the code and they are not relevant to the user, however if we are already stepping through a runtime function we should let step into work normally and step into other runtime functions.
This commit is contained in:
parent
80b5b95182
commit
292f5c69f0
@ -7,6 +7,7 @@ import (
|
|||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/astutil"
|
"github.com/go-delve/delve/pkg/astutil"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/reader"
|
"github.com/go-delve/delve/pkg/dwarf/reader"
|
||||||
@ -146,10 +147,17 @@ func (dbp *Target) Continue() error {
|
|||||||
}
|
}
|
||||||
if dbp.GetDirection() == Forward {
|
if dbp.GetDirection() == Forward {
|
||||||
text, err := disassembleCurrentInstruction(dbp, curthread)
|
text, err := disassembleCurrentInstruction(dbp, curthread)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var fn *Function
|
||||||
|
if loc, _ := curthread.Location(); loc != nil {
|
||||||
|
fn = loc.Fn
|
||||||
|
}
|
||||||
// here we either set a breakpoint into the destination of the CALL
|
// here we either set a breakpoint into the destination of the CALL
|
||||||
// instruction or we determined that the called function is hidden,
|
// instruction or we determined that the called function is hidden,
|
||||||
// either way we need to resume execution
|
// either way we need to resume execution
|
||||||
if err = setStepIntoBreakpoint(dbp, text, sameGoroutineCondition(dbp.SelectedGoroutine())); err != nil {
|
if err = setStepIntoBreakpoint(dbp, fn, text, sameGoroutineCondition(dbp.SelectedGoroutine())); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -513,7 +521,7 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {
|
|||||||
sameFrameCond := astutil.And(sameGCond, frameoffCondition(&topframe))
|
sameFrameCond := astutil.And(sameGCond, frameoffCondition(&topframe))
|
||||||
|
|
||||||
if stepInto && !backward {
|
if stepInto && !backward {
|
||||||
err := setStepIntoBreakpoints(dbp, text, topframe, sameGCond)
|
err := setStepIntoBreakpoints(dbp, topframe.Current.Fn, text, topframe, sameGCond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -625,14 +633,14 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setStepIntoBreakpoints(dbp *Target, text []AsmInstruction, topframe Stackframe, sameGCond ast.Expr) error {
|
func setStepIntoBreakpoints(dbp *Target, curfn *Function, text []AsmInstruction, topframe Stackframe, sameGCond ast.Expr) error {
|
||||||
for _, instr := range text {
|
for _, instr := range text {
|
||||||
if instr.Loc.File != topframe.Current.File || instr.Loc.Line != topframe.Current.Line || !instr.IsCall() {
|
if instr.Loc.File != topframe.Current.File || instr.Loc.Line != topframe.Current.Line || !instr.IsCall() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if instr.DestLoc != nil {
|
if instr.DestLoc != nil {
|
||||||
if err := setStepIntoBreakpoint(dbp, []AsmInstruction{instr}, sameGCond); err != nil {
|
if err := setStepIntoBreakpoint(dbp, curfn, []AsmInstruction{instr}, sameGCond); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -708,11 +716,16 @@ func removePCsBetween(pcs []uint64, start, end uint64) []uint64 {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func setStepIntoBreakpoint(dbp *Target, text []AsmInstruction, cond ast.Expr) error {
|
func setStepIntoBreakpoint(dbp *Target, curfn *Function, text []AsmInstruction, cond ast.Expr) error {
|
||||||
if len(text) <= 0 {
|
if len(text) <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the current function is already a runtime function then
|
||||||
|
// setStepIntoBreakpoint is allowed to step into unexported runtime
|
||||||
|
// functions.
|
||||||
|
stepIntoUnexportedRuntime := curfn != nil && strings.HasPrefix(curfn.Name, "runtime.")
|
||||||
|
|
||||||
instr := text[0]
|
instr := text[0]
|
||||||
|
|
||||||
if instr.DestLoc == nil {
|
if instr.DestLoc == nil {
|
||||||
@ -724,7 +737,7 @@ func setStepIntoBreakpoint(dbp *Target, text []AsmInstruction, cond ast.Expr) er
|
|||||||
fn := instr.DestLoc.Fn
|
fn := instr.DestLoc.Fn
|
||||||
|
|
||||||
// Skip unexported runtime functions
|
// Skip unexported runtime functions
|
||||||
if fn != nil && fn.privateRuntime() {
|
if !stepIntoUnexportedRuntime && fn != nil && fn.privateRuntime() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user