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

@ -51,7 +51,7 @@ type Process struct {
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
@ -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{}
} if bp, ok := dbp.FindBreakpoint(addr); ok {
return dbp.setBreakpoint(dbp.CurrentThread.ID, addr, UserBreakpoint) return nil, BreakpointExistsError{bp.File, bp.Line, bp.Addr}
} }
// SetTempBreakpoint sets a temp breakpoint. Used during 'next' operations. f, l, fn := dbp.goSymTable.PCToLine(uint64(addr))
func (dbp *Process) SetTempBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error) { if fn == nil {
bp, err := dbp.setBreakpoint(dbp.CurrentThread.ID, addr, kind) 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) {