libgo: Remove debug/proc, os.Error.

From-SVN: r182074
This commit is contained in:
Ian Lance Taylor 2011-12-07 01:21:57 +00:00
parent 9c63abc9a1
commit 598fd331d0
7 changed files with 3 additions and 395 deletions

View File

@ -1,17 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proc
import "os"
// Process tracing is not supported on IRIX yet.
func Attach(pid int) (Process, os.Error) {
return nil, os.NewError("debug/proc not implemented on IRIX")
}
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {
return Attach(0)
}

View File

@ -1,17 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proc
import "os"
// Process tracing is not supported on RTEMS yet.
func Attach(pid int) (Process, os.Error) {
return nil, os.NewError("debug/proc not implemented on RTEMS")
}
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {
return Attach(0)
}

View File

@ -1,17 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proc
import "os"
// Process tracing is not supported on Solaris yet.
func Attach(pid int) (Process, os.Error) {
return nil, os.NewError("debug/proc not implemented on Solaris")
}
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {
return Attach(0)
}

View File

@ -1,132 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
ptrace and NTPL, the missing manpage
== Signals ==
A signal sent to a ptrace'd process or thread causes only the thread
that receives it to stop and report to the attached process.
Use tgkill to target a signal (for example, SIGSTOP) at a particular
thread. If you use kill, the signal could be delivered to another
thread in the same process.
Note that SIGSTOP differs from its usual behavior when a process is
being traced. Usually, a SIGSTOP sent to any thread in a thread group
will stop all threads in the thread group. When a thread is traced,
however, a SIGSTOP affects only the receiving thread (and any other
threads in the thread group that are not traced).
SIGKILL behaves like it does for non-traced processes. It affects all
threads in the process and terminates them without the WSTOPSIG event
generated by other signals. However, if PTRACE_O_TRACEEXIT is set,
the attached process will still receive PTRACE_EVENT_EXIT events
before receiving WIFSIGNALED events.
See "Following thread death" for a caveat regarding signal delivery to
zombie threads.
== Waiting on threads ==
Cloned threads in ptrace'd processes are treated similarly to cloned
threads in your own process. Thus, you must use the __WALL option in
order to receive notifications from threads created by the child
process. Similarly, the __WCLONE option will wait only on
notifications from threads created by the child process and *not* on
notifications from the initial child thread.
Even when waiting on a specific thread's PID using waitpid or similar,
__WALL or __WCLONE is necessary or waitpid will return ECHILD.
== Attaching to existing threads ==
libthread_db (which gdb uses), attaches to existing threads by pulling
the pthread data structures out of the traced process. The much
easier way is to traverse the /proc/PID/task directory, though it's
unclear how the semantics of these two approaches differ.
Unfortunately, if the main thread has exited (but the overall process
has not), it sticks around as a zombie process. This zombie will
appear in the /proc/PID/task directory, but trying to attach to it
will yield EPERM. In this case, the third field of the
/proc/PID/task/PID/stat file will be "Z". Attempting to open the stat
file is also a convenient way to detect races between listing the task
directory and the thread exiting. Coincidentally, gdb will simply
fail to attach to a process whose main thread is a zombie.
Because new threads may be created while the debugger is in the
process of attaching to existing threads, the debugger must repeatedly
re-list the task directory until it has attached to (and thus stopped)
every thread listed.
In order to follow new threads created by existing threads,
PTRACE_O_TRACECLONE must be set on each thread attached to.
== Following new threads ==
With the child process stopped, use PTRACE_SETOPTIONS to set the
PTRACE_O_TRACECLONE option. This option is per-thread, and thus must
be set on each existing thread individually. When an existing thread
with PTRACE_O_TRACECLONE set spawns a new thread, the existing thread
will stop with (SIGTRAP | PTRACE_EVENT_CLONE << 8) and the PID of the
new thread can be retrieved with PTRACE_GETEVENTMSG on the creating
thread. At this time, the new thread will exist, but will initially
be stopped with a SIGSTOP. The new thread will automatically be
traced and will inherit the PTRACE_O_TRACECLONE option from its
parent. The attached process should wait on the new thread to receive
the SIGSTOP notification.
When using waitpid(-1, ...), don't rely on the parent thread reporting
a SIGTRAP before receiving the SIGSTOP from the new child thread.
Without PTRACE_O_TRACECLONE, newly cloned threads will not be
ptrace'd. As a result, signals received by new threads will be
handled in the usual way, which may affect the parent and in turn
appear to the attached process, but attributed to the parent (possibly
in unexpected ways).
== Following thread death ==
If any thread with the PTRACE_O_TRACEEXIT option set exits (either by
returning or pthread_exit'ing), the tracing process will receive an
immediate PTRACE_EVENT_EXIT. At this point, the thread will still
exist. The exit status, encoded as for wait, can be queried using
PTRACE_GETEVENTMSG on the exiting thread's PID. The thread should be
continued so it can actually exit, after which its wait behavior is
the same as for a thread without the PTRACE_O_TRACEEXIT option.
If a non-main thread exits (either by returning or pthread_exit'ing),
its corresponding process will also exit, producing a WIFEXITED event
(after the process is continued from a possible PTRACE_EVENT_EXIT
event). It is *not* necessary for another thread to ptrace_join for
this to happen.
If the main thread exits by returning, then all threads will exit,
first generating a PTRACE_EVENT_EXIT event for each thread if
appropriate, then producing a WIFEXITED event for each thread.
If the main thread exits using pthread_exit, then it enters a
non-waitable zombie state. It will still produce an immediate
PTRACE_O_TRACEEXIT event, but the WIFEXITED event will be delayed
until the entire process exits. This state exists so that shells
don't think the process is done until all of the threads have exited.
Unfortunately, signals cannot be delivered to non-waitable zombies.
Most notably, SIGSTOP cannot be delivered; as a result, when you
broadcast SIGSTOP to all of the threads, you must not wait for
non-waitable zombies to stop. Furthermore, any ptrace command on a
non-waitable zombie, including PTRACE_DETACH, will return ESRCH.
== Multi-threaded debuggers ==
If the debugger itself is multi-threaded, ptrace calls must come from
the same thread that originally attached to the remote thread. The
kernel simply compares the PID of the caller of ptrace against the
tracer PID of the process passed to ptrace. Because each debugger
thread has a different PID, calling ptrace from a different thread
might as well be calling it from a different process and the kernel
will return ESRCH.
wait, on the other hand, does not have this restriction. Any debugger
thread can wait on any thread in the attached process.

View File

@ -1,209 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proc
import (
"os"
"strconv"
"syscall"
)
type alphaRegs struct {
syscall.PtraceRegs
setter func(*syscall.PtraceRegs) os.Error
}
var names = [...]string{
"r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
"r8",
"r19",
"r20",
"r21",
"r22",
"r23",
"r24",
"r25",
"r26",
"r27",
"r28",
"hae",
"trap_a0",
"trap_a1",
"trap_a2",
"ps",
"pc",
"gp",
"r16",
"r17",
"r18",
}
func (r *alphaRegs) PC() Word { return Word(r.Pc) }
func (r *alphaRegs) SetPC(val Word) os.Error {
r.Pc = uint64(val)
return r.setter(&r.PtraceRegs)
}
func (r *alphaRegs) Link() Word {
panic("No link register")
}
func (r *alphaRegs) SetLink(val Word) os.Error {
panic("No link register")
}
func (r *alphaRegs) SP() Word { return Word(r.Ps) }
func (r *alphaRegs) SetSP(val Word) os.Error {
r.Ps = uint64(val)
return r.setter(&r.PtraceRegs)
}
func (r *alphaRegs) Names() []string { return names[0:] }
func (r *alphaRegs) Get(i int) Word {
switch i {
case 0:
return Word(r.R0)
case 1:
return Word(r.R1)
case 2:
return Word(r.R2)
case 3:
return Word(r.R3)
case 4:
return Word(r.R4)
case 5:
return Word(r.R5)
case 6:
return Word(r.R6)
case 7:
return Word(r.R7)
case 8:
return Word(r.R8)
case 9:
return Word(r.R19)
case 10:
return Word(r.R20)
case 11:
return Word(r.R21)
case 12:
return Word(r.R22)
case 13:
return Word(r.R23)
case 14:
return Word(r.R24)
case 15:
return Word(r.R25)
case 16:
return Word(r.R26)
case 17:
return Word(r.R27)
case 18:
return Word(r.R28)
case 19:
return Word(r.Hae)
case 20:
return Word(r.Trap_a0)
case 21:
return Word(r.Trap_a1)
case 22:
return Word(r.Trap_a2)
case 23:
return Word(r.Ps)
case 24:
return Word(r.Pc)
case 25:
return Word(r.Gp)
case 26:
return Word(r.R16)
case 27:
return Word(r.R17)
case 28:
return Word(r.R18)
}
panic("invalid register index " + strconv.Itoa(i))
}
func (r *alphaRegs) Set(i int, val Word) os.Error {
switch i {
case 0:
r.R0 = uint64(val)
case 1:
r.R1 = uint64(val)
case 2:
r.R2 = uint64(val)
case 3:
r.R3 = uint64(val)
case 4:
r.R4 = uint64(val)
case 5:
r.R5 = uint64(val)
case 6:
r.R6 = uint64(val)
case 7:
r.R7 = uint64(val)
case 8:
r.R8 = uint64(val)
case 9:
r.R19 = uint64(val)
case 10:
r.R20 = uint64(val)
case 11:
r.R21 = uint64(val)
case 12:
r.R22 = uint64(val)
case 13:
r.R23 = uint64(val)
case 14:
r.R24 = uint64(val)
case 15:
r.R25 = uint64(val)
case 16:
r.R26 = uint64(val)
case 17:
r.R27 = uint64(val)
case 18:
r.R28 = uint64(val)
case 19:
r.Hae = uint64(val)
case 20:
r.Trap_a0 = uint64(val)
case 21:
r.Trap_a1 = uint64(val)
case 22:
r.Trap_a2 = uint64(val)
case 23:
r.Ps = uint64(val)
case 24:
r.Pc = uint64(val)
case 25:
r.Gp = uint64(val)
case 26:
r.R16 = uint64(val)
case 27:
r.R17 = uint64(val)
case 28:
r.R18 = uint64(val)
default:
panic("invalid register index " + strconv.Itoa(i))
}
return r.setter(&r.PtraceRegs)
}
func newRegs(regs *syscall.PtraceRegs, setter func(*syscall.PtraceRegs) os.Error) Regs {
res := alphaRegs{}
res.PtraceRegs = *regs
res.setter = setter
return &res
}

View File

@ -9,7 +9,7 @@ import (
"syscall"
)
func selfConnectedTCPSocket() (pr, pw *os.File, err os.Error) {
func selfConnectedTCPSocket() (pr, pw *os.File, err error) {
// See ../syscall/exec.go for description of ForkLock.
syscall.ForkLock.RLock()
sockfd, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
@ -49,7 +49,7 @@ func selfConnectedTCPSocket() (pr, pw *os.File, err os.Error) {
return fd, fd, nil
}
func newPollServer() (s *pollServer, err os.Error) {
func newPollServer() (s *pollServer, err error) {
s = new(pollServer)
s.cr = make(chan *netFD, 1)
s.cw = make(chan *netFD, 1)

View File

@ -37,7 +37,7 @@ var elen int;
// If n <= 0, Readdirnames returns all the names from the directory in
// a single slice. In this case, if Readdirnames succeeds (reads all
// the way to the end of the directory), it returns the slice and a
// nil os.Error. If it encounters an error before the end of the
// nil error. If it encounters an error before the end of the
// directory, Readdirnames returns the names read until that point and
// a non-nil error.
func (file *File) Readdirnames(n int) (names []string, err error) {