1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
7 // TODO(rsc): Imports here after to be in proc.go too in order
8 // for deps.bash to get the right answer.
21 // This is an implementation of the process tracing interface using
22 // Linux's ptrace(2) interface. The implementation is multi-threaded.
23 // Each attached process has an associated monitor thread, and each
24 // running attached thread has an associated "wait" thread. The wait
25 // thread calls wait4 on the thread's TID and reports any wait events
26 // or errors via "debug events". The monitor thread consumes these
27 // wait events and updates the internally maintained state of each
28 // thread. All ptrace calls must run in the monitor thread, so the
29 // monitor executes closures received on the debugReq channel.
31 // As ptrace's documentation is somewhat light, this is heavily based
32 // on information gleaned from the implementation of ptrace found at
33 // http://lxr.linux.no/linux+v2.6.30/kernel/ptrace.c
34 // http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/ptrace.c#L854
35 // as well as experimentation and examination of gdb's behavior.
47 // Each thread can be in one of the following set of states.
48 // Each state satisfies
49 // isRunning() || isStopped() || isZombie() || isTerminal().
51 // Running threads can be sent signals and must be waited on, but they
52 // cannot be inspected using ptrace.
54 // Stopped threads can be inspected and continued, but cannot be
55 // meaningfully waited on. They can be sent signals, but the signals
56 // will be queued until they are running again.
58 // Zombie threads cannot be inspected, continued, or sent signals (and
59 // therefore they cannot be stopped), but they must be waited on.
61 // Terminal threads no longer exist in the OS and thus you can't do
62 // anything with them.
63 type threadState string
66 running threadState = "Running"
67 singleStepping threadState = "SingleStepping" // Transient
68 stopping threadState = "Stopping" // Transient
69 stopped threadState = "Stopped"
70 stoppedBreakpoint threadState = "StoppedBreakpoint"
71 stoppedSignal threadState = "StoppedSignal"
72 stoppedThreadCreate threadState = "StoppedThreadCreate"
73 stoppedExiting threadState = "StoppedExiting"
74 exiting threadState = "Exiting" // Transient (except main thread)
75 exited threadState = "Exited"
76 detached threadState = "Detached"
79 func (ts threadState) isRunning() bool {
80 return ts == running || ts == singleStepping || ts == stopping
83 func (ts threadState) isStopped() bool {
84 return ts == stopped || ts == stoppedBreakpoint || ts == stoppedSignal || ts == stoppedThreadCreate || ts == stoppedExiting
87 func (ts threadState) isZombie() bool { return ts == exiting }
89 func (ts threadState) isTerminal() bool { return ts == exited || ts == detached }
91 func (ts threadState) String() string { return string(ts) }
97 // A breakpoint stores information about a single breakpoint,
98 // including its program counter, the overwritten text if the
99 // breakpoint is installed.
100 type breakpoint struct {
105 func (bp *breakpoint) String() string {
109 return fmt.Sprintf("%#x", bp.pc)
112 // bpinst386 is the breakpoint instruction used on 386 and amd64.
113 var bpinst386 = []byte{0xcc}
115 // A debugEvent represents a reason a thread stopped or a wait error.
116 type debugEvent struct {
122 // A debugReq is a request to execute a closure in the monitor thread.
123 type debugReq struct {
128 // A transitionHandler specifies a function to be called when a thread
129 // changes state and a function to be called when an error occurs in
130 // the monitor. Both run in the monitor thread. Before the monitor
131 // invokes a handler, it removes the handler from the handler queue.
132 // The handler should re-add itself if needed.
133 type transitionHandler struct {
134 handle func(*thread, threadState, threadState)
138 // A process is a Linux process, which consists of a set of threads.
139 // Each running process has one monitor thread, which processes
140 // messages from the debugEvents, debugReqs, and stopReq channels and
141 // calls transition handlers.
143 // To send a message to the monitor thread, first receive from the
144 // ready channel. If the ready channel returns true, the monitor is
145 // still running and will accept a message. If the ready channel
146 // returns false, the monitor is not running (the ready channel has
147 // been closed), and the reason it is not running will be stored in err.
148 type process struct {
150 threads map[int]*thread
151 breakpoints map[uintptr]*breakpoint
153 debugEvents chan *debugEvent
154 debugReqs chan *debugReq
155 stopReq chan os.Error
156 transitionHandlers vector.Vector
160 // A thread represents a Linux thread in another process that is being
161 // debugged. Each running thread has an associated goroutine that
162 // waits for thread updates and sends them to the process monitor.
166 // Whether to ignore the next SIGSTOP received by wait.
167 ignoreNextSigstop bool
169 // Thread state. Only modified via setState.
171 // If state == StoppedBreakpoint
172 breakpoint *breakpoint
173 // If state == StoppedSignal or state == Exited
175 // If state == StoppedThreadCreate
177 // If state == Exited
185 type badState struct {
191 func (e *badState) String() string {
192 return fmt.Sprintf("Thread %d %s from state %v", e.thread.tid, e.message, e.state)
195 type breakpointExistsError Word
197 func (e breakpointExistsError) String() string {
198 return fmt.Sprintf("breakpoint already exists at PC %#x", e)
201 type noBreakpointError Word
203 func (e noBreakpointError) String() string { return fmt.Sprintf("no breakpoint at PC %#x", e) }
205 type newThreadError struct {
211 func (e *newThreadError) String() string {
212 return fmt.Sprintf("newThread wait wanted pid %v and signal %v, got %v and %v", e.Pid, e.StopSignal(), e.wantPid, e.wantSig)
215 type ProcessExited struct{}
217 func (p ProcessExited) String() string { return "process exited" }
223 func (t *thread) ptracePeekText(addr uintptr, out []byte) (int, os.Error) {
224 c, err := syscall.PtracePeekText(t.tid, addr, out)
226 fmt.Printf("peek(%#x) => %v, %v\n", addr, out, err)
228 return c, os.NewSyscallError("ptrace(PEEKTEXT)", err)
231 func (t *thread) ptracePokeText(addr uintptr, out []byte) (int, os.Error) {
232 c, err := syscall.PtracePokeText(t.tid, addr, out)
234 fmt.Printf("poke(%#x, %v) => %v\n", addr, out, err)
236 return c, os.NewSyscallError("ptrace(POKETEXT)", err)
239 func (t *thread) ptraceGetRegs(regs *syscall.PtraceRegs) os.Error {
240 err := syscall.PtraceGetRegs(t.tid, regs)
241 return os.NewSyscallError("ptrace(GETREGS)", err)
244 func (t *thread) ptraceSetRegs(regs *syscall.PtraceRegs) os.Error {
245 err := syscall.PtraceSetRegs(t.tid, regs)
246 return os.NewSyscallError("ptrace(SETREGS)", err)
249 func (t *thread) ptraceSetOptions(options int) os.Error {
250 err := syscall.PtraceSetOptions(t.tid, options)
251 return os.NewSyscallError("ptrace(SETOPTIONS)", err)
254 func (t *thread) ptraceGetEventMsg() (uint, os.Error) {
255 msg, err := syscall.PtraceGetEventMsg(t.tid)
256 return msg, os.NewSyscallError("ptrace(GETEVENTMSG)", err)
259 func (t *thread) ptraceCont() os.Error {
260 err := syscall.PtraceCont(t.tid, 0)
261 return os.NewSyscallError("ptrace(CONT)", err)
264 func (t *thread) ptraceContWithSignal(sig int) os.Error {
265 err := syscall.PtraceCont(t.tid, sig)
266 return os.NewSyscallError("ptrace(CONT)", err)
269 func (t *thread) ptraceStep() os.Error {
270 err := syscall.PtraceSingleStep(t.tid)
271 return os.NewSyscallError("ptrace(SINGLESTEP)", err)
274 func (t *thread) ptraceDetach() os.Error {
275 err := syscall.PtraceDetach(t.tid)
276 return os.NewSyscallError("ptrace(DETACH)", err)
283 var logLock sync.Mutex
285 func (t *thread) logTrace(format string, args ...interface{}) {
290 defer logLock.Unlock()
291 fmt.Fprintf(os.Stderr, "Thread %d", t.tid)
293 var regs syscall.PtraceRegs
294 err := t.ptraceGetRegs(®s)
296 fmt.Fprintf(os.Stderr, "@%x", regs.PC())
299 fmt.Fprint(os.Stderr, ": ")
300 fmt.Fprintf(os.Stderr, format, args...)
301 fmt.Fprint(os.Stderr, "\n")
304 func (t *thread) warn(format string, args ...interface{}) {
306 defer logLock.Unlock()
307 fmt.Fprintf(os.Stderr, "Thread %d: WARNING ", t.tid)
308 fmt.Fprintf(os.Stderr, format, args...)
309 fmt.Fprint(os.Stderr, "\n")
312 func (p *process) logTrace(format string, args ...interface{}) {
317 defer logLock.Unlock()
318 fmt.Fprintf(os.Stderr, "Process %d: ", p.pid)
319 fmt.Fprintf(os.Stderr, format, args...)
320 fmt.Fprint(os.Stderr, "\n")
327 // someStoppedThread returns a stopped thread from the process.
328 // Returns nil if no threads are stopped.
330 // Must be called from the monitor thread.
331 func (p *process) someStoppedThread() *thread {
332 for _, t := range p.threads {
333 if t.state.isStopped() {
340 // someRunningThread returns a running thread from the process.
341 // Returns nil if no threads are running.
343 // Must be called from the monitor thread.
344 func (p *process) someRunningThread() *thread {
345 for _, t := range p.threads {
346 if t.state.isRunning() {
354 * Breakpoint utilities
357 // installBreakpoints adds breakpoints to the attached process.
359 // Must be called from the monitor thread.
360 func (p *process) installBreakpoints() os.Error {
362 main := p.someStoppedThread()
363 for _, b := range p.breakpoints {
364 if b.olddata != nil {
368 b.olddata = make([]byte, len(bpinst386))
369 _, err := main.ptracePeekText(uintptr(b.pc), b.olddata)
375 _, err = main.ptracePokeText(uintptr(b.pc), bpinst386)
383 p.logTrace("installed %d/%d breakpoints", n, len(p.breakpoints))
389 // uninstallBreakpoints removes the installed breakpoints from p.
391 // Must be called from the monitor thread.
392 func (p *process) uninstallBreakpoints() os.Error {
393 if len(p.threads) == 0 {
397 main := p.someStoppedThread()
398 for _, b := range p.breakpoints {
399 if b.olddata == nil {
403 _, err := main.ptracePokeText(uintptr(b.pc), b.olddata)
411 p.logTrace("uninstalled %d/%d breakpoints", n, len(p.breakpoints))
418 * Debug event handling
421 // wait waits for a wait event from this thread and sends it on the
422 // debug events channel for this thread's process. This should be
423 // started in its own goroutine when the attached thread enters a
424 // running state. The goroutine will exit as soon as it sends a debug
426 func (t *thread) wait() {
430 t.logTrace("beginning wait")
431 ev.Waitmsg, ev.err = os.Wait(t.tid, syscall.WALL)
432 if ev.err == nil && ev.Pid != t.tid {
433 panic(fmt.Sprint("Wait returned pid ", ev.Pid, " wanted ", t.tid))
435 if ev.StopSignal() == syscall.SIGSTOP && t.ignoreNextSigstop {
436 // Spurious SIGSTOP. See Thread.Stop().
437 t.ignoreNextSigstop = false
438 err := t.ptraceCont()
442 // If we failed to continue, just let
443 // the stop go through so we can
444 // update the thread's state.
447 // The monitor exited
450 t.proc.debugEvents <- &ev
455 // setState sets this thread's state, starts a wait thread if
456 // necessary, and invokes state transition handlers.
458 // Must be called from the monitor thread.
459 func (t *thread) setState(newState threadState) {
462 t.logTrace("state %v -> %v", oldState, newState)
464 if !oldState.isRunning() && (newState.isRunning() || newState.isZombie()) {
465 // Start waiting on this thread
469 // Invoke state change handlers
470 handlers := t.proc.transitionHandlers
471 if handlers.Len() == 0 {
475 t.proc.transitionHandlers = nil
476 for _, h := range handlers {
477 h := h.(*transitionHandler)
478 h.handle(t, oldState, newState)
482 // sendSigstop sends a SIGSTOP to this thread.
483 func (t *thread) sendSigstop() os.Error {
484 t.logTrace("sending SIGSTOP")
485 err := syscall.Tgkill(t.proc.pid, t.tid, syscall.SIGSTOP)
486 return os.NewSyscallError("tgkill", err)
489 // stopAsync sends SIGSTOP to all threads in state 'running'.
491 // Must be called from the monitor thread.
492 func (p *process) stopAsync() os.Error {
493 for _, t := range p.threads {
494 if t.state == running {
495 err := t.sendSigstop()
505 // doTrap handles SIGTRAP debug events with a cause of 0. These can
506 // be caused either by an installed breakpoint, a breakpoint in the
507 // program text, or by single stepping.
509 // TODO(austin) I think we also get this on an execve syscall.
510 func (ev *debugEvent) doTrap() (threadState, os.Error) {
513 if t.state == singleStepping {
517 // Hit a breakpoint. Linux leaves the program counter after
518 // the breakpoint. If this is an installed breakpoint, we
519 // need to back the PC up to the breakpoint PC.
520 var regs syscall.PtraceRegs
521 err := t.ptraceGetRegs(®s)
526 b, ok := t.proc.breakpoints[uintptr(regs.PC())-uintptr(len(bpinst386))]
528 // We must have hit a breakpoint that was actually in
529 // the program. Leave the IP where it is so we don't
530 // re-execute the breakpoint instruction. Expose the
531 // fact that we stopped with a SIGTRAP.
532 return stoppedSignal, nil
536 t.logTrace("at breakpoint %v, backing up PC from %#x", b, regs.PC())
538 regs.SetPC(uint64(b.pc))
539 err = t.ptraceSetRegs(®s)
543 return stoppedBreakpoint, nil
546 // doPtraceClone handles SIGTRAP debug events with a PTRACE_EVENT_CLONE
547 // cause. It initializes the new thread, adds it to the process, and
548 // returns the appropriate thread state for the existing thread.
549 func (ev *debugEvent) doPtraceClone() (threadState, os.Error) {
552 // Get the TID of the new thread
553 tid, err := t.ptraceGetEventMsg()
558 nt, err := t.proc.newThread(int(tid), syscall.SIGSTOP, true)
563 // Remember the thread
566 return stoppedThreadCreate, nil
569 // doPtraceExit handles SIGTRAP debug events with a PTRACE_EVENT_EXIT
570 // cause. It sets up the thread's state, but does not remove it from
571 // the process. A later WIFEXITED debug event will remove it from the
573 func (ev *debugEvent) doPtraceExit() (threadState, os.Error) {
577 exitStatus, err := t.ptraceGetEventMsg()
581 ws := syscall.WaitStatus(exitStatus)
582 t.logTrace("exited with %v", ws)
585 t.exitStatus = ws.ExitStatus()
587 t.signal = ws.Signal()
590 // We still need to continue this thread and wait on this
591 // thread's WIFEXITED event. We'll delete it then.
592 return stoppedExiting, nil
595 // process handles a debug event. It modifies any thread or process
596 // state as necessary, uninstalls breakpoints if necessary, and stops
597 // any running threads.
598 func (ev *debugEvent) process() os.Error {
607 // Decode wait status.
608 var state threadState
611 state = stoppedSignal
612 t.signal = ev.StopSignal()
613 t.logTrace("stopped with %v", ev)
614 if ev.StopSignal() == syscall.SIGTRAP {
615 // What caused the debug trap?
617 switch cause := ev.TrapCause(); cause {
619 // Breakpoint or single stepping
620 state, err = ev.doTrap()
622 case syscall.PTRACE_EVENT_CLONE:
623 state, err = ev.doPtraceClone()
625 case syscall.PTRACE_EVENT_EXIT:
626 state, err = ev.doPtraceExit()
629 t.warn("Unknown trap cause %d", cause)
634 t.warn("failed to handle trap %v: %v", ev, err)
640 t.proc.threads[t.tid] = nil, false
641 t.logTrace("exited %v", ev)
642 // We should have gotten the exit status in
643 // PTRACE_EVENT_EXIT, but just in case.
644 t.exitStatus = ev.ExitStatus()
648 t.proc.threads[t.tid] = nil, false
649 t.logTrace("signaled %v", ev)
650 // Again, this should be redundant.
651 t.signal = ev.Signal()
654 panic(fmt.Sprintf("Unexpected wait status %v", ev.Waitmsg))
657 // If we sent a SIGSTOP to the thread (indicated by state
658 // Stopping), we might have raced with a different type of
659 // stop. If we didn't get the stop we expected, then the
660 // SIGSTOP we sent is now queued up, so we should ignore the
662 if t.state == stopping && ev.StopSignal() != syscall.SIGSTOP {
663 t.ignoreNextSigstop = true
666 // TODO(austin) If we're in state stopping and get a SIGSTOP,
667 // set state stopped instead of stoppedSignal.
671 if t.proc.someRunningThread() == nil {
672 // Nothing is running, uninstall breakpoints
673 return t.proc.uninstallBreakpoints()
675 // Stop any other running threads
676 return t.proc.stopAsync()
679 // onStop adds a handler for state transitions from running to
680 // non-running states. The handler will be called from the monitor
683 // Must be called from the monitor thread.
684 func (t *thread) onStop(handle func(), onErr func(os.Error)) {
685 // TODO(austin) This is rather inefficient for things like
686 // stepping all threads during a continue. Maybe move
687 // transitionHandlers to the thread, or have both per-thread
688 // and per-process transition handlers.
689 h := &transitionHandler{nil, onErr}
690 h.handle = func(st *thread, old, new threadState) {
691 if t == st && old.isRunning() && !new.isRunning() {
694 t.proc.transitionHandlers.Push(h)
697 t.proc.transitionHandlers.Push(h)
704 // monitor handles debug events and debug requests for p, exiting when
705 // there are no threads left in p.
706 func (p *process) monitor() {
709 // Linux requires that all ptrace calls come from the thread
710 // that originally attached. Prevent the Go scheduler from
711 // migrating us to other OS threads.
712 runtime.LockOSThread()
713 defer runtime.UnlockOSThread()
719 case event := <-p.debugEvents:
720 err = event.process()
722 case req := <-p.debugReqs:
725 case err = <-p.stopReq:
729 if len(p.threads) == 0 {
730 if err == nil && hadThreads {
731 p.logTrace("no more threads; monitor exiting")
732 err = ProcessExited{}
739 // Abort waiting handlers
740 // TODO(austin) How do I stop the wait threads?
741 for _, h := range p.transitionHandlers {
742 h := h.(*transitionHandler)
746 // Indicate that the monitor cannot receive any more messages
751 // do executes f in the monitor thread (and, thus, atomically with
752 // respect to thread state changes). f must not block.
754 // Must NOT be called from the monitor thread.
755 func (p *process) do(f func() os.Error) os.Error {
759 req := &debugReq{f, make(chan os.Error)}
764 // stopMonitor stops the monitor with the given error. If the monitor
765 // is already stopped, does nothing.
766 func (p *process) stopMonitor(err os.Error) {
768 panic("cannot stop the monitor with no error")
776 * Public thread interface
779 func (t *thread) Regs() (Regs, os.Error) {
780 var regs syscall.PtraceRegs
782 err := t.proc.do(func() os.Error {
783 if !t.state.isStopped() {
784 return &badState{t, "cannot get registers", t.state}
786 return t.ptraceGetRegs(®s)
792 setter := func(r *syscall.PtraceRegs) os.Error {
793 return t.proc.do(func() os.Error {
794 if !t.state.isStopped() {
795 return &badState{t, "cannot get registers", t.state}
797 return t.ptraceSetRegs(r)
800 return newRegs(®s, setter), nil
803 func (t *thread) Peek(addr Word, out []byte) (int, os.Error) {
806 err := t.proc.do(func() os.Error {
807 if !t.state.isStopped() {
808 return &badState{t, "cannot peek text", t.state}
812 c, err = t.ptracePeekText(uintptr(addr), out)
819 func (t *thread) Poke(addr Word, out []byte) (int, os.Error) {
822 err := t.proc.do(func() os.Error {
823 if !t.state.isStopped() {
824 return &badState{t, "cannot poke text", t.state}
828 c, err = t.ptracePokeText(uintptr(addr), out)
835 // stepAsync starts this thread single stepping. When the single step
836 // is complete, it will send nil on the given channel. If an error
837 // occurs while setting up the single step, it returns that error. If
838 // an error occurs while waiting for the single step to complete, it
839 // sends that error on the channel.
840 func (t *thread) stepAsync(ready chan os.Error) os.Error {
841 if err := t.ptraceStep(); err != nil {
844 t.setState(singleStepping)
845 t.onStop(func() { ready <- nil },
846 func(err os.Error) { ready <- err })
850 func (t *thread) Step() os.Error {
852 defer t.logTrace("}")
854 ready := make(chan os.Error)
856 err := t.proc.do(func() os.Error {
857 if !t.state.isStopped() {
858 return &badState{t, "cannot single step", t.state}
860 return t.stepAsync(ready)
870 // TODO(austin) We should probably get this via C's strsignal.
871 var sigNames = [...]string{
872 "SIGEXIT", "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL",
873 "SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL",
874 "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM",
875 "SIGTERM", "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP",
876 "SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG", "SIGXCPU",
877 "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGPOLL",
881 // sigName returns the symbolic name for the given signal number. If
882 // the signal number is invalid, returns "<invalid>".
883 func sigName(signal int) string {
884 if signal < 0 || signal >= len(sigNames) {
887 return sigNames[signal]
890 func (t *thread) Stopped() (Cause, os.Error) {
892 err := t.proc.do(func() os.Error {
897 case stoppedBreakpoint:
898 c = Breakpoint(t.breakpoint.pc)
901 c = Signal(sigName(t.signal))
903 case stoppedThreadCreate:
904 c = &ThreadCreate{t.newThread}
906 case stoppedExiting, exiting, exited:
908 c = &ThreadExit{t.exitStatus, ""}
910 c = &ThreadExit{t.exitStatus, sigName(t.signal)}
914 return &badState{t, "cannot get stop cause", t.state}
925 func (p *process) Threads() []Thread {
928 p.do(func() os.Error {
929 res = make([]Thread, len(p.threads))
931 for _, t := range p.threads {
932 // Exclude zombie threads.
934 if st == exiting || st == exited || st == detached {
947 func (p *process) AddBreakpoint(pc Word) os.Error {
948 return p.do(func() os.Error {
949 if t := p.someRunningThread(); t != nil {
950 return &badState{t, "cannot add breakpoint", t.state}
952 if _, ok := p.breakpoints[uintptr(pc)]; ok {
953 return breakpointExistsError(pc)
955 p.breakpoints[uintptr(pc)] = &breakpoint{pc: uintptr(pc)}
960 func (p *process) RemoveBreakpoint(pc Word) os.Error {
961 return p.do(func() os.Error {
962 if t := p.someRunningThread(); t != nil {
963 return &badState{t, "cannot remove breakpoint", t.state}
965 if _, ok := p.breakpoints[uintptr(pc)]; !ok {
966 return noBreakpointError(pc)
968 p.breakpoints[uintptr(pc)] = nil, false
973 func (p *process) Continue() os.Error {
974 // Single step any threads that are stopped at breakpoints so
975 // we can reinstall breakpoints.
976 var ready chan os.Error
979 err := p.do(func() os.Error {
980 // We make the ready channel big enough to hold all
981 // ready message so we don't jam up the monitor if we
982 // stop listening (e.g., if there's an error).
983 ready = make(chan os.Error, len(p.threads))
985 for _, t := range p.threads {
986 if !t.state.isStopped() {
990 // We use the breakpoint map directly here
991 // instead of checking the stop cause because
992 // it could have been stopped at a breakpoint
993 // for some other reason, or the breakpoint
994 // could have been added since it was stopped.
995 var regs syscall.PtraceRegs
996 err := t.ptraceGetRegs(®s)
1000 if b, ok := p.breakpoints[uintptr(regs.PC())]; ok {
1001 t.logTrace("stepping over breakpoint %v", b)
1002 if err := t.stepAsync(ready); err != nil {
1015 // Wait for single stepping threads
1025 // Continue all threads
1026 err = p.do(func() os.Error {
1027 if err := p.installBreakpoints(); err != nil {
1031 for _, t := range p.threads {
1034 case !t.state.isStopped():
1037 case t.state == stoppedSignal && t.signal != syscall.SIGSTOP && t.signal != syscall.SIGTRAP:
1038 t.logTrace("continuing with signal %d", t.signal)
1039 err = t.ptraceContWithSignal(t.signal)
1042 t.logTrace("continuing")
1043 err = t.ptraceCont()
1048 if t.state == stoppedExiting {
1057 // TODO(austin) Do we need to stop the monitor with
1058 // this error atomically with the do-routine above?
1066 func (p *process) WaitStop() os.Error {
1067 // We need a non-blocking ready channel for the case where all
1068 // threads are already stopped.
1069 ready := make(chan os.Error, 1)
1071 err := p.do(func() os.Error {
1072 // Are all of the threads already stopped?
1073 if p.someRunningThread() == nil {
1078 // Monitor state transitions
1079 h := &transitionHandler{}
1080 h.handle = func(st *thread, old, new threadState) {
1081 if !new.isRunning() {
1082 if p.someRunningThread() == nil {
1087 p.transitionHandlers.Push(h)
1089 h.onErr = func(err os.Error) { ready <- err }
1090 p.transitionHandlers.Push(h)
1100 func (p *process) Stop() os.Error {
1101 err := p.do(func() os.Error { return p.stopAsync() })
1109 func (p *process) Detach() os.Error {
1110 if err := p.Stop(); err != nil {
1114 err := p.do(func() os.Error {
1115 if err := p.uninstallBreakpoints(); err != nil {
1119 for pid, t := range p.threads {
1120 if t.state.isStopped() {
1121 // We can't detach from zombies.
1122 if err := t.ptraceDetach(); err != nil {
1126 t.setState(detached)
1127 p.threads[pid] = nil, false
1131 // TODO(austin) Wait for monitor thread to exit?
1135 // newThread creates a new thread object and waits for its initial
1136 // signal. If cloned is true, this thread was cloned from a thread we
1137 // are already attached to.
1139 // Must be run from the monitor thread.
1140 func (p *process) newThread(tid int, signal int, cloned bool) (*thread, os.Error) {
1141 t := &thread{tid: tid, proc: p, state: stopped}
1143 // Get the signal from the thread
1144 // TODO(austin) Thread might already be stopped if we're attaching.
1145 w, err := os.Wait(tid, syscall.WALL)
1149 if w.Pid != tid || w.StopSignal() != signal {
1150 return nil, &newThreadError{w, tid, signal}
1154 err = t.ptraceSetOptions(syscall.PTRACE_O_TRACECLONE | syscall.PTRACE_O_TRACEEXIT)
1165 // attachThread attaches a running thread to the process.
1167 // Must NOT be run from the monitor thread.
1168 func (p *process) attachThread(tid int) (*thread, os.Error) {
1169 p.logTrace("attaching to thread %d", tid)
1171 err := p.do(func() os.Error {
1172 errno := syscall.PtraceAttach(tid)
1174 return os.NewSyscallError("ptrace(ATTACH)", errno)
1178 thr, err = p.newThread(tid, syscall.SIGSTOP, false)
1184 // attachAllThreads attaches to all threads in a process.
1185 func (p *process) attachAllThreads() os.Error {
1186 taskPath := "/proc/" + strconv.Itoa(p.pid) + "/task"
1187 taskDir, err := os.Open(taskPath, os.O_RDONLY, 0)
1191 defer taskDir.Close()
1193 // We stop threads as we attach to them; however, because new
1194 // threads can appear while we're looping over all of them, we
1195 // have to repeatly scan until we know we're attached to all
1197 for again := true; again; {
1200 tids, err := taskDir.Readdirnames(-1)
1205 for _, tidStr := range tids {
1206 tid, err := strconv.Atoi(tidStr)
1210 if _, ok := p.threads[tid]; ok {
1214 _, err = p.attachThread(tid)
1216 // There could have been a race, or
1217 // this process could be a zobmie.
1218 statFile, err2 := ioutil.ReadFile(taskPath + "/" + tidStr + "/stat")
1220 switch err2 := err2.(type) {
1222 if err2.Error == os.ENOENT {
1223 // Raced with thread exit
1224 p.logTrace("raced with thread %d exit", tid)
1228 // Return the original error
1232 statParts := strings.Split(string(statFile), " ", 4)
1233 if len(statParts) > 2 && statParts[2] == "Z" {
1235 p.logTrace("thread %d is a zombie", tid)
1239 // Return the original error
1249 // newProcess creates a new process object and starts its monitor thread.
1250 func newProcess(pid int) *process {
1253 threads: make(map[int]*thread),
1254 breakpoints: make(map[uintptr]*breakpoint),
1255 ready: make(chan bool, 1),
1256 debugEvents: make(chan *debugEvent),
1257 debugReqs: make(chan *debugReq),
1258 stopReq: make(chan os.Error),
1266 // Attach attaches to process pid and stops all of its threads.
1267 func Attach(pid int) (Process, os.Error) {
1268 p := newProcess(pid)
1270 // Attach to all threads
1271 err := p.attachAllThreads()
1274 // TODO(austin) Detach stopped the monitor already
1275 //p.stopMonitor(err);
1282 // ForkExec forks the current process and execs argv0, stopping the
1283 // new process after the exec syscall. See os.ForkExec for additional
1285 func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {
1288 // Create array of integer (system) fds.
1289 intfd := make([]int, len(fd))
1290 for i, f := range fd {
1298 // Fork from the monitor thread so we get the right tracer pid.
1299 err := p.do(func() os.Error {
1300 pid, errno := syscall.PtraceForkExec(argv0, argv, envv, dir, intfd)
1302 return &os.PathError{"fork/exec", argv0, os.Errno(errno)}
1306 // The process will raise SIGTRAP when it reaches execve.
1307 _, err := p.newThread(pid, syscall.SIGTRAP, false)