Set CurrentBreakpoint on DebuggedProcess
This commit is contained in:
parent
42a57ad285
commit
e5a4a5ae9b
@ -31,6 +31,7 @@ type DebuggedProcess struct {
|
||||
HWBreakPoints [4]*BreakPoint
|
||||
BreakPoints map[uint64]*BreakPoint
|
||||
Threads map[int]*ThreadContext
|
||||
CurrentBreakpoint *BreakPoint
|
||||
CurrentThread *ThreadContext
|
||||
dwarf *dwarf.Data
|
||||
goSymTable *gosym.Table
|
||||
@ -280,13 +281,13 @@ func (dbp *DebuggedProcess) next() error {
|
||||
}
|
||||
|
||||
for {
|
||||
thread, breakpoint, err := trapWait(dbp, -1)
|
||||
thread, err := trapWait(dbp, -1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Check if we've hit a breakpoint.
|
||||
if breakpoint != nil {
|
||||
if err = thread.clearTempBreakpoint(breakpoint.Addr); err != nil {
|
||||
if dbp.CurrentBreakpoint != nil {
|
||||
if err = thread.clearTempBreakpoint(dbp.CurrentBreakpoint.Addr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -319,7 +320,7 @@ func (dbp *DebuggedProcess) Continue() error {
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) resume() error {
|
||||
thread, breakpoint, err := trapWait(dbp, -1)
|
||||
thread, err := trapWait(dbp, -1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -330,8 +331,8 @@ func (dbp *DebuggedProcess) resume() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if breakpoint != nil {
|
||||
if !breakpoint.Temp {
|
||||
if dbp.CurrentBreakpoint != nil {
|
||||
if !dbp.CurrentBreakpoint.Temp {
|
||||
return dbp.Halt()
|
||||
}
|
||||
}
|
||||
@ -512,26 +513,28 @@ func (dbp *DebuggedProcess) clearTempBreakpoints() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (dbp *DebuggedProcess) handleBreakpointOnThread(id int) (*ThreadContext, *BreakPoint, error) {
|
||||
func (dbp *DebuggedProcess) handleBreakpointOnThread(id int) (*ThreadContext, error) {
|
||||
thread, ok := dbp.Threads[id]
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("could not find thread for %d", id)
|
||||
return nil, fmt.Errorf("could not find thread for %d", id)
|
||||
}
|
||||
pc, err := thread.CurrentPC()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
// Check for hardware breakpoint
|
||||
for _, bp := range dbp.HWBreakPoints {
|
||||
if bp != nil && bp.Addr == pc {
|
||||
return thread, bp, nil
|
||||
dbp.CurrentBreakpoint = bp
|
||||
return thread, nil
|
||||
}
|
||||
}
|
||||
// Check to see if we have hit a software breakpoint.
|
||||
if bp, ok := dbp.BreakPoints[pc-1]; ok {
|
||||
return thread, bp, nil
|
||||
dbp.CurrentBreakpoint = bp
|
||||
return thread, nil
|
||||
}
|
||||
return thread, nil, nil
|
||||
return thread, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) run(fn func() error) error {
|
||||
@ -540,6 +543,7 @@ func (dbp *DebuggedProcess) run(fn func() error) error {
|
||||
}
|
||||
dbp.running = true
|
||||
dbp.halt = false
|
||||
dbp.CurrentBreakpoint = nil
|
||||
defer func() { dbp.running = false }()
|
||||
if err := fn(); err != nil {
|
||||
if _, ok := err.(ManualStopError); !ok {
|
||||
|
||||
@ -171,17 +171,17 @@ func (dbp *DebuggedProcess) findExecutable() (*macho.File, error) {
|
||||
return exe, nil
|
||||
}
|
||||
|
||||
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, *BreakPoint, error) {
|
||||
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) {
|
||||
port := C.mach_port_wait(dbp.os.portSet)
|
||||
|
||||
switch port {
|
||||
case dbp.os.notificationPort:
|
||||
_, status, err := wait(dbp.Pid, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
dbp.exited = true
|
||||
return nil, nil, ProcessExitedError{Pid: dbp.Pid, Status: status.ExitStatus()}
|
||||
return nil, ProcessExitedError{Pid: dbp.Pid, Status: status.ExitStatus()}
|
||||
case C.MACH_RCV_INTERRUPTED:
|
||||
if !dbp.halt {
|
||||
// Call trapWait again, it seems
|
||||
@ -189,9 +189,9 @@ func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, *BreakPoint, error
|
||||
// process natural death _sometimes_.
|
||||
return trapWait(dbp, pid)
|
||||
}
|
||||
return nil, nil, ManualStopError{}
|
||||
return nil, ManualStopError{}
|
||||
case 0:
|
||||
return nil, nil, fmt.Errorf("error while waiting for task")
|
||||
return nil, fmt.Errorf("error while waiting for task")
|
||||
}
|
||||
|
||||
// Since we cannot be notified of new threads on OS X
|
||||
|
||||
@ -216,11 +216,11 @@ func stopped(pid int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, *BreakPoint, error) {
|
||||
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) {
|
||||
for {
|
||||
wpid, status, err := wait(pid, 0)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("wait err %s %d", err, pid)
|
||||
return nil, fmt.Errorf("wait err %s %d", err, pid)
|
||||
}
|
||||
if wpid == 0 {
|
||||
continue
|
||||
@ -231,29 +231,29 @@ func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, *BreakPoint, error
|
||||
|
||||
if status.Exited() && wpid == dbp.Pid {
|
||||
dbp.exited = true
|
||||
return nil, nil, ProcessExitedError{Pid: wpid, Status: status.ExitStatus()}
|
||||
return nil, ProcessExitedError{Pid: wpid, Status: status.ExitStatus()}
|
||||
}
|
||||
if status.StopSignal() == sys.SIGTRAP && status.TrapCause() == sys.PTRACE_EVENT_CLONE {
|
||||
// A traced thread has cloned a new thread, grab the pid and
|
||||
// add it to our list of traced threads.
|
||||
cloned, err := sys.PtraceGetEventMsg(wpid)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("could not get event message: %s", err)
|
||||
return nil, fmt.Errorf("could not get event message: %s", err)
|
||||
}
|
||||
|
||||
th, err := dbp.addThread(int(cloned), false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = th.Continue()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
|
||||
return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
|
||||
}
|
||||
|
||||
err = dbp.Threads[int(wpid)].Continue()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
|
||||
return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@ -261,7 +261,7 @@ func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, *BreakPoint, error
|
||||
return dbp.handleBreakpointOnThread(wpid)
|
||||
}
|
||||
if status.StopSignal() == sys.SIGSTOP && dbp.halt {
|
||||
return nil, nil, ManualStopError{}
|
||||
return nil, ManualStopError{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ func (thread *ThreadContext) CallFn(name string, fn func(*ThreadContext) error)
|
||||
if err := thread.Continue(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, _, err = trapWait(thread.Process, -1); err != nil {
|
||||
if _, err = trapWait(thread.Process, -1); err != nil {
|
||||
return err
|
||||
}
|
||||
return fn(thread)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user