提交 178589a4 编写于 作者: A aarzilli 提交者: Derek Parker

proc: breakpoints refactoring

Move some duplicate code, related to breakpoints, that was in both
backends into a single place.
This is in preparation to solve issue #844 (conditional breakpoints
make step and next fail) which will make this common breakpoint code
more complicated.
上级 8d34bb5b
......@@ -152,3 +152,104 @@ type NoBreakpointError struct {
func (nbp NoBreakpointError) Error() string {
return fmt.Sprintf("no breakpoint at %#v", nbp.Addr)
}
type BreakpointMap struct {
M map[uint64]*Breakpoint
breakpointIDCounter int
internalBreakpointIDCounter int
}
func NewBreakpointMap() BreakpointMap {
return BreakpointMap{
M: make(map[uint64]*Breakpoint),
}
}
func (bpmap *BreakpointMap) ResetBreakpointIDCounter() {
bpmap.breakpointIDCounter = 0
}
type writeBreakpointFn func(addr uint64) (file string, line int, fn *Function, originalData []byte, err error)
type clearBreakpointFn func(*Breakpoint) error
// Set creates a breakpoint at addr calling writeBreakpoint. Do not call this
// function, call proc.Process.SetBreakpoint instead, this function exists
// to implement proc.Process.SetBreakpoint.
func (bpmap *BreakpointMap) Set(addr uint64, kind BreakpointKind, cond ast.Expr, writeBreakpoint writeBreakpointFn) (*Breakpoint, error) {
if bp, ok := bpmap.M[addr]; ok {
return bp, BreakpointExistsError{bp.File, bp.Line, bp.Addr}
}
f, l, fn, originalData, err := writeBreakpoint(addr)
if err != nil {
return nil, err
}
newBreakpoint := &Breakpoint{
FunctionName: fn.Name,
File: f,
Line: l,
Addr: addr,
Kind: kind,
Cond: cond,
OriginalData: originalData,
HitCount: map[int]uint64{},
}
if kind != UserBreakpoint {
bpmap.internalBreakpointIDCounter++
newBreakpoint.ID = bpmap.internalBreakpointIDCounter
} else {
bpmap.breakpointIDCounter++
newBreakpoint.ID = bpmap.breakpointIDCounter
}
bpmap.M[addr] = newBreakpoint
return newBreakpoint, nil
}
// SetWithID creates a breakpoint at addr, with the specified ID.
func (bpmap *BreakpointMap) SetWithID(id int, addr uint64, writeBreakpoint writeBreakpointFn) (*Breakpoint, error) {
bp, err := bpmap.Set(addr, UserBreakpoint, nil, writeBreakpoint)
if err == nil {
bp.ID = id
bpmap.breakpointIDCounter--
}
return bp, err
}
// Clear clears the breakpoint at addr.
// Do not call this function call proc.Process.ClearBreakpoint instead.
func (bpmap *BreakpointMap) Clear(addr uint64, clearBreakpoint clearBreakpointFn) (*Breakpoint, error) {
bp, ok := bpmap.M[addr]
if !ok {
return nil, NoBreakpointError{Addr: addr}
}
if err := clearBreakpoint(bp); err != nil {
return nil, err
}
delete(bpmap.M, addr)
return bp, nil
}
// ClearInternalBreakpoints removes all internal breakpoints from the map,
// calling clearBreakpoint on each one.
// Do not call this function, call proc.Process.ClearInternalBreakpoints
// instead, this function is used to implement that.
func (bpmap *BreakpointMap) ClearInternalBreakpoints(clearBreakpoint clearBreakpointFn) error {
for addr, bp := range bpmap.M {
if !bp.Internal() {
continue
}
if err := clearBreakpoint(bp); err != nil {
return err
}
delete(bpmap.M, addr)
}
return nil
}
......@@ -144,7 +144,7 @@ func (r *OffsetReaderAt) ReadMemory(buf []byte, addr uintptr) (n int, err error)
type Process struct {
bi proc.BinaryInfo
core *Core
breakpoints map[uint64]*proc.Breakpoint
breakpoints proc.BreakpointMap
currentThread *Thread
selectedGoroutine *proc.G
allGCache []*proc.G
......@@ -167,7 +167,7 @@ func OpenCore(corePath, exePath string) (*Process, error) {
}
p := &Process{
core: core,
breakpoints: make(map[uint64]*proc.Breakpoint),
breakpoints: proc.NewBreakpointMap(),
bi: proc.NewBinaryInfo("linux", "amd64"),
}
for _, thread := range core.Threads {
......@@ -258,8 +258,8 @@ func (t *Thread) SetCurrentBreakpoint() error {
return nil
}
func (p *Process) Breakpoints() map[uint64]*proc.Breakpoint {
return p.breakpoints
func (p *Process) Breakpoints() *proc.BreakpointMap {
return &p.breakpoints
}
func (p *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) {
......
......@@ -40,7 +40,7 @@ func Disassemble(dbp Process, g *G, startPC, endPC uint64) ([]AsmInstruction, er
return disassemble(mem, regs, dbp.Breakpoints(), dbp.BinInfo(), startPC, endPC)
}
func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints map[uint64]*Breakpoint, bi *BinaryInfo, startPC, endPC uint64) ([]AsmInstruction, error) {
func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startPC, endPC uint64) ([]AsmInstruction, error) {
mem := make([]byte, int(endPC-startPC))
_, err := memrw.ReadMemory(mem, uintptr(startPC))
if err != nil {
......@@ -56,7 +56,7 @@ func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints map[uint64]
}
for len(mem) > 0 {
bp, atbp := breakpoints[pc]
bp, atbp := breakpoints.M[pc]
if atbp {
for i := range bp.OriginalData {
mem[i] = bp.OriginalData[i]
......
......@@ -111,9 +111,7 @@ type Process struct {
manualStopRequested bool
breakpoints map[uint64]*proc.Breakpoint
breakpointIDCounter int
internalBreakpointIDCounter int
breakpoints proc.BreakpointMap
gcmdok bool // true if the stub supports g and G commands
threadStopInfo bool // true if the stub supports qThreadStopInfo
......@@ -170,7 +168,7 @@ func New(process *os.Process) *Process {
},
threads: make(map[int]*Thread),
bi: proc.NewBinaryInfo(runtime.GOOS, runtime.GOARCH),
breakpoints: make(map[uint64]*proc.Breakpoint),
breakpoints: proc.NewBreakpointMap(),
gcmdok: true,
threadStopInfo: true,
process: process,
......@@ -319,12 +317,10 @@ func (p *Process) Connect(conn net.Conn, path string, pid int) error {
panicpc, err := proc.FindFunctionLocation(p, "runtime.startpanic", true, 0)
if err == nil {
bp, err := p.SetBreakpoint(panicpc, proc.UserBreakpoint, nil)
bp, err := p.breakpoints.SetWithID(-1, panicpc, p.writeBreakpoint)
if err == nil {
bp.Name = proc.UnrecoveredPanic
bp.Variables = []string{"runtime.curg._panic.arg"}
bp.ID = -1
p.breakpointIDCounter--
}
}
......@@ -816,7 +812,7 @@ func (p *Process) Restart(pos string) error {
}
p.selectedGoroutine, _ = proc.GetG(p.CurrentThread())
for addr := range p.breakpoints {
for addr := range p.breakpoints.M {
p.conn.setBreakpoint(addr)
}
......@@ -918,7 +914,7 @@ func (p *Process) Direction(dir proc.Direction) error {
if p.conn.direction == dir {
return nil
}
for _, bp := range p.Breakpoints() {
for _, bp := range p.Breakpoints().M {
if bp.Internal() {
return ErrDirChange
}
......@@ -927,89 +923,60 @@ func (p *Process) Direction(dir proc.Direction) error {
return nil
}
func (p *Process) Breakpoints() map[uint64]*proc.Breakpoint {
return p.breakpoints
func (p *Process) Breakpoints() *proc.BreakpointMap {
return &p.breakpoints
}
func (p *Process) FindBreakpoint(pc uint64) (*proc.Breakpoint, bool) {
// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
if bp, ok := p.breakpoints[pc-uint64(p.bi.Arch.BreakpointSize())]; ok {
if bp, ok := p.breakpoints.M[pc-uint64(p.bi.Arch.BreakpointSize())]; ok {
return bp, true
}
// Directly use addr to lookup breakpoint.
if bp, ok := p.breakpoints[pc]; ok {
if bp, ok := p.breakpoints.M[pc]; ok {
return bp, true
}
return nil, false
}
func (p *Process) SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error) {
if bp, ok := p.breakpoints[addr]; ok {
return bp, proc.BreakpointExistsError{bp.File, bp.Line, bp.Addr}
}
func (p *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, []byte, error) {
f, l, fn := p.bi.PCToLine(uint64(addr))
if fn == nil {
return nil, proc.InvalidAddressError{Address: addr}
return "", 0, nil, nil, proc.InvalidAddressError{Address: addr}
}
newBreakpoint := &proc.Breakpoint{
FunctionName: fn.Name,
File: f,
Line: l,
Addr: addr,
Kind: kind,
Cond: cond,
HitCount: map[int]uint64{},
if err := p.conn.setBreakpoint(addr); err != nil {
return "", 0, nil, nil, err
}
if kind != proc.UserBreakpoint {
p.internalBreakpointIDCounter++
newBreakpoint.ID = p.internalBreakpointIDCounter
} else {
p.breakpointIDCounter++
newBreakpoint.ID = p.breakpointIDCounter
}
return f, l, fn, nil, nil
}
if err := p.conn.setBreakpoint(addr); err != nil {
return nil, err
}
p.breakpoints[addr] = newBreakpoint
return newBreakpoint, nil
func (p *Process) SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error) {
return p.breakpoints.Set(addr, kind, cond, p.writeBreakpoint)
}
func (p *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) {
if p.exited {
return nil, &proc.ProcessExitedError{Pid: p.conn.pid}
}
bp := p.breakpoints[addr]
if bp == nil {
return nil, proc.NoBreakpointError{Addr: addr}
}
if err := p.conn.clearBreakpoint(addr); err != nil {
return nil, err
}
delete(p.breakpoints, addr)
return bp, nil
return p.breakpoints.Clear(addr, func(bp *proc.Breakpoint) error {
return p.conn.clearBreakpoint(bp.Addr)
})
}
func (p *Process) ClearInternalBreakpoints() error {
for _, bp := range p.breakpoints {
if !bp.Internal() {
continue
}
if _, err := p.ClearBreakpoint(bp.Addr); err != nil {
return p.breakpoints.ClearInternalBreakpoints(func(bp *proc.Breakpoint) error {
if err := p.conn.clearBreakpoint(bp.Addr); err != nil {
return err
}
}
for i := range p.threads {
if p.threads[i].CurrentBreakpoint != nil && p.threads[i].CurrentBreakpoint.Internal() {
p.threads[i].CurrentBreakpoint = nil
for _, thread := range p.threads {
if thread.CurrentBreakpoint == bp {
thread.CurrentBreakpoint = nil
}
}
}
return nil
return nil
})
}
type threadUpdater struct {
......@@ -1186,7 +1153,7 @@ func (t *Thread) BinInfo() *proc.BinaryInfo {
func (t *Thread) stepInstruction(tu *threadUpdater) error {
pc := t.regs.PC()
if _, atbp := t.p.breakpoints[pc]; atbp {
if _, atbp := t.p.breakpoints.M[pc]; atbp {
err := t.p.conn.clearBreakpoint(pc)
if err != nil {
return err
......@@ -1354,7 +1321,7 @@ func (t *Thread) reloadGAtPC() error {
// around by clearing and re-setting the breakpoint in a specific sequence
// with the memory writes.
// Additionally all breakpoints in [pc, pc+len(movinstr)] need to be removed
for addr := range t.p.breakpoints {
for addr := range t.p.breakpoints.M {
if addr >= pc && addr <= pc+uint64(len(movinstr)) {
err := t.p.conn.clearBreakpoint(addr)
if err != nil {
......
......@@ -97,7 +97,7 @@ type ProcessManipulation interface {
// BreakpointManipulation is an interface for managing breakpoints.
type BreakpointManipulation interface {
Breakpoints() map[uint64]*Breakpoint
Breakpoints() *BreakpointMap
SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error)
ClearBreakpoint(addr uint64) (*Breakpoint, error)
ClearInternalBreakpoints() error
......
......@@ -17,7 +17,7 @@ type Process struct {
// Breakpoint table, holds information on breakpoints.
// Maps instruction address to Breakpoint struct.
breakpoints map[uint64]*proc.Breakpoint
breakpoints proc.BreakpointMap
// List of threads mapped as such: pid -> *Thread
threads map[int]*Thread
......@@ -29,19 +29,17 @@ type Process struct {
// Normally selectedGoroutine is currentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread
selectedGoroutine *proc.G
allGCache []*proc.G
os *OSProcessDetails
breakpointIDCounter int
internalBreakpointIDCounter int
firstStart bool
haltMu sync.Mutex
halt bool
resumeChan chan<- struct{}
exited bool
ptraceChan chan func()
ptraceDoneChan chan interface{}
childProcess bool // this process was launched, not attached to
manualStopRequested bool
allGCache []*proc.G
os *OSProcessDetails
firstStart bool
haltMu sync.Mutex
halt bool
resumeChan chan<- struct{}
exited bool
ptraceChan chan func()
ptraceDoneChan chan interface{}
childProcess bool // this process was launched, not attached to
manualStopRequested bool
}
// New returns an initialized Process struct. Before returning,
......@@ -52,7 +50,7 @@ func New(pid int) *Process {
dbp := &Process{
pid: pid,
threads: make(map[int]*Thread),
breakpoints: make(map[uint64]*proc.Breakpoint),
breakpoints: proc.NewBreakpointMap(),
firstStart: true,
os: new(OSProcessDetails),
ptraceChan: make(chan func()),
......@@ -90,7 +88,7 @@ func (dbp *Process) Detach(kill bool) (err error) {
}
if !kill {
// Clean up any breakpoints we've set.
for _, bp := range dbp.breakpoints {
for _, bp := range dbp.breakpoints.M {
if bp != nil {
_, err := dbp.ClearBreakpoint(bp.Addr)
if err != nil {
......@@ -147,8 +145,8 @@ func (dbp *Process) CurrentThread() proc.Thread {
return dbp.currentThread
}
func (dbp *Process) Breakpoints() map[uint64]*proc.Breakpoint {
return dbp.breakpoints
func (dbp *Process) Breakpoints() *proc.BreakpointMap {
return &dbp.breakpoints
}
// LoadInformation finds the executable and then uses it
......@@ -193,52 +191,29 @@ func (dbp *Process) ManualStopRequested() bool {
return msr
}
// 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
// ptrace actions needing the thread to be in a signal-delivery-stop.
func (dbp *Process) SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error) {
tid := dbp.currentThread.ID
if bp, ok := dbp.FindBreakpoint(addr); ok {
return bp, proc.BreakpointExistsError{bp.File, bp.Line, bp.Addr}
}
func (dbp *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, []byte, error) {
f, l, fn := dbp.bi.PCToLine(uint64(addr))
if fn == nil {
return nil, proc.InvalidAddressError{Address: addr}
}
newBreakpoint := &proc.Breakpoint{
FunctionName: fn.Name,
File: f,
Line: l,
Addr: addr,
Kind: kind,
Cond: cond,
HitCount: map[int]uint64{},
}
if kind != proc.UserBreakpoint {
dbp.internalBreakpointIDCounter++
newBreakpoint.ID = dbp.internalBreakpointIDCounter
} else {
dbp.breakpointIDCounter++
newBreakpoint.ID = dbp.breakpointIDCounter
return "", 0, nil, nil, proc.InvalidAddressError{Address: addr}
}
thread := dbp.threads[tid]
originalData := make([]byte, dbp.bi.Arch.BreakpointSize())
_, err := thread.ReadMemory(originalData, uintptr(addr))
_, err := dbp.currentThread.ReadMemory(originalData, uintptr(addr))
if err != nil {
return nil, err
return "", 0, nil, nil, err
}
if err := dbp.writeSoftwareBreakpoint(thread, addr); err != nil {
return nil, err
if err := dbp.writeSoftwareBreakpoint(dbp.currentThread, addr); err != nil {
return "", 0, nil, nil, err
}
newBreakpoint.OriginalData = originalData
dbp.breakpoints[addr] = newBreakpoint
return newBreakpoint, nil
return f, l, fn, originalData, nil
}
// 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
// ptrace actions needing the thread to be in a signal-delivery-stop.
func (dbp *Process) SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error) {
return dbp.breakpoints.Set(addr, kind, cond, dbp.writeBreakpoint)
}
// ClearBreakpoint clears the breakpoint at addr.
......@@ -246,18 +221,7 @@ func (dbp *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) {
if dbp.exited {
return nil, &proc.ProcessExitedError{Pid: dbp.Pid()}
}
bp, ok := dbp.FindBreakpoint(addr)
if !ok {
return nil, proc.NoBreakpointError{Addr: addr}
}
if _, err := dbp.currentThread.ClearBreakpoint(bp); err != nil {
return nil, err
}
delete(dbp.breakpoints, addr)
return bp, nil
return dbp.breakpoints.Clear(addr, dbp.currentThread.ClearBreakpoint)
}
func (dbp *Process) ContinueOnce() (proc.Thread, error) {
......@@ -377,11 +341,11 @@ func (dbp *Process) Halt() (err error) {
// FindBreakpoint finds the breakpoint for the given pc.
func (dbp *Process) FindBreakpoint(pc uint64) (*proc.Breakpoint, bool) {
// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
if bp, ok := dbp.breakpoints[pc-uint64(dbp.bi.Arch.BreakpointSize())]; ok {
if bp, ok := dbp.breakpoints.M[pc-uint64(dbp.bi.Arch.BreakpointSize())]; ok {
return bp, true
}
// Directly use addr to lookup breakpoint.
if bp, ok := dbp.breakpoints[pc]; ok {
if bp, ok := dbp.breakpoints.M[pc]; ok {
return bp, true
}
return nil, false
......@@ -406,12 +370,10 @@ func initializeDebugProcess(dbp *Process, path string) (*Process, error) {
panicpc, err := proc.FindFunctionLocation(dbp, "runtime.startpanic", true, 0)
if err == nil {
bp, err := dbp.SetBreakpoint(panicpc, proc.UserBreakpoint, nil)
bp, err := dbp.breakpoints.SetWithID(-1, panicpc, dbp.writeBreakpoint)
if err == nil {
bp.Name = proc.UnrecoveredPanic
bp.Variables = []string{"runtime.curg._panic.arg"}
bp.ID = -1
dbp.breakpointIDCounter--
}
}
......@@ -419,20 +381,17 @@ func initializeDebugProcess(dbp *Process, path string) (*Process, error) {
}
func (dbp *Process) ClearInternalBreakpoints() error {
for _, bp := range dbp.breakpoints {
if !bp.Internal() {
continue
}
if _, err := dbp.ClearBreakpoint(bp.Addr); err != nil {
return dbp.breakpoints.ClearInternalBreakpoints(func(bp *proc.Breakpoint) error {
if err := dbp.currentThread.ClearBreakpoint(bp); err != nil {
return err
}
}
for i := range dbp.threads {
if dbp.threads[i].CurrentBreakpoint != nil && dbp.threads[i].CurrentBreakpoint.Internal() {
dbp.threads[i].CurrentBreakpoint = nil
for _, thread := range dbp.threads {
if thread.CurrentBreakpoint == bp {
thread.CurrentBreakpoint = nil
}
}
}
return nil
return nil
})
}
func (dbp *Process) handlePtraceFuncs() {
......
......@@ -65,7 +65,7 @@ func (thread *Thread) StepInstruction() (err error) {
bp, ok := thread.dbp.FindBreakpoint(pc)
if ok {
// Clear the breakpoint so that we can continue execution.
_, err = thread.ClearBreakpoint(bp)
err = thread.ClearBreakpoint(bp)
if err != nil {
return err
}
......@@ -177,11 +177,11 @@ func (th *Thread) ThreadID() int {
}
// ClearBreakpoint clears the specified breakpoint.
func (thread *Thread) ClearBreakpoint(bp *proc.Breakpoint) (*proc.Breakpoint, error) {
func (thread *Thread) ClearBreakpoint(bp *proc.Breakpoint) error {
if _, err := thread.WriteMemory(uintptr(bp.Addr), bp.OriginalData); err != nil {
return nil, fmt.Errorf("could not clear breakpoint %s", err)
return fmt.Errorf("could not clear breakpoint %s", err)
}
return bp, nil
return nil
}
// Registers obtains register values from the debugged process.
......
......@@ -68,7 +68,7 @@ func Next(dbp Process) (err error) {
if dbp.Exited() {
return &ProcessExitedError{Pid: dbp.Pid()}
}
for _, bp := range dbp.Breakpoints() {
for _, bp := range dbp.Breakpoints().M {
if bp.Internal() {
return fmt.Errorf("next while nexting")
}
......@@ -216,7 +216,7 @@ func Step(dbp Process) (err error) {
if dbp.Exited() {
return &ProcessExitedError{Pid: dbp.Pid()}
}
for _, bp := range dbp.Breakpoints() {
for _, bp := range dbp.Breakpoints().M {
if bp.Internal() {
return fmt.Errorf("next while nexting")
}
......
......@@ -361,7 +361,7 @@ type nextTest struct {
func countBreakpoints(p proc.Process) int {
bpcount := 0
for _, bp := range p.Breakpoints() {
for _, bp := range p.Breakpoints().M {
if bp.ID >= 0 {
bpcount++
}
......@@ -422,7 +422,7 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc
}
if countBreakpoints(p) != 0 {
t.Fatal("Not all breakpoints were cleaned up", len(p.Breakpoints()))
t.Fatal("Not all breakpoints were cleaned up", len(p.Breakpoints().M))
}
})
}
......@@ -2272,7 +2272,7 @@ func TestStepConcurrentDirect(t *testing.T) {
_, err = p.ClearBreakpoint(bp.Addr)
assertNoError(err, t, "ClearBreakpoint()")
for _, b := range p.Breakpoints() {
for _, b := range p.Breakpoints().M {
if b.Name == proc.UnrecoveredPanic {
_, err := p.ClearBreakpoint(b.Addr)
assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)")
......@@ -2327,7 +2327,7 @@ func TestStepConcurrentDirect(t *testing.T) {
}
func nextInProgress(p proc.Process) bool {
for _, bp := range p.Breakpoints() {
for _, bp := range p.Breakpoints().M {
if bp.Internal() {
return true
}
......@@ -2343,7 +2343,7 @@ func TestStepConcurrentPtr(t *testing.T) {
_, err = p.SetBreakpoint(pc, proc.UserBreakpoint, nil)
assertNoError(err, t, "SetBreakpoint()")
for _, b := range p.Breakpoints() {
for _, b := range p.Breakpoints().M {
if b.Name == proc.UnrecoveredPanic {
_, err := p.ClearBreakpoint(b.Addr)
assertNoError(err, t, "ClearBreakpoint(unrecovered-panic)")
......
......@@ -411,11 +411,11 @@ func onRuntimeBreakpoint(thread Thread) bool {
}
// onNextGorutine returns true if this thread is on the goroutine requested by the current 'next' command
func onNextGoroutine(thread Thread, breakpoints map[uint64]*Breakpoint) (bool, error) {
func onNextGoroutine(thread Thread, breakpoints *BreakpointMap) (bool, error) {
var bp *Breakpoint
for i := range breakpoints {
if breakpoints[i].Internal() && breakpoints[i].Cond != nil {
bp = breakpoints[i]
for i := range breakpoints.M {
if breakpoints.M[i].Internal() && breakpoints.M[i].Cond != nil {
bp = breakpoints.M[i]
break
}
}
......
......@@ -264,7 +264,7 @@ func (d *Debugger) state() (*api.DebuggerState, error) {
}
}
for _, bp := range d.target.Breakpoints() {
for _, bp := range d.target.Breakpoints().M {
if bp.Internal() {
state.NextInProgress = true
break
......@@ -398,7 +398,7 @@ func (d *Debugger) Breakpoints() []*api.Breakpoint {
func (d *Debugger) breakpoints() []*api.Breakpoint {
bps := []*api.Breakpoint{}
for _, bp := range d.target.Breakpoints() {
for _, bp := range d.target.Breakpoints().M {
if bp.Internal() {
continue
}
......@@ -420,7 +420,7 @@ func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint {
}
func (d *Debugger) findBreakpoint(id int) *proc.Breakpoint {
for _, bp := range d.target.Breakpoints() {
for _, bp := range d.target.Breakpoints().M {
if bp.ID == id {
return bp
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册