Ensure thread is stopped before setting breakpoint

For hardware breakpoints we have to set them on every thread. It could
be the case that another thread is running. Stop it first, set the
breakpoint, then continue it.
This commit is contained in:
Derek Parker 2015-06-24 09:29:16 -05:00
parent 7c8fd02685
commit b35a743a3c
5 changed files with 23 additions and 5 deletions

@ -90,8 +90,15 @@ func (dbp *Process) setBreakpoint(tid int, addr uint64, temp bool) (*Breakpoint,
if used {
continue
}
for t, _ := range dbp.Threads {
if err := dbp.setHardwareBreakpoint(i, t, addr); err != nil {
for tid, t := range dbp.Threads {
if t.running {
err := t.Halt()
if err != nil {
return nil, err
}
defer t.Continue()
}
if err := dbp.setHardwareBreakpoint(i, tid, addr); err != nil {
return nil, fmt.Errorf("could not set hardware breakpoint on thread %d: %s", t, err)
}
}

@ -271,12 +271,15 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
continue
}
if status.StopSignal() == sys.SIGTRAP {
th.running = false
return dbp.handleBreakpointOnThread(wpid)
}
if status.StopSignal() == sys.SIGTRAP && dbp.halt {
th.running = false
return th, nil
}
if status.StopSignal() == sys.SIGSTOP && dbp.halt {
th.running = false
return nil, ManualStopError{}
}
if th != nil {

@ -65,7 +65,11 @@ func (thread *Thread) Continue() error {
// Otherwise we simply execute the next instruction.
func (thread *Thread) Step() (err error) {
thread.singleStepping = true
defer func() { thread.singleStepping = false }()
thread.running = true
defer func() {
thread.singleStepping = false
thread.running = false
}()
pc, err := thread.PC()
if err != nil {
return err

@ -18,6 +18,7 @@ func (t *Thread) Halt() error {
if kret != C.KERN_SUCCESS {
return fmt.Errorf("could not suspend thread %d", t.Id)
}
t.running = false
return nil
}
@ -35,6 +36,7 @@ func (t *Thread) singleStep() error {
}
func (t *Thread) resume() error {
t.running = true
// TODO(dp) set flag for ptrace stops
var err error
t.dbp.execPtraceFunc(func() { err = PtraceCont(t.dbp.Pid, 0) })

@ -18,16 +18,18 @@ func (t *Thread) Halt() error {
}
err := sys.Tgkill(t.dbp.Pid, t.Id, sys.SIGSTOP)
if err != nil {
return fmt.Errorf("Halt err %s %d", err, t.Id)
return fmt.Errorf("halt err %s on thread %d", err, t.Id)
}
_, _, err = wait(t.Id, 0)
if err != nil {
return fmt.Errorf("wait err %s %d", err, t.Id)
return fmt.Errorf("wait err %s on thread %d", err, t.Id)
}
t.running = false
return nil
}
func (t *Thread) resume() (err error) {
t.running = true
t.dbp.execPtraceFunc(func() { err = PtraceCont(t.Id, 0) })
return
}