diff --git a/dwarf/line/state_machine.go b/dwarf/line/state_machine.go index fdf070d9..bc8ee483 100644 --- a/dwarf/line/state_machine.go +++ b/dwarf/line/state_machine.go @@ -85,7 +85,7 @@ func (dbl *DebugLineInfo) NextLocAfterPC(pc uint64) *Location { for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() { findAndExecOpcode(sm, buf, b) - if sm.Line > line { + if sm.Line != line { break } } @@ -134,7 +134,7 @@ func (dbl *DebugLineInfo) LoopExitLocation(pc uint64) *Location { for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() { findAndExecOpcode(sm, buf, b) - if sm.Line > line { + if sm.Line != line { break } } @@ -148,7 +148,7 @@ func executeUntilPC(sm *StateMachine, buf *bytes.Buffer, pc uint64) { for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() { findAndExecOpcode(sm, buf, b) - if line != 0 && sm.Line > line { + if line != 0 && sm.Line != line { break } diff --git a/proctl/proctl_linux_amd64.go b/proctl/proctl_linux_amd64.go index 20dfa33a..313e43ef 100644 --- a/proctl/proctl_linux_amd64.go +++ b/proctl/proctl_linux_amd64.go @@ -18,16 +18,17 @@ import ( // Struct representing a debugged process. Holds onto pid, register values, // process struct and process state. type DebuggedProcess struct { - Pid int - Regs *syscall.PtraceRegs - Process *os.Process - ProcessState *os.ProcessState - Executable *elf.File - Symbols []elf.Symbol - GoSymTable *gosym.Table - FrameEntries frame.FrameDescriptionEntries - DebugLine *line.DebugLineInfo - BreakPoints map[string]*BreakPoint + Pid int + Regs *syscall.PtraceRegs + Process *os.Process + ProcessState *os.ProcessState + Executable *elf.File + Symbols []elf.Symbol + GoSymTable *gosym.Table + FrameEntries frame.FrameDescriptionEntries + DebugLine *line.DebugLineInfo + BreakPoints map[string]*BreakPoint + TempBreakPoints map[uint64]*BreakPoint } // Represents a single breakpoint. Stores information on the break @@ -69,11 +70,12 @@ func NewDebugProcess(pid int) (*DebuggedProcess, error) { } debuggedProc := DebuggedProcess{ - Pid: pid, - Regs: &syscall.PtraceRegs{}, - Process: proc, - ProcessState: ps, - BreakPoints: make(map[string]*BreakPoint), + Pid: pid, + Regs: &syscall.PtraceRegs{}, + Process: proc, + ProcessState: ps, + BreakPoints: make(map[string]*BreakPoint), + TempBreakPoints: make(map[uint64]*BreakPoint), } err = debuggedProc.LoadInformation() @@ -228,29 +230,46 @@ func (dbp *DebuggedProcess) Next() error { } loc := dbp.DebugLine.NextLocAfterPC(pc) + addrs = append(addrs, loc.Address) if !fde.AddressRange.Cover(loc.Address) { // Next line is outside current frame, use return addr. addr := dbp.ReturnAddressFromOffset(fde.ReturnAddressOffset(pc)) loc = dbp.DebugLine.LocationInfoForPC(addr) + addrs = append(addrs, loc.Address) } - addrs = append(addrs, loc.Address) if loc.Delta < 0 { // We are likely in a loop, set breakpoints at entry and exit. entry := dbp.DebugLine.LoopEntryLocation(loc.Line) - exit := dbp.DebugLine.LoopExitLocation(pc) + exit := dbp.DebugLine.LoopExitLocation(loc.Address) addrs = append(addrs, entry.Address, exit.Address) } for _, addr := range addrs { - if _, err := dbp.Break(uintptr(addr)); err != nil { + bp, err := dbp.Break(uintptr(addr)) + if err != nil { if _, ok := err.(BreakPointExistsError); !ok { return err } + + continue + } + dbp.TempBreakPoints[addr] = bp + } + + err = dbp.Continue() + if err != nil { + return err + } + + if bp, ok := dbp.TempBreakPoints[pc]; ok { + _, err := dbp.Clear(bp.Addr) + if err != nil { + return err } } - return dbp.Continue() + return nil } // Continue process until next breakpoint. diff --git a/proctl/proctl_test.go b/proctl/proctl_test.go index b7ce5140..11ccc69e 100644 --- a/proctl/proctl_test.go +++ b/proctl/proctl_test.go @@ -180,9 +180,11 @@ func TestNext(t *testing.T) { {17, 19}, {19, 20}, {20, 22}, - {22, 20}, + {22, 19}, + {19, 20}, {20, 22}, - {22, 25}, + {22, 19}, + {19, 25}, {25, 26}, {26, 30}, {30, 31},