summaryrefslogtreecommitdiff
path: root/src/pkg/debug/proc/proc_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/debug/proc/proc_linux.go')
-rw-r--r--src/pkg/debug/proc/proc_linux.go161
1 files changed, 80 insertions, 81 deletions
diff --git a/src/pkg/debug/proc/proc_linux.go b/src/pkg/debug/proc/proc_linux.go
index 8fb147ddc..82291be23 100644
--- a/src/pkg/debug/proc/proc_linux.go
+++ b/src/pkg/debug/proc/proc_linux.go
@@ -35,9 +35,9 @@ import (
// as well as experimentation and examination of gdb's behavior.
const (
- trace = false;
- traceIP = false;
- traceMem = false;
+ trace = false;
+ traceIP = false;
+ traceMem = false;
)
/*
@@ -60,20 +60,20 @@ const (
//
// Terminal threads no longer exist in the OS and thus you can't do
// anything with them.
-type threadState string;
+type threadState string
const (
- running threadState = "Running";
- singleStepping threadState = "SingleStepping"; // Transient
- stopping threadState = "Stopping"; // Transient
- stopped threadState = "Stopped";
- stoppedBreakpoint threadState = "StoppedBreakpoint";
- stoppedSignal threadState = "StoppedSignal";
- stoppedThreadCreate threadState = "StoppedThreadCreate";
- stoppedExiting threadState = "StoppedExiting";
- exiting threadState = "Exiting"; // Transient (except main thread)
- exited threadState = "Exited";
- detached threadState = "Detached";
+ running threadState = "Running";
+ singleStepping threadState = "SingleStepping"; // Transient
+ stopping threadState = "Stopping"; // Transient
+ stopped threadState = "Stopped";
+ stoppedBreakpoint threadState = "StoppedBreakpoint";
+ stoppedSignal threadState = "StoppedSignal";
+ stoppedThreadCreate threadState = "StoppedThreadCreate";
+ stoppedExiting threadState = "StoppedExiting";
+ exiting threadState = "Exiting"; // Transient (except main thread)
+ exited threadState = "Exited";
+ detached threadState = "Detached";
)
func (ts threadState) isRunning() bool {
@@ -104,8 +104,8 @@ func (ts threadState) String() string {
// including its program counter, the overwritten text if the
// breakpoint is installed.
type breakpoint struct {
- pc uintptr;
- olddata []byte;
+ pc uintptr;
+ olddata []byte;
}
func (bp *breakpoint) String() string {
@@ -116,19 +116,19 @@ func (bp *breakpoint) String() string {
}
// bpinst386 is the breakpoint instruction used on 386 and amd64.
-var bpinst386 = []byte{0xcc};
+var bpinst386 = []byte{0xcc}
// A debugEvent represents a reason a thread stopped or a wait error.
type debugEvent struct {
*os.Waitmsg;
- t *thread;
- err os.Error;
+ t *thread;
+ err os.Error;
}
// A debugReq is a request to execute a closure in the monitor thread.
type debugReq struct {
- f func () os.Error;
- res chan os.Error;
+ f func() os.Error;
+ res chan os.Error;
}
// A transitionHandler specifies a function to be called when a thread
@@ -137,8 +137,8 @@ type debugReq struct {
// invokes a handler, it removes the handler from the handler queue.
// The handler should re-add itself if needed.
type transitionHandler struct {
- handle func (*thread, threadState, threadState);
- onErr func (os.Error);
+ handle func(*thread, threadState, threadState);
+ onErr func(os.Error);
}
// A process is a Linux process, which consists of a set of threads.
@@ -146,34 +146,34 @@ type transitionHandler struct {
// messages from the debugEvents, debugReqs, and stopReq channels and
// calls transition handlers.
type process struct {
- pid int;
- threads map[int] *thread;
- breakpoints map[uintptr] *breakpoint;
- debugEvents chan *debugEvent;
- debugReqs chan *debugReq;
- stopReq chan os.Error;
- transitionHandlers *vector.Vector;
+ pid int;
+ threads map[int]*thread;
+ breakpoints map[uintptr]*breakpoint;
+ debugEvents chan *debugEvent;
+ debugReqs chan *debugReq;
+ stopReq chan os.Error;
+ transitionHandlers *vector.Vector;
}
// A thread represents a Linux thread in another process that is being
// debugged. Each running thread has an associated goroutine that
// waits for thread updates and sends them to the process monitor.
type thread struct {
- tid int;
- proc *process;
+ tid int;
+ proc *process;
// Whether to ignore the next SIGSTOP received by wait.
- ignoreNextSigstop bool;
+ ignoreNextSigstop bool;
// Thread state. Only modified via setState.
- state threadState;
+ state threadState;
// If state == StoppedBreakpoint
- breakpoint *breakpoint;
+ breakpoint *breakpoint;
// If state == StoppedSignal or state == Exited
- signal int;
+ signal int;
// If state == StoppedThreadCreate
- newThread *thread;
+ newThread *thread;
// If state == Exited
- exitStatus int;
+ exitStatus int;
}
/*
@@ -181,9 +181,9 @@ type thread struct {
*/
type badState struct {
- thread *thread;
- message string;
- state threadState;
+ thread *thread;
+ message string;
+ state threadState;
}
func (e *badState) String() string {
@@ -204,8 +204,8 @@ func (e noBreakpointError) String() string {
type newThreadError struct {
*os.Waitmsg;
- wantPid int;
- wantSig int;
+ wantPid int;
+ wantSig int;
}
func (e *newThreadError) String() string {
@@ -435,9 +435,9 @@ func (t *thread) wait() {
if err == nil {
continue;
}
- // If we failed to continue, just let
- // the stop go through so we can
- // update the thread's state.
+ // If we failed to continue, just let
+ // the stop go through so we can
+ // update the thread's state.
}
t.proc.debugEvents <- &ev;
break;
@@ -515,7 +515,7 @@ func (ev *debugEvent) doTrap() (threadState, os.Error) {
return stopped, err;
}
- b, ok := t.proc.breakpoints[uintptr(regs.PC())-uintptr(len(bpinst386))];
+ b, ok := t.proc.breakpoints[uintptr(regs.PC()) - uintptr(len(bpinst386))];
if !ok {
// We must have hit a breakpoint that was actually in
// the program. Leave the IP where it is so we don't
@@ -673,13 +673,13 @@ func (ev *debugEvent) process() os.Error {
// thread.
//
// Must be called from the monitor thread.
-func (t *thread) onStop(handle func (), onErr func (os.Error)) {
+func (t *thread) onStop(handle func(), onErr func(os.Error)) {
// TODO(austin) This is rather inefficient for things like
// stepping all threads during a continue. Maybe move
// transitionHandlers to the thread, or have both per-thread
// and per-process transition handlers.
h := &transitionHandler{nil, onErr};
- h.handle = func (st *thread, old, new threadState) {
+ h.handle = func(st *thread, old, new threadState) {
if t == st && old.isRunning() && !new.isRunning() {
handle();
} else {
@@ -753,7 +753,7 @@ func (p *process) monitor() {
// respect to thread state changes). f must not block.
//
// Must NOT be called from the monitor thread.
-func (p *process) do(f func () os.Error) os.Error {
+func (p *process) do(f func() os.Error) os.Error {
// TODO(austin) If monitor is stopped, return error.
req := &debugReq{f, make(chan os.Error)};
p.debugReqs <- req;
@@ -764,7 +764,7 @@ func (p *process) do(f func () os.Error) os.Error {
// is already stopped, does nothing.
func (p *process) stopMonitor(err os.Error) {
_ = p.stopReq <- err; // do not block
- // TODO(austin) Wait until monitor has exited?
+// TODO(austin) Wait until monitor has exited?
}
/*
@@ -774,7 +774,7 @@ func (p *process) stopMonitor(err os.Error) {
func (t *thread) Regs() (Regs, os.Error) {
var regs syscall.PtraceRegs;
- err := t.proc.do(func () os.Error {
+ err := t.proc.do(func() os.Error {
if !t.state.isStopped() {
return &badState{t, "cannot get registers", t.state};
}
@@ -784,8 +784,8 @@ func (t *thread) Regs() (Regs, os.Error) {
return nil, err;
}
- setter := func (r *syscall.PtraceRegs) os.Error {
- return t.proc.do(func () os.Error {
+ setter := func(r *syscall.PtraceRegs) os.Error {
+ return t.proc.do(func() os.Error {
if !t.state.isStopped() {
return &badState{t, "cannot get registers", t.state};
}
@@ -798,7 +798,7 @@ func (t *thread) Regs() (Regs, os.Error) {
func (t *thread) Peek(addr Word, out []byte) (int, os.Error) {
var c int;
- err := t.proc.do(func () os.Error {
+ err := t.proc.do(func() os.Error {
if !t.state.isStopped() {
return &badState{t, "cannot peek text", t.state};
}
@@ -814,7 +814,7 @@ func (t *thread) Peek(addr Word, out []byte) (int, os.Error) {
func (t *thread) Poke(addr Word, out []byte) (int, os.Error) {
var c int;
- err := t.proc.do(func () os.Error {
+ err := t.proc.do(func() os.Error {
if !t.state.isStopped() {
return &badState{t, "cannot poke text", t.state};
}
@@ -837,10 +837,10 @@ func (t *thread) stepAsync(ready chan os.Error) os.Error {
return err;
}
t.setState(singleStepping);
- t.onStop(func () {
- ready <- nil;
- },
- func (err os.Error) {
+ t.onStop(func() {
+ ready <- nil;
+ },
+ func(err os.Error) {
ready <- err;
});
return nil;
@@ -852,7 +852,7 @@ func (t *thread) Step() os.Error {
ready := make(chan os.Error);
- err := t.proc.do(func () os.Error {
+ err := t.proc.do(func() os.Error {
if !t.state.isStopped() {
return &badState{t, "cannot single step", t.state};
}
@@ -867,14 +867,14 @@ func (t *thread) Step() os.Error {
}
// TODO(austin) We should probably get this via C's strsignal.
-var sigNames = [...]string {
+var sigNames = [...]string{
"SIGEXIT", "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL",
"SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL",
"SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM",
"SIGTERM", "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP",
"SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG", "SIGXCPU",
"SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGPOLL",
- "SIGPWR", "SIGSYS"
+ "SIGPWR", "SIGSYS",
}
// sigName returns the symbolic name for the given signal number. If
@@ -924,7 +924,7 @@ func (t *thread) Stopped() (Cause, os.Error) {
func (p *process) Threads() []Thread {
var res []Thread;
- p.do(func () os.Error {
+ p.do(func() os.Error {
res = make([]Thread, len(p.threads));
i := 0;
for _, t := range p.threads {
@@ -944,7 +944,7 @@ func (p *process) Threads() []Thread {
}
func (p *process) AddBreakpoint(pc Word) os.Error {
- return p.do(func () os.Error {
+ return p.do(func() os.Error {
if t := p.someRunningThread(); t != nil {
return &badState{t, "cannot add breakpoint", t.state};
}
@@ -957,7 +957,7 @@ func (p *process) AddBreakpoint(pc Word) os.Error {
}
func (p *process) RemoveBreakpoint(pc Word) os.Error {
- return p.do(func () os.Error {
+ return p.do(func() os.Error {
if t := p.someRunningThread(); t != nil {
return &badState{t, "cannot remove breakpoint", t.state};
}
@@ -975,7 +975,7 @@ func (p *process) Continue() os.Error {
var ready chan os.Error;
count := 0;
- err := p.do(func () os.Error {
+ err := p.do(func() os.Error {
// We make the ready channel big enough to hold all
// ready message so we don't jam up the monitor if we
// stop listening (e.g., if there's an error).
@@ -1022,7 +1022,7 @@ func (p *process) Continue() os.Error {
}
// Continue all threads
- err = p.do(func () os.Error {
+ err = p.do(func() os.Error {
if err := p.installBreakpoints(); err != nil {
return err;
}
@@ -1067,7 +1067,7 @@ func (p *process) WaitStop() os.Error {
// threads are already stopped.
ready := make(chan os.Error, 1);
- err := p.do(func () os.Error {
+ err := p.do(func() os.Error {
// Are all of the threads already stopped?
if p.someRunningThread() == nil {
ready <- nil;
@@ -1076,7 +1076,7 @@ func (p *process) WaitStop() os.Error {
// Monitor state transitions
h := &transitionHandler{};
- h.handle = func (st *thread, old, new threadState) {
+ h.handle = func(st *thread, old, new threadState) {
if !new.isRunning() {
if p.someRunningThread() == nil {
ready <- nil;
@@ -1085,7 +1085,7 @@ func (p *process) WaitStop() os.Error {
}
p.transitionHandlers.Push(h);
};
- h.onErr = func (err os.Error) {
+ h.onErr = func(err os.Error) {
ready <- err;
};
p.transitionHandlers.Push(h);
@@ -1099,7 +1099,7 @@ func (p *process) WaitStop() os.Error {
}
func (p *process) Stop() os.Error {
- err := p.do(func () os.Error {
+ err := p.do(func() os.Error {
return p.stopAsync();
});
if err != nil {
@@ -1114,7 +1114,7 @@ func (p *process) Detach() os.Error {
return err;
}
- err := p.do(func () os.Error {
+ err := p.do(func() os.Error {
if err := p.uninstallBreakpoints(); err != nil {
return err;
}
@@ -1171,7 +1171,7 @@ func (p *process) newThread(tid int, signal int, cloned bool) (*thread, os.Error
func (p *process) attachThread(tid int) (*thread, os.Error) {
p.logTrace("attaching to thread %d", tid);
var thr *thread;
- err := p.do(func () os.Error {
+ err := p.do(func() os.Error {
errno := syscall.PtraceAttach(tid);
if errno != 0 {
return os.NewSyscallError("ptrace(ATTACH)", errno);
@@ -1253,12 +1253,12 @@ func (p *process) attachAllThreads() os.Error {
func newProcess(pid int) *process {
p := &process{
pid: pid,
- threads: make(map[int] *thread),
- breakpoints: make(map[uintptr] *breakpoint),
+ threads: make(map[int]*thread),
+ breakpoints: make(map[uintptr]*breakpoint),
debugEvents: make(chan *debugEvent),
debugReqs: make(chan *debugReq),
stopReq: make(chan os.Error),
- transitionHandlers: vector.New(0)
+ transitionHandlers: vector.New(0),
};
go p.monitor();
@@ -1285,8 +1285,7 @@ func Attach(pid int) (Process, os.Error) {
// ForkExec forks the current process and execs argv0, stopping the
// new process after the exec syscall. See os.ForkExec for additional
// details.
-func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error)
-{
+func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {
p := newProcess(-1);
// Create array of integer (system) fds.
@@ -1300,7 +1299,7 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.F
}
// Fork from the monitor thread so we get the right tracer pid.
- err := p.do(func () os.Error {
+ err := p.do(func() os.Error {
pid, errno := syscall.PtraceForkExec(argv0, argv, envv, dir, intfd);
if errno != 0 {
return &os.PathError{"fork/exec", argv0, os.Errno(errno)};