proc: Renamed temp breakpoints to internal breakpoints

This commit is contained in:
aarzilli 2016-09-30 08:35:29 +02:00
parent 7c49d4968d
commit 9cbe768836
6 changed files with 112 additions and 126 deletions

@ -9,7 +9,7 @@ package main
// Expect to be stopped in fmt.Printf or runtime.duffzero // Expect to be stopped in fmt.Printf or runtime.duffzero
// In bug, s #2 runs to the process exit because the call // In bug, s #2 runs to the process exit because the call
// to duffzero enters duffzero well after the nominal entry // to duffzero enters duffzero well after the nominal entry
// and skips the temporary breakpoint placed by StepZero(). // and skips the internal breakpoint placed by Step().
import "fmt" import "fmt"
var v int = 99 var v int = 99

@ -21,7 +21,7 @@ type Breakpoint struct {
OriginalData []byte // If software breakpoint, the data we replace with breakpoint instruction. OriginalData []byte // If software breakpoint, the data we replace with breakpoint instruction.
Name string // User defined name of the breakpoint Name string // User defined name of the breakpoint
ID int // Monotonically increasing ID. ID int // Monotonically increasing ID.
Kind BreakpointKind // Whether this is a temp breakpoint (for next'ing or stepping). Kind BreakpointKind // Whether this is an internal breakpoint (for next'ing or stepping).
// Breakpoint information // Breakpoint information
Tracepoint bool // Tracepoint flag Tracepoint bool // Tracepoint flag
@ -103,48 +103,6 @@ func (iae InvalidAddressError) Error() string {
return fmt.Sprintf("Invalid address %#v\n", iae.address) return fmt.Sprintf("Invalid address %#v\n", iae.address)
} }
func (dbp *Process) setBreakpoint(tid int, addr uint64, kind BreakpointKind) (*Breakpoint, error) {
if bp, ok := dbp.FindBreakpoint(addr); ok {
return nil, BreakpointExistsError{bp.File, bp.Line, bp.Addr}
}
f, l, fn := dbp.goSymTable.PCToLine(uint64(addr))
if fn == nil {
return nil, InvalidAddressError{address: addr}
}
newBreakpoint := &Breakpoint{
FunctionName: fn.Name,
File: f,
Line: l,
Addr: addr,
Kind: kind,
Cond: nil,
HitCount: map[int]uint64{},
}
if kind != UserBreakpoint {
dbp.tempBreakpointIDCounter++
newBreakpoint.ID = dbp.tempBreakpointIDCounter
} else {
dbp.breakpointIDCounter++
newBreakpoint.ID = dbp.breakpointIDCounter
}
thread := dbp.Threads[tid]
originalData, err := thread.readMemory(uintptr(addr), dbp.arch.BreakpointSize())
if err != nil {
return nil, err
}
if err := dbp.writeSoftwareBreakpoint(thread, addr); err != nil {
return nil, err
}
newBreakpoint.OriginalData = originalData
dbp.Breakpoints[addr] = newBreakpoint
return newBreakpoint, nil
}
func (dbp *Process) writeSoftwareBreakpoint(thread *Thread, addr uint64) error { func (dbp *Process) writeSoftwareBreakpoint(thread *Thread, addr uint64) error {
_, err := thread.writeMemory(uintptr(addr), dbp.arch.BreakpointInstruction()) _, err := thread.writeMemory(uintptr(addr), dbp.arch.BreakpointInstruction())
return err return err

@ -43,21 +43,21 @@ type Process struct {
// Maps package names to package paths, needed to lookup types inside DWARF info // Maps package names to package paths, needed to lookup types inside DWARF info
packageMap map[string]string packageMap map[string]string
allGCache []*G allGCache []*G
dwarf *dwarf.Data dwarf *dwarf.Data
goSymTable *gosym.Table goSymTable *gosym.Table
frameEntries frame.FrameDescriptionEntries frameEntries frame.FrameDescriptionEntries
lineInfo line.DebugLines lineInfo line.DebugLines
os *OSProcessDetails os *OSProcessDetails
arch Arch arch Arch
breakpointIDCounter int breakpointIDCounter int
tempBreakpointIDCounter int internalBreakpointIDCounter int
firstStart bool firstStart bool
halt bool halt bool
exited bool exited bool
ptraceChan chan func() ptraceChan chan func()
ptraceDoneChan chan interface{} ptraceDoneChan chan interface{}
types map[string]dwarf.Offset types map[string]dwarf.Offset
loadModuleDataOnce sync.Once loadModuleDataOnce sync.Once
moduleData []moduleData moduleData []moduleData
@ -224,21 +224,48 @@ func (dbp *Process) RequestManualStop() error {
// SetBreakpoint sets a breakpoint at addr, and stores it in the process wide // SetBreakpoint sets a breakpoint at addr, and stores it in the process wide
// break point table. Setting a break point must be thread specific due to // break point table. Setting a break point must be thread specific due to
// ptrace actions needing the thread to be in a signal-delivery-stop. // ptrace actions needing the thread to be in a signal-delivery-stop.
func (dbp *Process) SetBreakpoint(addr uint64) (*Breakpoint, error) { func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error) {
if dbp.exited { tid := dbp.CurrentThread.ID
return nil, &ProcessExitedError{}
}
return dbp.setBreakpoint(dbp.CurrentThread.ID, addr, UserBreakpoint)
}
// SetTempBreakpoint sets a temp breakpoint. Used during 'next' operations. if bp, ok := dbp.FindBreakpoint(addr); ok {
func (dbp *Process) SetTempBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error) { return nil, BreakpointExistsError{bp.File, bp.Line, bp.Addr}
bp, err := dbp.setBreakpoint(dbp.CurrentThread.ID, addr, kind) }
f, l, fn := dbp.goSymTable.PCToLine(uint64(addr))
if fn == nil {
return nil, InvalidAddressError{address: addr}
}
newBreakpoint := &Breakpoint{
FunctionName: fn.Name,
File: f,
Line: l,
Addr: addr,
Kind: kind,
Cond: cond,
HitCount: map[int]uint64{},
}
if kind != UserBreakpoint {
dbp.internalBreakpointIDCounter++
newBreakpoint.ID = dbp.internalBreakpointIDCounter
} else {
dbp.breakpointIDCounter++
newBreakpoint.ID = dbp.breakpointIDCounter
}
thread := dbp.Threads[tid]
originalData, err := thread.readMemory(uintptr(addr), dbp.arch.BreakpointSize())
if err != nil { if err != nil {
return nil, err return nil, err
} }
bp.Cond = cond if err := dbp.writeSoftwareBreakpoint(thread, addr); err != nil {
return bp, nil return nil, err
}
newBreakpoint.OriginalData = originalData
dbp.Breakpoints[addr] = newBreakpoint
return newBreakpoint, nil
} }
// ClearBreakpoint clears the breakpoint at addr. // ClearBreakpoint clears the breakpoint at addr.
@ -280,7 +307,7 @@ func (dbp *Process) Next() (err error) {
switch err.(type) { switch err.(type) {
case ThreadBlockedError, NoReturnAddr: // Noop case ThreadBlockedError, NoReturnAddr: // Noop
default: default:
dbp.ClearTempBreakpoints() dbp.ClearInternalBreakpoints()
return return
} }
} }
@ -330,7 +357,7 @@ func (dbp *Process) Continue() error {
} }
} }
return dbp.conditionErrors() return dbp.conditionErrors()
case dbp.CurrentThread.onTriggeredTempBreakpoint(): case dbp.CurrentThread.onTriggeredInternalBreakpoint():
if dbp.CurrentThread.CurrentBreakpoint.Kind == StepBreakpoint { if dbp.CurrentThread.CurrentBreakpoint.Kind == StepBreakpoint {
// See description of proc.(*Process).next for the meaning of StepBreakpoints // See description of proc.(*Process).next for the meaning of StepBreakpoints
if err := dbp.conditionErrors(); err != nil { if err := dbp.conditionErrors(); err != nil {
@ -351,7 +378,7 @@ func (dbp *Process) Continue() error {
return err return err
} }
} else { } else {
if err := dbp.ClearTempBreakpoints(); err != nil { if err := dbp.ClearInternalBreakpoints(); err != nil {
return err return err
} }
return dbp.conditionErrors() return dbp.conditionErrors()
@ -362,7 +389,7 @@ func (dbp *Process) Continue() error {
return err return err
} }
if onNextGoroutine { if onNextGoroutine {
err := dbp.ClearTempBreakpoints() err := dbp.ClearInternalBreakpoints()
if err != nil { if err != nil {
return err return err
} }
@ -389,12 +416,12 @@ func (dbp *Process) conditionErrors() error {
} }
// pick a new dbp.CurrentThread, with the following priority: // pick a new dbp.CurrentThread, with the following priority:
// - a thread with onTriggeredTempBreakpoint() == true // - a thread with onTriggeredInternalBreakpoint() == true
// - a thread with onTriggeredBreakpoint() == true (prioritizing trapthread) // - a thread with onTriggeredBreakpoint() == true (prioritizing trapthread)
// - trapthread // - trapthread
func (dbp *Process) pickCurrentThread(trapthread *Thread) error { func (dbp *Process) pickCurrentThread(trapthread *Thread) error {
for _, th := range dbp.Threads { for _, th := range dbp.Threads {
if th.onTriggeredTempBreakpoint() { if th.onTriggeredInternalBreakpoint() {
return dbp.SwitchThread(th.ID) return dbp.SwitchThread(th.ID)
} }
} }
@ -425,7 +452,7 @@ func (dbp *Process) Step() (err error) {
switch err.(type) { switch err.(type) {
case ThreadBlockedError, NoReturnAddr: // Noop case ThreadBlockedError, NoReturnAddr: // Noop
default: default:
dbp.ClearTempBreakpoints() dbp.ClearInternalBreakpoints()
return return
} }
} }
@ -461,7 +488,7 @@ func (dbp *Process) StepInstruction() (err error) {
} }
if dbp.SelectedGoroutine.thread == nil { if dbp.SelectedGoroutine.thread == nil {
// Step called on parked goroutine // Step called on parked goroutine
if _, err := dbp.SetTempBreakpoint(dbp.SelectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.SelectedGoroutine)); err != nil { if _, err := dbp.SetBreakpoint(dbp.SelectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.SelectedGoroutine)); err != nil {
return err return err
} }
return dbp.Continue() return dbp.Continue()
@ -715,7 +742,7 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
panicpc, err := dbp.FindFunctionLocation("runtime.startpanic", true, 0) panicpc, err := dbp.FindFunctionLocation("runtime.startpanic", true, 0)
if err == nil { if err == nil {
bp, err := dbp.SetBreakpoint(panicpc) bp, err := dbp.SetBreakpoint(panicpc, UserBreakpoint, nil)
if err == nil { if err == nil {
bp.Name = "unrecovered-panic" bp.Name = "unrecovered-panic"
bp.ID = -1 bp.ID = -1
@ -726,7 +753,7 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
return dbp, nil return dbp, nil
} }
func (dbp *Process) ClearTempBreakpoints() error { func (dbp *Process) ClearInternalBreakpoints() error {
for _, bp := range dbp.Breakpoints { for _, bp := range dbp.Breakpoints {
if !bp.Internal() { if !bp.Internal() {
continue continue

@ -138,7 +138,7 @@ func setFunctionBreakpoint(p *Process, fname string) (*Breakpoint, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return p.SetBreakpoint(addr) return p.SetBreakpoint(addr, UserBreakpoint, nil)
} }
func TestHalt(t *testing.T) { func TestHalt(t *testing.T) {
@ -188,7 +188,7 @@ func TestStep(t *testing.T) {
helloworldfunc := p.goSymTable.LookupFunc("main.helloworld") helloworldfunc := p.goSymTable.LookupFunc("main.helloworld")
helloworldaddr := helloworldfunc.Entry helloworldaddr := helloworldfunc.Entry
_, err := p.SetBreakpoint(helloworldaddr) _, err := p.SetBreakpoint(helloworldaddr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
@ -210,7 +210,7 @@ func TestBreakpoint(t *testing.T) {
helloworldfunc := p.goSymTable.LookupFunc("main.helloworld") helloworldfunc := p.goSymTable.LookupFunc("main.helloworld")
helloworldaddr := helloworldfunc.Entry helloworldaddr := helloworldfunc.Entry
bp, err := p.SetBreakpoint(helloworldaddr) bp, err := p.SetBreakpoint(helloworldaddr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
@ -237,7 +237,7 @@ func TestBreakpointInSeperateGoRoutine(t *testing.T) {
t.Fatal("No fn exists") t.Fatal("No fn exists")
} }
_, err := p.SetBreakpoint(fn.Entry) _, err := p.SetBreakpoint(fn.Entry, UserBreakpoint, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -261,7 +261,7 @@ func TestBreakpointInSeperateGoRoutine(t *testing.T) {
func TestBreakpointWithNonExistantFunction(t *testing.T) { func TestBreakpointWithNonExistantFunction(t *testing.T) {
withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) { withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) {
_, err := p.SetBreakpoint(0) _, err := p.SetBreakpoint(0, UserBreakpoint, nil)
if err == nil { if err == nil {
t.Fatal("Should not be able to break at non existant function") t.Fatal("Should not be able to break at non existant function")
} }
@ -271,7 +271,7 @@ func TestBreakpointWithNonExistantFunction(t *testing.T) {
func TestClearBreakpointBreakpoint(t *testing.T) { func TestClearBreakpointBreakpoint(t *testing.T) {
withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) { withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) {
fn := p.goSymTable.LookupFunc("main.sleepytime") fn := p.goSymTable.LookupFunc("main.sleepytime")
bp, err := p.SetBreakpoint(fn.Entry) bp, err := p.SetBreakpoint(fn.Entry, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
bp, err = p.ClearBreakpoint(fn.Entry) bp, err = p.ClearBreakpoint(fn.Entry)
@ -324,7 +324,7 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc
var pc uint64 var pc uint64
pc, err = p.FindFileLocation(fixture.Source, testcases[0].begin) pc, err = p.FindFileLocation(fixture.Source, testcases[0].begin)
assertNoError(err, t, "FindFileLocation()") assertNoError(err, t, "FindFileLocation()")
bp, err = p.SetBreakpoint(pc) bp, err = p.SetBreakpoint(pc, UserBreakpoint, nil)
} }
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
@ -579,7 +579,7 @@ func TestFindReturnAddress(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, err = p.SetBreakpoint(start) _, err = p.SetBreakpoint(start, UserBreakpoint, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -605,7 +605,7 @@ func TestFindReturnAddressTopOfStackFn(t *testing.T) {
if fn == nil { if fn == nil {
t.Fatalf("could not find function %s", fnName) t.Fatalf("could not find function %s", fnName)
} }
if _, err := p.SetBreakpoint(fn.Entry); err != nil { if _, err := p.SetBreakpoint(fn.Entry, UserBreakpoint, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := p.Continue(); err != nil { if err := p.Continue(); err != nil {
@ -628,7 +628,7 @@ func TestSwitchThread(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, err = p.SetBreakpoint(pc) _, err = p.SetBreakpoint(pc, UserBreakpoint, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -670,7 +670,7 @@ func TestCGONext(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, err = p.SetBreakpoint(pc) _, err = p.SetBreakpoint(pc, UserBreakpoint, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -953,7 +953,7 @@ func TestBreakpointOnFunctionEntry(t *testing.T) {
withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) { withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) {
addr, err := p.FindFunctionLocation("main.main", false, 0) addr, err := p.FindFunctionLocation("main.main", false, 0)
assertNoError(err, t, "FindFunctionLocation()") assertNoError(err, t, "FindFunctionLocation()")
_, err = p.SetBreakpoint(addr) _, err = p.SetBreakpoint(addr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
_, ln := currentLineNumber(p, t) _, ln := currentLineNumber(p, t)
@ -977,7 +977,7 @@ func TestIssue239(t *testing.T) {
withTestProcess("is sue239", t, func(p *Process, fixture protest.Fixture) { withTestProcess("is sue239", t, func(p *Process, fixture protest.Fixture) {
pos, _, err := p.goSymTable.LineToPC(fixture.Source, 17) pos, _, err := p.goSymTable.LineToPC(fixture.Source, 17)
assertNoError(err, t, "LineToPC()") assertNoError(err, t, "LineToPC()")
_, err = p.SetBreakpoint(pos) _, err = p.SetBreakpoint(pos, UserBreakpoint, nil)
assertNoError(err, t, fmt.Sprintf("SetBreakpoint(%d)", pos)) assertNoError(err, t, fmt.Sprintf("SetBreakpoint(%d)", pos))
assertNoError(p.Continue(), t, fmt.Sprintf("Continue()")) assertNoError(p.Continue(), t, fmt.Sprintf("Continue()"))
}) })
@ -1238,7 +1238,7 @@ func TestBreakpointCounts(t *testing.T) {
withTestProcess("bpcountstest", t, func(p *Process, fixture protest.Fixture) { withTestProcess("bpcountstest", t, func(p *Process, fixture protest.Fixture) {
addr, _, err := p.goSymTable.LineToPC(fixture.Source, 12) addr, _, err := p.goSymTable.LineToPC(fixture.Source, 12)
assertNoError(err, t, "LineToPC") assertNoError(err, t, "LineToPC")
bp, err := p.SetBreakpoint(addr) bp, err := p.SetBreakpoint(addr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
for { for {
@ -1289,7 +1289,7 @@ func TestBreakpointCountsWithDetection(t *testing.T) {
withTestProcess("bpcountstest", t, func(p *Process, fixture protest.Fixture) { withTestProcess("bpcountstest", t, func(p *Process, fixture protest.Fixture) {
addr, _, err := p.goSymTable.LineToPC(fixture.Source, 12) addr, _, err := p.goSymTable.LineToPC(fixture.Source, 12)
assertNoError(err, t, "LineToPC") assertNoError(err, t, "LineToPC")
bp, err := p.SetBreakpoint(addr) bp, err := p.SetBreakpoint(addr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
for { for {
@ -1384,7 +1384,7 @@ func TestIssue262(t *testing.T) {
withTestProcess("issue262", t, func(p *Process, fixture protest.Fixture) { withTestProcess("issue262", t, func(p *Process, fixture protest.Fixture) {
addr, _, err := p.goSymTable.LineToPC(fixture.Source, 11) addr, _, err := p.goSymTable.LineToPC(fixture.Source, 11)
assertNoError(err, t, "LineToPC") assertNoError(err, t, "LineToPC")
_, err = p.SetBreakpoint(addr) _, err = p.SetBreakpoint(addr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
@ -1400,12 +1400,13 @@ func TestIssue262(t *testing.T) {
} }
func TestIssue305(t *testing.T) { func TestIssue305(t *testing.T) {
// If 'next' hits a breakpoint on the goroutine it's stepping through the temp breakpoints aren't cleared // If 'next' hits a breakpoint on the goroutine it's stepping through
// preventing further use of 'next' command // the internal breakpoints aren't cleared preventing further use of
// 'next' command
withTestProcess("issue305", t, func(p *Process, fixture protest.Fixture) { withTestProcess("issue305", t, func(p *Process, fixture protest.Fixture) {
addr, _, err := p.goSymTable.LineToPC(fixture.Source, 5) addr, _, err := p.goSymTable.LineToPC(fixture.Source, 5)
assertNoError(err, t, "LineToPC()") assertNoError(err, t, "LineToPC()")
_, err = p.SetBreakpoint(addr) _, err = p.SetBreakpoint(addr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
@ -1445,7 +1446,7 @@ func TestCondBreakpoint(t *testing.T) {
withTestProcess("parallel_next", t, func(p *Process, fixture protest.Fixture) { withTestProcess("parallel_next", t, func(p *Process, fixture protest.Fixture) {
addr, _, err := p.goSymTable.LineToPC(fixture.Source, 9) addr, _, err := p.goSymTable.LineToPC(fixture.Source, 9)
assertNoError(err, t, "LineToPC") assertNoError(err, t, "LineToPC")
bp, err := p.SetBreakpoint(addr) bp, err := p.SetBreakpoint(addr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
bp.Cond = &ast.BinaryExpr{ bp.Cond = &ast.BinaryExpr{
Op: token.EQL, Op: token.EQL,
@ -1469,7 +1470,7 @@ func TestCondBreakpointError(t *testing.T) {
withTestProcess("parallel_next", t, func(p *Process, fixture protest.Fixture) { withTestProcess("parallel_next", t, func(p *Process, fixture protest.Fixture) {
addr, _, err := p.goSymTable.LineToPC(fixture.Source, 9) addr, _, err := p.goSymTable.LineToPC(fixture.Source, 9)
assertNoError(err, t, "LineToPC") assertNoError(err, t, "LineToPC")
bp, err := p.SetBreakpoint(addr) bp, err := p.SetBreakpoint(addr, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
bp.Cond = &ast.BinaryExpr{ bp.Cond = &ast.BinaryExpr{
Op: token.EQL, Op: token.EQL,
@ -1549,7 +1550,7 @@ func TestIssue384(t *testing.T) {
withTestProcess("issue384", t, func(p *Process, fixture protest.Fixture) { withTestProcess("issue384", t, func(p *Process, fixture protest.Fixture) {
start, _, err := p.goSymTable.LineToPC(fixture.Source, 13) start, _, err := p.goSymTable.LineToPC(fixture.Source, 13)
assertNoError(err, t, "LineToPC()") assertNoError(err, t, "LineToPC()")
_, err = p.SetBreakpoint(start) _, err = p.SetBreakpoint(start, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
_, err = evalVariable(p, "st") _, err = evalVariable(p, "st")
@ -1562,7 +1563,7 @@ func TestIssue332_Part1(t *testing.T) {
withTestProcess("issue332", t, func(p *Process, fixture protest.Fixture) { withTestProcess("issue332", t, func(p *Process, fixture protest.Fixture) {
start, _, err := p.goSymTable.LineToPC(fixture.Source, 8) start, _, err := p.goSymTable.LineToPC(fixture.Source, 8)
assertNoError(err, t, "LineToPC()") assertNoError(err, t, "LineToPC()")
_, err = p.SetBreakpoint(start) _, err = p.SetBreakpoint(start, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
assertNoError(p.Next(), t, "first Next()") assertNoError(p.Next(), t, "first Next()")
@ -1588,7 +1589,7 @@ func TestIssue332_Part2(t *testing.T) {
withTestProcess("issue332", t, func(p *Process, fixture protest.Fixture) { withTestProcess("issue332", t, func(p *Process, fixture protest.Fixture) {
start, _, err := p.goSymTable.LineToPC(fixture.Source, 8) start, _, err := p.goSymTable.LineToPC(fixture.Source, 8)
assertNoError(err, t, "LineToPC()") assertNoError(err, t, "LineToPC()")
_, err = p.SetBreakpoint(start) _, err = p.SetBreakpoint(start, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
@ -1639,7 +1640,7 @@ func TestIssue414(t *testing.T) {
withTestProcess("math", t, func(p *Process, fixture protest.Fixture) { withTestProcess("math", t, func(p *Process, fixture protest.Fixture) {
start, _, err := p.goSymTable.LineToPC(fixture.Source, 9) start, _, err := p.goSymTable.LineToPC(fixture.Source, 9)
assertNoError(err, t, "LineToPC()") assertNoError(err, t, "LineToPC()")
_, err = p.SetBreakpoint(start) _, err = p.SetBreakpoint(start, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
for { for {
@ -1905,10 +1906,10 @@ func TestUnsupportedArch(t *testing.T) {
func TestIssue573(t *testing.T) { func TestIssue573(t *testing.T) {
// calls to runtime.duffzero and runtime.duffcopy jump directly into the middle // calls to runtime.duffzero and runtime.duffcopy jump directly into the middle
// of the function and the temp breakpoint set by StepInto may be missed. // of the function and the internal breakpoint set by StepInto may be missed.
withTestProcess("issue573", t, func(p *Process, fixture protest.Fixture) { withTestProcess("issue573", t, func(p *Process, fixture protest.Fixture) {
f := p.goSymTable.LookupFunc("main.foo") f := p.goSymTable.LookupFunc("main.foo")
_, err := p.SetBreakpoint(f.Entry) _, err := p.SetBreakpoint(f.Entry, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
assertNoError(p.Step(), t, "Step() #1") assertNoError(p.Step(), t, "Step() #1")
@ -2044,7 +2045,7 @@ func TestStepConcurrentDirect(t *testing.T) {
withTestProcess("teststepconcurrent", t, func(p *Process, fixture protest.Fixture) { withTestProcess("teststepconcurrent", t, func(p *Process, fixture protest.Fixture) {
pc, err := p.FindFileLocation(fixture.Source, 37) pc, err := p.FindFileLocation(fixture.Source, 37)
assertNoError(err, t, "FindFileLocation()") assertNoError(err, t, "FindFileLocation()")
bp, err := p.SetBreakpoint(pc) bp, err := p.SetBreakpoint(pc, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
@ -2095,7 +2096,7 @@ func TestStepConcurrentPtr(t *testing.T) {
withTestProcess("teststepconcurrent", t, func(p *Process, fixture protest.Fixture) { withTestProcess("teststepconcurrent", t, func(p *Process, fixture protest.Fixture) {
pc, err := p.FindFileLocation(fixture.Source, 24) pc, err := p.FindFileLocation(fixture.Source, 24)
assertNoError(err, t, "FindFileLocation()") assertNoError(err, t, "FindFileLocation()")
_, err = p.SetBreakpoint(pc) _, err = p.SetBreakpoint(pc, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
kvals := map[int]int64{} kvals := map[int]int64{}
@ -2129,7 +2130,7 @@ func TestStepConcurrentPtr(t *testing.T) {
assertNoError(p.Step(), t, "Step()") assertNoError(p.Step(), t, "Step()")
for nextInProgress(p) { for nextInProgress(p) {
if p.SelectedGoroutine.ID == gid { if p.SelectedGoroutine.ID == gid {
t.Fatalf("step did not step into function call (but temp breakpoints still active?) (%d %d)", gid, p.SelectedGoroutine.ID) t.Fatalf("step did not step into function call (but internal breakpoints still active?) (%d %d)", gid, p.SelectedGoroutine.ID)
} }
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")
} }
@ -2161,7 +2162,7 @@ func TestStepOnCallPtrInstr(t *testing.T) {
withTestProcess("teststepprog", t, func(p *Process, fixture protest.Fixture) { withTestProcess("teststepprog", t, func(p *Process, fixture protest.Fixture) {
pc, err := p.FindFileLocation(fixture.Source, 10) pc, err := p.FindFileLocation(fixture.Source, 10)
assertNoError(err, t, "FindFileLocation()") assertNoError(err, t, "FindFileLocation()")
_, err = p.SetBreakpoint(pc) _, err = p.SetBreakpoint(pc, UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()") assertNoError(err, t, "SetBreakpoint()")
assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Continue(), t, "Continue()")

@ -182,14 +182,14 @@ func (dbp *Process) next(stepInto bool) error {
if instr.DestLoc != nil && instr.DestLoc.Fn != nil { if instr.DestLoc != nil && instr.DestLoc.Fn != nil {
if err := dbp.setStepIntoBreakpoint([]AsmInstruction{instr}, cond); err != nil { if err := dbp.setStepIntoBreakpoint([]AsmInstruction{instr}, cond); err != nil {
dbp.ClearTempBreakpoints() dbp.ClearInternalBreakpoints()
return err return err
} }
} else { } else {
// Non-absolute call instruction, set a StepBreakpoint here // Non-absolute call instruction, set a StepBreakpoint here
if _, err := dbp.SetTempBreakpoint(instr.Loc.PC, StepBreakpoint, cond); err != nil { if _, err := dbp.SetBreakpoint(instr.Loc.PC, StepBreakpoint, cond); err != nil {
if _, ok := err.(BreakpointExistsError); !ok { if _, ok := err.(BreakpointExistsError); !ok {
dbp.ClearTempBreakpoints() dbp.ClearInternalBreakpoints()
return err return err
} }
} }
@ -219,10 +219,10 @@ func (dbp *Process) next(stepInto bool) error {
} }
} }
if deferpc != 0 && deferpc != topframe.Current.PC { if deferpc != 0 && deferpc != topframe.Current.PC {
bp, err := dbp.SetTempBreakpoint(deferpc, NextDeferBreakpoint, cond) bp, err := dbp.SetBreakpoint(deferpc, NextDeferBreakpoint, cond)
if err != nil { if err != nil {
if _, ok := err.(BreakpointExistsError); !ok { if _, ok := err.(BreakpointExistsError); !ok {
dbp.ClearTempBreakpoints() dbp.ClearInternalBreakpoints()
return err return err
} }
} }
@ -254,7 +254,7 @@ func (dbp *Process) next(stepInto bool) error {
// Add a breakpoint on the return address for the current frame // Add a breakpoint on the return address for the current frame
pcs = append(pcs, topframe.Ret) pcs = append(pcs, topframe.Ret)
return dbp.setTempBreakpoints(topframe.Current.PC, pcs, NextBreakpoint, cond) return dbp.setInternalBreakpoints(topframe.Current.PC, pcs, NextBreakpoint, cond)
} }
func (dbp *Process) setStepIntoBreakpoint(text []AsmInstruction, cond ast.Expr) error { func (dbp *Process) setStepIntoBreakpoint(text []AsmInstruction, cond ast.Expr) error {
@ -288,7 +288,7 @@ func (dbp *Process) setStepIntoBreakpoint(text []AsmInstruction, cond ast.Expr)
// Set a breakpoint after the function's prologue // Set a breakpoint after the function's prologue
pc, _ := dbp.FirstPCAfterPrologue(fn, false) pc, _ := dbp.FirstPCAfterPrologue(fn, false)
if _, err := dbp.SetTempBreakpoint(pc, NextBreakpoint, cond); err != nil { if _, err := dbp.SetBreakpoint(pc, NextBreakpoint, cond); err != nil {
if _, ok := err.(BreakpointExistsError); !ok { if _, ok := err.(BreakpointExistsError); !ok {
return err return err
} }
@ -297,16 +297,16 @@ func (dbp *Process) setStepIntoBreakpoint(text []AsmInstruction, cond ast.Expr)
return nil return nil
} }
// setTempBreakpoints sets a breakpoint to all addresses specified in pcs // setInternalBreakpoints sets a breakpoint to all addresses specified in pcs
// skipping over curpc and curpc-1 // skipping over curpc and curpc-1
func (dbp *Process) setTempBreakpoints(curpc uint64, pcs []uint64, kind BreakpointKind, cond ast.Expr) error { func (dbp *Process) setInternalBreakpoints(curpc uint64, pcs []uint64, kind BreakpointKind, cond ast.Expr) error {
for i := range pcs { for i := range pcs {
if pcs[i] == curpc || pcs[i] == curpc-1 { if pcs[i] == curpc || pcs[i] == curpc-1 {
continue continue
} }
if _, err := dbp.SetTempBreakpoint(pcs[i], kind, cond); err != nil { if _, err := dbp.SetBreakpoint(pcs[i], kind, cond); err != nil {
if _, ok := err.(BreakpointExistsError); !ok { if _, ok := err.(BreakpointExistsError); !ok {
dbp.ClearTempBreakpoints() dbp.ClearInternalBreakpoints()
return err return err
} }
} }
@ -461,7 +461,7 @@ func (thread *Thread) onTriggeredBreakpoint() bool {
return (thread.CurrentBreakpoint != nil) && thread.BreakpointConditionMet return (thread.CurrentBreakpoint != nil) && thread.BreakpointConditionMet
} }
func (thread *Thread) onTriggeredTempBreakpoint() bool { func (thread *Thread) onTriggeredInternalBreakpoint() bool {
return thread.onTriggeredBreakpoint() && thread.CurrentBreakpoint.Internal() return thread.onTriggeredBreakpoint() && thread.CurrentBreakpoint.Internal()
} }

@ -120,7 +120,7 @@ func (d *Debugger) Restart() error {
if oldBp.ID < 0 { if oldBp.ID < 0 {
continue continue
} }
newBp, err := p.SetBreakpoint(oldBp.Addr) newBp, err := p.SetBreakpoint(oldBp.Addr, proc.UserBreakpoint, nil)
if err != nil { if err != nil {
return err return err
} }
@ -224,7 +224,7 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin
return nil, err return nil, err
} }
bp, err := d.process.SetBreakpoint(addr) bp, err := d.process.SetBreakpoint(addr, proc.UserBreakpoint, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -254,7 +254,7 @@ func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
} }
func (d *Debugger) CancelNext() error { func (d *Debugger) CancelNext() error {
return d.process.ClearTempBreakpoints() return d.process.ClearInternalBreakpoints()
} }
func copyBreakpointInfo(bp *proc.Breakpoint, requested *api.Breakpoint) (err error) { func copyBreakpointInfo(bp *proc.Breakpoint, requested *api.Breakpoint) (err error) {