proc/*: allow stepping into functions without debug_info symbols
If proc.Step encounters a CALL instruction that points to an address that isn't associated with any function it should still follow the CALL. The circumstances creating this problem do not normally occur, it was encountered in the process of fixing a bug created by Go1.12.
This commit is contained in:
parent
f813520e9b
commit
b8ed126bf6
@ -252,8 +252,13 @@ func (bpmap *BreakpointMap) Set(addr uint64, kind BreakpointKind, cond ast.Expr,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fnName := ""
|
||||
if fn != nil {
|
||||
fnName = fn.Name
|
||||
}
|
||||
|
||||
newBreakpoint := &Breakpoint{
|
||||
FunctionName: fn.Name,
|
||||
FunctionName: fnName,
|
||||
File: f,
|
||||
Line: l,
|
||||
Addr: addr,
|
||||
|
@ -118,7 +118,7 @@ func resolveCallArg(inst *archInst, currentGoroutine bool, regs Registers, mem M
|
||||
|
||||
file, line, fn := bininfo.PCToLine(pc)
|
||||
if fn == nil {
|
||||
return nil
|
||||
return &Location{PC: pc}
|
||||
}
|
||||
return &Location{PC: pc, File: file, Line: line, Fn: fn}
|
||||
}
|
||||
|
@ -1028,9 +1028,6 @@ func (p *Process) FindBreakpoint(pc uint64) (*proc.Breakpoint, bool) {
|
||||
|
||||
func (p *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, []byte, error) {
|
||||
f, l, fn := p.bi.PCToLine(uint64(addr))
|
||||
if fn == nil {
|
||||
return "", 0, nil, nil, proc.InvalidAddressError{Address: addr}
|
||||
}
|
||||
|
||||
if err := p.conn.setBreakpoint(addr); err != nil {
|
||||
return "", 0, nil, nil, err
|
||||
|
@ -211,9 +211,6 @@ func (dbp *Process) CheckAndClearManualStopRequest() bool {
|
||||
|
||||
func (dbp *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, []byte, error) {
|
||||
f, l, fn := dbp.bi.PCToLine(uint64(addr))
|
||||
if fn == nil {
|
||||
return "", 0, nil, nil, proc.InvalidAddressError{Address: addr}
|
||||
}
|
||||
|
||||
originalData := make([]byte, dbp.bi.Arch.BreakpointSize())
|
||||
_, err := dbp.currentThread.ReadMemory(originalData, uintptr(addr))
|
||||
|
@ -379,21 +379,16 @@ func setStepIntoBreakpoint(dbp Process, text []AsmInstruction, cond ast.Expr) er
|
||||
|
||||
instr := text[0]
|
||||
|
||||
if instr.DestLoc == nil || instr.DestLoc.Fn == nil {
|
||||
if instr.DestLoc == nil {
|
||||
// Call destination couldn't be resolved because this was not the
|
||||
// current instruction, therefore the step-into breakpoint can not be set.
|
||||
return nil
|
||||
}
|
||||
|
||||
fn := instr.DestLoc.Fn
|
||||
|
||||
// Ensure PC and Entry match, otherwise StepInto is likely to set
|
||||
// its breakpoint before DestLoc.PC and hence run too far ahead.
|
||||
// Calls to runtime.duffzero and duffcopy have this problem.
|
||||
if fn.Entry != instr.DestLoc.PC {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip unexported runtime functions
|
||||
if strings.HasPrefix(fn.Name, "runtime.") && !isExportedRuntime(fn.Name) {
|
||||
if fn != nil && strings.HasPrefix(fn.Name, "runtime.") && !isExportedRuntime(fn.Name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -401,8 +396,19 @@ func setStepIntoBreakpoint(dbp Process, text []AsmInstruction, cond ast.Expr) er
|
||||
// or entire packages from being stepped into with 'step'
|
||||
// those extra checks should be done here.
|
||||
|
||||
pc := instr.DestLoc.PC
|
||||
|
||||
// We want to skip the function prologue but we should only do it if the
|
||||
// destination address of the CALL instruction is the entry point of the
|
||||
// function.
|
||||
// Calls to runtime.duffzero and duffcopy inserted by the compiler can
|
||||
// sometimes point inside the body of those functions, well after the
|
||||
// prologue.
|
||||
if fn != nil && fn.Entry == instr.DestLoc.PC {
|
||||
pc, _ = FirstPCAfterPrologue(dbp, fn, false)
|
||||
}
|
||||
|
||||
// Set a breakpoint after the function's prologue
|
||||
pc, _ := FirstPCAfterPrologue(dbp, fn, false)
|
||||
if _, err := dbp.SetBreakpoint(pc, NextBreakpoint, cond); err != nil {
|
||||
if _, ok := err.(BreakpointExistsError); !ok {
|
||||
return err
|
||||
|
Loading…
Reference in New Issue
Block a user