From b35a743a3c34d0a216e97a39a57e6668572cbe86 Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Wed, 24 Jun 2015 09:29:16 -0500 Subject: [PATCH] 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. --- proc/breakpoints.go | 11 +++++++++-- proc/proc_linux.go | 3 +++ proc/threads.go | 6 +++++- proc/threads_darwin.go | 2 ++ proc/threads_linux.go | 6 ++++-- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/proc/breakpoints.go b/proc/breakpoints.go index 3acf51f0..ae51d364 100644 --- a/proc/breakpoints.go +++ b/proc/breakpoints.go @@ -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) } } diff --git a/proc/proc_linux.go b/proc/proc_linux.go index 53414d32..90b47225 100644 --- a/proc/proc_linux.go +++ b/proc/proc_linux.go @@ -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 { diff --git a/proc/threads.go b/proc/threads.go index 859d6ddb..ed15714e 100644 --- a/proc/threads.go +++ b/proc/threads.go @@ -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 diff --git a/proc/threads_darwin.go b/proc/threads_darwin.go index 7ef1e154..40a1271a 100644 --- a/proc/threads_darwin.go +++ b/proc/threads_darwin.go @@ -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) }) diff --git a/proc/threads_linux.go b/proc/threads_linux.go index 28572b07..e737463a 100644 --- a/proc/threads_linux.go +++ b/proc/threads_linux.go @@ -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 }