OSDN Git Service

Add Go frontend, libgo library, and Go testsuite.
[pf3gnuchains/gcc-fork.git] / libgo / go / debug / proc / proc_linux.go
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.
4
5 package proc
6
7 // TODO(rsc): Imports here after to be in proc.go too in order
8 // for deps.bash to get the right answer.
9 import (
10         "container/vector"
11         "fmt"
12         "io/ioutil"
13         "os"
14         "runtime"
15         "strconv"
16         "strings"
17         "sync"
18         "syscall"
19 )
20
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.
30 //
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.
36
37 const (
38         trace    = false
39         traceIP  = false
40         traceMem = false
41 )
42
43 /*
44  * Thread state
45  */
46
47 // Each thread can be in one of the following set of states.
48 // Each state satisfies
49 //  isRunning() || isStopped() || isZombie() || isTerminal().
50 //
51 // Running threads can be sent signals and must be waited on, but they
52 // cannot be inspected using ptrace.
53 //
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.
57 //
58 // Zombie threads cannot be inspected, continued, or sent signals (and
59 // therefore they cannot be stopped), but they must be waited on.
60 //
61 // Terminal threads no longer exist in the OS and thus you can't do
62 // anything with them.
63 type threadState string
64
65 const (
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"
77 )
78
79 func (ts threadState) isRunning() bool {
80         return ts == running || ts == singleStepping || ts == stopping
81 }
82
83 func (ts threadState) isStopped() bool {
84         return ts == stopped || ts == stoppedBreakpoint || ts == stoppedSignal || ts == stoppedThreadCreate || ts == stoppedExiting
85 }
86
87 func (ts threadState) isZombie() bool { return ts == exiting }
88
89 func (ts threadState) isTerminal() bool { return ts == exited || ts == detached }
90
91 func (ts threadState) String() string { return string(ts) }
92
93 /*
94  * Basic types
95  */
96
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 {
101         pc      uintptr
102         olddata []byte
103 }
104
105 func (bp *breakpoint) String() string {
106         if bp == nil {
107                 return "<nil>"
108         }
109         return fmt.Sprintf("%#x", bp.pc)
110 }
111
112 // bpinst386 is the breakpoint instruction used on 386 and amd64.
113 var bpinst386 = []byte{0xcc}
114
115 // A debugEvent represents a reason a thread stopped or a wait error.
116 type debugEvent struct {
117         *os.Waitmsg
118         t   *thread
119         err os.Error
120 }
121
122 // A debugReq is a request to execute a closure in the monitor thread.
123 type debugReq struct {
124         f   func() os.Error
125         res chan os.Error
126 }
127
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)
135         onErr  func(os.Error)
136 }
137
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.
142 //
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 {
149         pid                int
150         threads            map[int]*thread
151         breakpoints        map[uintptr]*breakpoint
152         ready              chan bool
153         debugEvents        chan *debugEvent
154         debugReqs          chan *debugReq
155         stopReq            chan os.Error
156         transitionHandlers vector.Vector
157         err                os.Error
158 }
159
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.
163 type thread struct {
164         tid  int
165         proc *process
166         // Whether to ignore the next SIGSTOP received by wait.
167         ignoreNextSigstop bool
168
169         // Thread state.  Only modified via setState.
170         state threadState
171         // If state == StoppedBreakpoint
172         breakpoint *breakpoint
173         // If state == StoppedSignal or state == Exited
174         signal int
175         // If state == StoppedThreadCreate
176         newThread *thread
177         // If state == Exited
178         exitStatus int
179 }
180
181 /*
182  * Errors
183  */
184
185 type badState struct {
186         thread  *thread
187         message string
188         state   threadState
189 }
190
191 func (e *badState) String() string {
192         return fmt.Sprintf("Thread %d %s from state %v", e.thread.tid, e.message, e.state)
193 }
194
195 type breakpointExistsError Word
196
197 func (e breakpointExistsError) String() string {
198         return fmt.Sprintf("breakpoint already exists at PC %#x", e)
199 }
200
201 type noBreakpointError Word
202
203 func (e noBreakpointError) String() string { return fmt.Sprintf("no breakpoint at PC %#x", e) }
204
205 type newThreadError struct {
206         *os.Waitmsg
207         wantPid int
208         wantSig int
209 }
210
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)
213 }
214
215 type ProcessExited struct{}
216
217 func (p ProcessExited) String() string { return "process exited" }
218
219 /*
220  * Ptrace wrappers
221  */
222
223 func (t *thread) ptracePeekText(addr uintptr, out []byte) (int, os.Error) {
224         c, err := syscall.PtracePeekText(t.tid, addr, out)
225         if traceMem {
226                 fmt.Printf("peek(%#x) => %v, %v\n", addr, out, err)
227         }
228         return c, os.NewSyscallError("ptrace(PEEKTEXT)", err)
229 }
230
231 func (t *thread) ptracePokeText(addr uintptr, out []byte) (int, os.Error) {
232         c, err := syscall.PtracePokeText(t.tid, addr, out)
233         if traceMem {
234                 fmt.Printf("poke(%#x, %v) => %v\n", addr, out, err)
235         }
236         return c, os.NewSyscallError("ptrace(POKETEXT)", err)
237 }
238
239 func (t *thread) ptraceGetRegs(regs *syscall.PtraceRegs) os.Error {
240         err := syscall.PtraceGetRegs(t.tid, regs)
241         return os.NewSyscallError("ptrace(GETREGS)", err)
242 }
243
244 func (t *thread) ptraceSetRegs(regs *syscall.PtraceRegs) os.Error {
245         err := syscall.PtraceSetRegs(t.tid, regs)
246         return os.NewSyscallError("ptrace(SETREGS)", err)
247 }
248
249 func (t *thread) ptraceSetOptions(options int) os.Error {
250         err := syscall.PtraceSetOptions(t.tid, options)
251         return os.NewSyscallError("ptrace(SETOPTIONS)", err)
252 }
253
254 func (t *thread) ptraceGetEventMsg() (uint, os.Error) {
255         msg, err := syscall.PtraceGetEventMsg(t.tid)
256         return msg, os.NewSyscallError("ptrace(GETEVENTMSG)", err)
257 }
258
259 func (t *thread) ptraceCont() os.Error {
260         err := syscall.PtraceCont(t.tid, 0)
261         return os.NewSyscallError("ptrace(CONT)", err)
262 }
263
264 func (t *thread) ptraceContWithSignal(sig int) os.Error {
265         err := syscall.PtraceCont(t.tid, sig)
266         return os.NewSyscallError("ptrace(CONT)", err)
267 }
268
269 func (t *thread) ptraceStep() os.Error {
270         err := syscall.PtraceSingleStep(t.tid)
271         return os.NewSyscallError("ptrace(SINGLESTEP)", err)
272 }
273
274 func (t *thread) ptraceDetach() os.Error {
275         err := syscall.PtraceDetach(t.tid)
276         return os.NewSyscallError("ptrace(DETACH)", err)
277 }
278
279 /*
280  * Logging utilties
281  */
282
283 var logLock sync.Mutex
284
285 func (t *thread) logTrace(format string, args ...interface{}) {
286         if !trace {
287                 return
288         }
289         logLock.Lock()
290         defer logLock.Unlock()
291         fmt.Fprintf(os.Stderr, "Thread %d", t.tid)
292         if traceIP {
293                 var regs syscall.PtraceRegs
294                 err := t.ptraceGetRegs(&regs)
295                 if err == nil {
296                         fmt.Fprintf(os.Stderr, "@%x", regs.PC())
297                 }
298         }
299         fmt.Fprint(os.Stderr, ": ")
300         fmt.Fprintf(os.Stderr, format, args...)
301         fmt.Fprint(os.Stderr, "\n")
302 }
303
304 func (t *thread) warn(format string, args ...interface{}) {
305         logLock.Lock()
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")
310 }
311
312 func (p *process) logTrace(format string, args ...interface{}) {
313         if !trace {
314                 return
315         }
316         logLock.Lock()
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")
321 }
322
323 /*
324  * State utilities
325  */
326
327 // someStoppedThread returns a stopped thread from the process.
328 // Returns nil if no threads are stopped.
329 //
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() {
334                         return t
335                 }
336         }
337         return nil
338 }
339
340 // someRunningThread returns a running thread from the process.
341 // Returns nil if no threads are running.
342 //
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() {
347                         return t
348                 }
349         }
350         return nil
351 }
352
353 /*
354  * Breakpoint utilities
355  */
356
357 // installBreakpoints adds breakpoints to the attached process.
358 //
359 // Must be called from the monitor thread.
360 func (p *process) installBreakpoints() os.Error {
361         n := 0
362         main := p.someStoppedThread()
363         for _, b := range p.breakpoints {
364                 if b.olddata != nil {
365                         continue
366                 }
367
368                 b.olddata = make([]byte, len(bpinst386))
369                 _, err := main.ptracePeekText(uintptr(b.pc), b.olddata)
370                 if err != nil {
371                         b.olddata = nil
372                         return err
373                 }
374
375                 _, err = main.ptracePokeText(uintptr(b.pc), bpinst386)
376                 if err != nil {
377                         b.olddata = nil
378                         return err
379                 }
380                 n++
381         }
382         if n > 0 {
383                 p.logTrace("installed %d/%d breakpoints", n, len(p.breakpoints))
384         }
385
386         return nil
387 }
388
389 // uninstallBreakpoints removes the installed breakpoints from p.
390 //
391 // Must be called from the monitor thread.
392 func (p *process) uninstallBreakpoints() os.Error {
393         if len(p.threads) == 0 {
394                 return nil
395         }
396         n := 0
397         main := p.someStoppedThread()
398         for _, b := range p.breakpoints {
399                 if b.olddata == nil {
400                         continue
401                 }
402
403                 _, err := main.ptracePokeText(uintptr(b.pc), b.olddata)
404                 if err != nil {
405                         return err
406                 }
407                 b.olddata = nil
408                 n++
409         }
410         if n > 0 {
411                 p.logTrace("uninstalled %d/%d breakpoints", n, len(p.breakpoints))
412         }
413
414         return nil
415 }
416
417 /*
418  * Debug event handling
419  */
420
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
425 // event.
426 func (t *thread) wait() {
427         for {
428                 var ev debugEvent
429                 ev.t = t
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))
434                 }
435                 if ev.StopSignal() == syscall.SIGSTOP && t.ignoreNextSigstop {
436                         // Spurious SIGSTOP.  See Thread.Stop().
437                         t.ignoreNextSigstop = false
438                         err := t.ptraceCont()
439                         if err == nil {
440                                 continue
441                         }
442                         // If we failed to continue, just let
443                         // the stop go through so we can
444                         // update the thread's state.
445                 }
446                 if !<-t.proc.ready {
447                         // The monitor exited
448                         break
449                 }
450                 t.proc.debugEvents <- &ev
451                 break
452         }
453 }
454
455 // setState sets this thread's state, starts a wait thread if
456 // necessary, and invokes state transition handlers.
457 //
458 // Must be called from the monitor thread.
459 func (t *thread) setState(newState threadState) {
460         oldState := t.state
461         t.state = newState
462         t.logTrace("state %v -> %v", oldState, newState)
463
464         if !oldState.isRunning() && (newState.isRunning() || newState.isZombie()) {
465                 // Start waiting on this thread
466                 go t.wait()
467         }
468
469         // Invoke state change handlers
470         handlers := t.proc.transitionHandlers
471         if handlers.Len() == 0 {
472                 return
473         }
474
475         t.proc.transitionHandlers = nil
476         for _, h := range handlers {
477                 h := h.(*transitionHandler)
478                 h.handle(t, oldState, newState)
479         }
480 }
481
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)
487 }
488
489 // stopAsync sends SIGSTOP to all threads in state 'running'.
490 //
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()
496                         if err != nil {
497                                 return err
498                         }
499                         t.setState(stopping)
500                 }
501         }
502         return nil
503 }
504
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.
508 //
509 // TODO(austin) I think we also get this on an execve syscall.
510 func (ev *debugEvent) doTrap() (threadState, os.Error) {
511         t := ev.t
512
513         if t.state == singleStepping {
514                 return stopped, nil
515         }
516
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(&regs)
522         if err != nil {
523                 return stopped, err
524         }
525
526         b, ok := t.proc.breakpoints[uintptr(regs.PC())-uintptr(len(bpinst386))]
527         if !ok {
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
533         }
534
535         t.breakpoint = b
536         t.logTrace("at breakpoint %v, backing up PC from %#x", b, regs.PC())
537
538         regs.SetPC(uint64(b.pc))
539         err = t.ptraceSetRegs(&regs)
540         if err != nil {
541                 return stopped, err
542         }
543         return stoppedBreakpoint, nil
544 }
545
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) {
550         t := ev.t
551
552         // Get the TID of the new thread
553         tid, err := t.ptraceGetEventMsg()
554         if err != nil {
555                 return stopped, err
556         }
557
558         nt, err := t.proc.newThread(int(tid), syscall.SIGSTOP, true)
559         if err != nil {
560                 return stopped, err
561         }
562
563         // Remember the thread
564         t.newThread = nt
565
566         return stoppedThreadCreate, nil
567 }
568
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
572 // process.
573 func (ev *debugEvent) doPtraceExit() (threadState, os.Error) {
574         t := ev.t
575
576         // Get exit status
577         exitStatus, err := t.ptraceGetEventMsg()
578         if err != nil {
579                 return stopped, err
580         }
581         ws := syscall.WaitStatus(exitStatus)
582         t.logTrace("exited with %v", ws)
583         switch {
584         case ws.Exited():
585                 t.exitStatus = ws.ExitStatus()
586         case ws.Signaled():
587                 t.signal = ws.Signal()
588         }
589
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
593 }
594
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 {
599         if ev.err != nil {
600                 return ev.err
601         }
602
603         t := ev.t
604         t.exitStatus = -1
605         t.signal = -1
606
607         // Decode wait status.
608         var state threadState
609         switch {
610         case ev.Stopped():
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?
616                         var err os.Error
617                         switch cause := ev.TrapCause(); cause {
618                         case 0:
619                                 // Breakpoint or single stepping
620                                 state, err = ev.doTrap()
621
622                         case syscall.PTRACE_EVENT_CLONE:
623                                 state, err = ev.doPtraceClone()
624
625                         case syscall.PTRACE_EVENT_EXIT:
626                                 state, err = ev.doPtraceExit()
627
628                         default:
629                                 t.warn("Unknown trap cause %d", cause)
630                         }
631
632                         if err != nil {
633                                 t.setState(stopped)
634                                 t.warn("failed to handle trap %v: %v", ev, err)
635                         }
636                 }
637
638         case ev.Exited():
639                 state = exited
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()
645
646         case ev.Signaled():
647                 state = exited
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()
652
653         default:
654                 panic(fmt.Sprintf("Unexpected wait status %v", ev.Waitmsg))
655         }
656
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
661         // next one we get.
662         if t.state == stopping && ev.StopSignal() != syscall.SIGSTOP {
663                 t.ignoreNextSigstop = true
664         }
665
666         // TODO(austin) If we're in state stopping and get a SIGSTOP,
667         // set state stopped instead of stoppedSignal.
668
669         t.setState(state)
670
671         if t.proc.someRunningThread() == nil {
672                 // Nothing is running, uninstall breakpoints
673                 return t.proc.uninstallBreakpoints()
674         }
675         // Stop any other running threads
676         return t.proc.stopAsync()
677 }
678
679 // onStop adds a handler for state transitions from running to
680 // non-running states.  The handler will be called from the monitor
681 // thread.
682 //
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() {
692                         handle()
693                 } else {
694                         t.proc.transitionHandlers.Push(h)
695                 }
696         }
697         t.proc.transitionHandlers.Push(h)
698 }
699
700 /*
701  * Event monitor
702  */
703
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() {
707         var err os.Error
708
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()
714
715         hadThreads := false
716         for err == nil {
717                 p.ready <- true
718                 select {
719                 case event := <-p.debugEvents:
720                         err = event.process()
721
722                 case req := <-p.debugReqs:
723                         req.res <- req.f()
724
725                 case err = <-p.stopReq:
726                         break
727                 }
728
729                 if len(p.threads) == 0 {
730                         if err == nil && hadThreads {
731                                 p.logTrace("no more threads; monitor exiting")
732                                 err = ProcessExited{}
733                         }
734                 } else {
735                         hadThreads = true
736                 }
737         }
738
739         // Abort waiting handlers
740         // TODO(austin) How do I stop the wait threads?
741         for _, h := range p.transitionHandlers {
742                 h := h.(*transitionHandler)
743                 h.onErr(err)
744         }
745
746         // Indicate that the monitor cannot receive any more messages
747         p.err = err
748         close(p.ready)
749 }
750
751 // do executes f in the monitor thread (and, thus, atomically with
752 // respect to thread state changes).  f must not block.
753 //
754 // Must NOT be called from the monitor thread.
755 func (p *process) do(f func() os.Error) os.Error {
756         if !<-p.ready {
757                 return p.err
758         }
759         req := &debugReq{f, make(chan os.Error)}
760         p.debugReqs <- req
761         return <-req.res
762 }
763
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) {
767         if err == nil {
768                 panic("cannot stop the monitor with no error")
769         }
770         if <-p.ready {
771                 p.stopReq <- err
772         }
773 }
774
775 /*
776  * Public thread interface
777  */
778
779 func (t *thread) Regs() (Regs, os.Error) {
780         var regs syscall.PtraceRegs
781
782         err := t.proc.do(func() os.Error {
783                 if !t.state.isStopped() {
784                         return &badState{t, "cannot get registers", t.state}
785                 }
786                 return t.ptraceGetRegs(&regs)
787         })
788         if err != nil {
789                 return nil, err
790         }
791
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}
796                         }
797                         return t.ptraceSetRegs(r)
798                 })
799         }
800         return newRegs(&regs, setter), nil
801 }
802
803 func (t *thread) Peek(addr Word, out []byte) (int, os.Error) {
804         var c int
805
806         err := t.proc.do(func() os.Error {
807                 if !t.state.isStopped() {
808                         return &badState{t, "cannot peek text", t.state}
809                 }
810
811                 var err os.Error
812                 c, err = t.ptracePeekText(uintptr(addr), out)
813                 return err
814         })
815
816         return c, err
817 }
818
819 func (t *thread) Poke(addr Word, out []byte) (int, os.Error) {
820         var c int
821
822         err := t.proc.do(func() os.Error {
823                 if !t.state.isStopped() {
824                         return &badState{t, "cannot poke text", t.state}
825                 }
826
827                 var err os.Error
828                 c, err = t.ptracePokeText(uintptr(addr), out)
829                 return err
830         })
831
832         return c, err
833 }
834
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 {
842                 return err
843         }
844         t.setState(singleStepping)
845         t.onStop(func() { ready <- nil },
846                 func(err os.Error) { ready <- err })
847         return nil
848 }
849
850 func (t *thread) Step() os.Error {
851         t.logTrace("Step {")
852         defer t.logTrace("}")
853
854         ready := make(chan os.Error)
855
856         err := t.proc.do(func() os.Error {
857                 if !t.state.isStopped() {
858                         return &badState{t, "cannot single step", t.state}
859                 }
860                 return t.stepAsync(ready)
861         })
862         if err != nil {
863                 return err
864         }
865
866         err = <-ready
867         return err
868 }
869
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",
878         "SIGPWR", "SIGSYS",
879 }
880
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) {
885                 return "<invalid>"
886         }
887         return sigNames[signal]
888 }
889
890 func (t *thread) Stopped() (Cause, os.Error) {
891         var c Cause
892         err := t.proc.do(func() os.Error {
893                 switch t.state {
894                 case stopped:
895                         c = Stopped{}
896
897                 case stoppedBreakpoint:
898                         c = Breakpoint(t.breakpoint.pc)
899
900                 case stoppedSignal:
901                         c = Signal(sigName(t.signal))
902
903                 case stoppedThreadCreate:
904                         c = &ThreadCreate{t.newThread}
905
906                 case stoppedExiting, exiting, exited:
907                         if t.signal == -1 {
908                                 c = &ThreadExit{t.exitStatus, ""}
909                         } else {
910                                 c = &ThreadExit{t.exitStatus, sigName(t.signal)}
911                         }
912
913                 default:
914                         return &badState{t, "cannot get stop cause", t.state}
915                 }
916                 return nil
917         })
918         if err != nil {
919                 return nil, err
920         }
921
922         return c, nil
923 }
924
925 func (p *process) Threads() []Thread {
926         var res []Thread
927
928         p.do(func() os.Error {
929                 res = make([]Thread, len(p.threads))
930                 i := 0
931                 for _, t := range p.threads {
932                         // Exclude zombie threads.
933                         st := t.state
934                         if st == exiting || st == exited || st == detached {
935                                 continue
936                         }
937
938                         res[i] = t
939                         i++
940                 }
941                 res = res[0:i]
942                 return nil
943         })
944         return res
945 }
946
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}
951                 }
952                 if _, ok := p.breakpoints[uintptr(pc)]; ok {
953                         return breakpointExistsError(pc)
954                 }
955                 p.breakpoints[uintptr(pc)] = &breakpoint{pc: uintptr(pc)}
956                 return nil
957         })
958 }
959
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}
964                 }
965                 if _, ok := p.breakpoints[uintptr(pc)]; !ok {
966                         return noBreakpointError(pc)
967                 }
968                 p.breakpoints[uintptr(pc)] = nil, false
969                 return nil
970         })
971 }
972
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
977         count := 0
978
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))
984
985                 for _, t := range p.threads {
986                         if !t.state.isStopped() {
987                                 continue
988                         }
989
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(&regs)
997                         if err != nil {
998                                 return err
999                         }
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 {
1003                                         return err
1004                                 }
1005                                 count++
1006                         }
1007                 }
1008                 return nil
1009         })
1010         if err != nil {
1011                 p.stopMonitor(err)
1012                 return err
1013         }
1014
1015         // Wait for single stepping threads
1016         for count > 0 {
1017                 err = <-ready
1018                 if err != nil {
1019                         p.stopMonitor(err)
1020                         return err
1021                 }
1022                 count--
1023         }
1024
1025         // Continue all threads
1026         err = p.do(func() os.Error {
1027                 if err := p.installBreakpoints(); err != nil {
1028                         return err
1029                 }
1030
1031                 for _, t := range p.threads {
1032                         var err os.Error
1033                         switch {
1034                         case !t.state.isStopped():
1035                                 continue
1036
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)
1040
1041                         default:
1042                                 t.logTrace("continuing")
1043                                 err = t.ptraceCont()
1044                         }
1045                         if err != nil {
1046                                 return err
1047                         }
1048                         if t.state == stoppedExiting {
1049                                 t.setState(exiting)
1050                         } else {
1051                                 t.setState(running)
1052                         }
1053                 }
1054                 return nil
1055         })
1056         if err != nil {
1057                 // TODO(austin) Do we need to stop the monitor with
1058                 // this error atomically with the do-routine above?
1059                 p.stopMonitor(err)
1060                 return err
1061         }
1062
1063         return nil
1064 }
1065
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)
1070
1071         err := p.do(func() os.Error {
1072                 // Are all of the threads already stopped?
1073                 if p.someRunningThread() == nil {
1074                         ready <- nil
1075                         return nil
1076                 }
1077
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 {
1083                                         ready <- nil
1084                                         return
1085                                 }
1086                         }
1087                         p.transitionHandlers.Push(h)
1088                 }
1089                 h.onErr = func(err os.Error) { ready <- err }
1090                 p.transitionHandlers.Push(h)
1091                 return nil
1092         })
1093         if err != nil {
1094                 return err
1095         }
1096
1097         return <-ready
1098 }
1099
1100 func (p *process) Stop() os.Error {
1101         err := p.do(func() os.Error { return p.stopAsync() })
1102         if err != nil {
1103                 return err
1104         }
1105
1106         return p.WaitStop()
1107 }
1108
1109 func (p *process) Detach() os.Error {
1110         if err := p.Stop(); err != nil {
1111                 return err
1112         }
1113
1114         err := p.do(func() os.Error {
1115                 if err := p.uninstallBreakpoints(); err != nil {
1116                         return err
1117                 }
1118
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 {
1123                                         return err
1124                                 }
1125                         }
1126                         t.setState(detached)
1127                         p.threads[pid] = nil, false
1128                 }
1129                 return nil
1130         })
1131         // TODO(austin) Wait for monitor thread to exit?
1132         return err
1133 }
1134
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.
1138 //
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}
1142
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)
1146         if err != nil {
1147                 return nil, err
1148         }
1149         if w.Pid != tid || w.StopSignal() != signal {
1150                 return nil, &newThreadError{w, tid, signal}
1151         }
1152
1153         if !cloned {
1154                 err = t.ptraceSetOptions(syscall.PTRACE_O_TRACECLONE | syscall.PTRACE_O_TRACEEXIT)
1155                 if err != nil {
1156                         return nil, err
1157                 }
1158         }
1159
1160         p.threads[tid] = t
1161
1162         return t, nil
1163 }
1164
1165 // attachThread attaches a running thread to the process.
1166 //
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)
1170         var thr *thread
1171         err := p.do(func() os.Error {
1172                 errno := syscall.PtraceAttach(tid)
1173                 if errno != 0 {
1174                         return os.NewSyscallError("ptrace(ATTACH)", errno)
1175                 }
1176
1177                 var err os.Error
1178                 thr, err = p.newThread(tid, syscall.SIGSTOP, false)
1179                 return err
1180         })
1181         return thr, err
1182 }
1183
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)
1188         if err != nil {
1189                 return err
1190         }
1191         defer taskDir.Close()
1192
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
1196         // of them.
1197         for again := true; again; {
1198                 again = false
1199
1200                 tids, err := taskDir.Readdirnames(-1)
1201                 if err != nil {
1202                         return err
1203                 }
1204
1205                 for _, tidStr := range tids {
1206                         tid, err := strconv.Atoi(tidStr)
1207                         if err != nil {
1208                                 return err
1209                         }
1210                         if _, ok := p.threads[tid]; ok {
1211                                 continue
1212                         }
1213
1214                         _, err = p.attachThread(tid)
1215                         if err != nil {
1216                                 // There could have been a race, or
1217                                 // this process could be a zobmie.
1218                                 statFile, err2 := ioutil.ReadFile(taskPath + "/" + tidStr + "/stat")
1219                                 if err2 != nil {
1220                                         switch err2 := err2.(type) {
1221                                         case *os.PathError:
1222                                                 if err2.Error == os.ENOENT {
1223                                                         // Raced with thread exit
1224                                                         p.logTrace("raced with thread %d exit", tid)
1225                                                         continue
1226                                                 }
1227                                         }
1228                                         // Return the original error
1229                                         return err
1230                                 }
1231
1232                                 statParts := strings.Split(string(statFile), " ", 4)
1233                                 if len(statParts) > 2 && statParts[2] == "Z" {
1234                                         // tid is a zombie
1235                                         p.logTrace("thread %d is a zombie", tid)
1236                                         continue
1237                                 }
1238
1239                                 // Return the original error
1240                                 return err
1241                         }
1242                         again = true
1243                 }
1244         }
1245
1246         return nil
1247 }
1248
1249 // newProcess creates a new process object and starts its monitor thread.
1250 func newProcess(pid int) *process {
1251         p := &process{
1252                 pid:         pid,
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),
1259         }
1260
1261         go p.monitor()
1262
1263         return p
1264 }
1265
1266 // Attach attaches to process pid and stops all of its threads.
1267 func Attach(pid int) (Process, os.Error) {
1268         p := newProcess(pid)
1269
1270         // Attach to all threads
1271         err := p.attachAllThreads()
1272         if err != nil {
1273                 p.Detach()
1274                 // TODO(austin) Detach stopped the monitor already
1275                 //p.stopMonitor(err);
1276                 return nil, err
1277         }
1278
1279         return p, nil
1280 }
1281
1282 // ForkExec forks the current process and execs argv0, stopping the
1283 // new process after the exec syscall.  See os.ForkExec for additional
1284 // details.
1285 func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {
1286         p := newProcess(-1)
1287
1288         // Create array of integer (system) fds.
1289         intfd := make([]int, len(fd))
1290         for i, f := range fd {
1291                 if f == nil {
1292                         intfd[i] = -1
1293                 } else {
1294                         intfd[i] = f.Fd()
1295                 }
1296         }
1297
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)
1301                 if errno != 0 {
1302                         return &os.PathError{"fork/exec", argv0, os.Errno(errno)}
1303                 }
1304                 p.pid = pid
1305
1306                 // The process will raise SIGTRAP when it reaches execve.
1307                 _, err := p.newThread(pid, syscall.SIGTRAP, false)
1308                 return err
1309         })
1310         if err != nil {
1311                 p.stopMonitor(err)
1312                 return nil, err
1313         }
1314
1315         return p, nil
1316 }