提交 e4426fa5 编写于 作者: D Derek Parker

Return breakpoint directly from trapWait

上级 e7a9daf2
......@@ -279,17 +279,15 @@ func (dbp *DebuggedProcess) next() error {
}
for {
thread, err := trapWait(dbp, -1)
thread, breakpoint, err := trapWait(dbp, -1)
if err != nil {
return err
}
pc, err := thread.CurrentPC()
if err != nil {
// Check if we've hit a breakpoint.
if breakpoint != nil {
if err = thread.clearTempBreakpoint(breakpoint.Addr); err != nil {
return err
}
// Check if we've hit a software breakpoint. If so, reset PC.
if err = thread.clearTempBreakpoint(pc - 1); err != nil {
return err
}
// Grab the current goroutine for this thread.
tg, err := thread.curG()
......@@ -316,9 +314,11 @@ func (dbp *DebuggedProcess) Continue() error {
return err
}
}
return dbp.run(dbp.resume)
}
fn := func() error {
thread, err := trapWait(dbp, -1)
func (dbp *DebuggedProcess) resume() error {
thread, breakpoint, err := trapWait(dbp, -1)
if err != nil {
return err
}
......@@ -329,41 +329,24 @@ func (dbp *DebuggedProcess) Continue() error {
if err != nil {
return err
}
if breakpoint != nil {
if !breakpoint.Temp {
return dbp.Halt()
}
}
// Check to see if we hit a runtime.breakpoint
fn := dbp.GoSymTable.PCToFunc(pc)
if fn != nil && fn.Name == "runtime.breakpoint" {
// step twice to get back to user code
for i := 0; i < 2; i++ {
err = thread.Step()
if err != nil {
if err = thread.Step(); err != nil {
return err
}
}
dbp.Halt()
return nil
}
// Check for hardware breakpoint
for _, bp := range dbp.HWBreakPoints {
if bp != nil && bp.Addr == pc {
if !bp.Temp {
return dbp.Halt()
}
return nil
}
}
// Check to see if we have hit a software breakpoint.
if bp, ok := dbp.BreakPoints[pc-1]; ok {
if !bp.Temp {
return dbp.Halt()
}
return nil
}
return fmt.Errorf("unrecognized breakpoint %#v", pc)
}
return dbp.run(fn)
}
// Steps through process.
......
......@@ -171,17 +171,17 @@ func (dbp *DebuggedProcess) findExecutable() (*macho.File, error) {
return exe, nil
}
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) {
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, *BreakPoint, 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, err
return nil, nil, err
}
dbp.exited = true
return nil, ProcessExitedError{Pid: dbp.Pid, Status: status.ExitStatus()}
return nil, 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, error) {
// process natural death _sometimes_.
return trapWait(dbp, pid)
}
return nil, ManualStopError{}
return nil, nil, ManualStopError{}
case 0:
return nil, fmt.Errorf("error while waiting for task")
return nil, nil, fmt.Errorf("error while waiting for task")
}
// Since we cannot be notified of new threads on OS X
......@@ -199,9 +199,24 @@ func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) {
dbp.updateThreadList()
thread, ok := dbp.Threads[int(port)]
if !ok {
return nil, fmt.Errorf("could not find thread for %d", port)
return nil, nil, fmt.Errorf("could not find thread for %d", port)
}
return thread, nil
pc, err := thread.CurrentPC()
if err != nil {
return nil, nil, err
}
// Check for hardware breakpoint
for _, bp := range dbp.HWBreakPoints {
if bp != nil && bp.Addr == pc {
return thread, bp, nil
}
}
// Check to see if we have hit a software breakpoint.
if bp, ok := dbp.BreakPoints[pc-1]; ok {
return thread, bp, nil
}
return thread, nil, nil
}
func wait(pid, options int) (int, *sys.WaitStatus, error) {
......
......@@ -216,11 +216,11 @@ func stopped(pid int) bool {
return false
}
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) {
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, *BreakPoint, error) {
for {
wpid, status, err := wait(pid, 0)
if err != nil {
return nil, fmt.Errorf("wait err %s %d", err, pid)
return nil, nil, fmt.Errorf("wait err %s %d", err, pid)
}
if wpid == 0 {
continue
......@@ -231,41 +231,55 @@ func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) {
if status.Exited() && wpid == dbp.Pid {
dbp.exited = true
return nil, ProcessExitedError{Pid: wpid, Status: status.ExitStatus()}
return nil, 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, fmt.Errorf("could not get event message: %s", err)
return nil, nil, fmt.Errorf("could not get event message: %s", err)
}
th, err := dbp.addThread(int(cloned), false)
if err != nil {
return nil, err
return nil, nil, err
}
err = th.Continue()
if err != nil {
return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
return nil, nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
}
err = dbp.Threads[int(wpid)].Continue()
if err != nil {
return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
return nil, nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
}
continue
}
if status.StopSignal() == sys.SIGTRAP {
thread, ok := dbp.Threads[wpid]
if !ok {
return nil, fmt.Errorf("could not find thread for %d", wpid)
return nil, nil, fmt.Errorf("could not find thread for %d", wpid)
}
return thread, nil
pc, err := thread.CurrentPC()
if err != nil {
return nil, nil, err
}
// Check for hardware breakpoint
for _, bp := range dbp.HWBreakPoints {
if bp != nil && bp.Addr == pc {
return thread, bp, nil
}
}
// Check to see if we have hit a software breakpoint.
if bp, ok := dbp.BreakPoints[pc-1]; ok {
return thread, bp, nil
}
return thread, nil, nil
}
if status.StopSignal() == sys.SIGSTOP && dbp.halt {
return nil, ManualStopError{}
return nil, 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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册