mirror of
https://github.com/golang/go
synced 2024-11-21 23:34:42 -07:00
debug/proc: Remove.
The package was always GNU/Linux specific, and is no longer used by anything now that exp/ogle has been removed. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/4757049
This commit is contained in:
parent
ee6e1a3ff7
commit
257df1719d
@ -68,7 +68,6 @@ DIRS=\
|
||||
debug/elf\
|
||||
debug/gosym\
|
||||
debug/pe\
|
||||
debug/proc\
|
||||
ebnf\
|
||||
encoding/ascii85\
|
||||
encoding/base32\
|
||||
@ -187,7 +186,6 @@ endif
|
||||
ifeq ($(GOOS),plan9)
|
||||
NOPLAN9BUILD=\
|
||||
crypto/tls\
|
||||
debug/proc\
|
||||
exp/gui/x11\
|
||||
expvar\
|
||||
http\
|
||||
@ -218,7 +216,6 @@ NOTEST+=\
|
||||
crypto\
|
||||
crypto/openpgp/error\
|
||||
crypto/x509/pkix\
|
||||
debug/proc\
|
||||
exp/gui\
|
||||
exp/gui/x11\
|
||||
go/ast\
|
||||
|
@ -1,13 +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.
|
||||
|
||||
include ../../../Make.inc
|
||||
|
||||
TARG=debug/proc
|
||||
GOFILES=\
|
||||
proc.go\
|
||||
proc_$(GOOS).go\
|
||||
regs_$(GOOS)_$(GOARCH).go\
|
||||
|
||||
include ../../../Make.pkg
|
@ -1,222 +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.
|
||||
|
||||
// Package proc provides a platform-independent interface for
|
||||
// tracing and controlling running processes. It supports
|
||||
// multi-threaded processes and provides typical low-level debugging
|
||||
// controls such as breakpoints, single stepping, and manipulating
|
||||
// memory and registers.
|
||||
package proc
|
||||
|
||||
// TODO(rsc): Have to import everything that proc_linux.go
|
||||
// and proc_darwin.go do, because deps.bash only looks at
|
||||
// this file.
|
||||
import (
|
||||
_ "container/vector"
|
||||
_ "fmt"
|
||||
_ "io"
|
||||
"os"
|
||||
_ "runtime"
|
||||
"strconv"
|
||||
_ "strings"
|
||||
_ "sync"
|
||||
_ "syscall"
|
||||
)
|
||||
|
||||
type Word uint64
|
||||
|
||||
// A Cause explains why a thread is stopped.
|
||||
type Cause interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
// Regs is a set of named machine registers, including a program
|
||||
// counter, link register, and stack pointer.
|
||||
//
|
||||
// TODO(austin) There's quite a proliferation of methods here. We
|
||||
// could make a Reg interface with Get and Set and make this just PC,
|
||||
// Link, SP, Names, and Reg. We could also put Index in Reg and that
|
||||
// makes it easy to get the index of things like the PC (currently
|
||||
// there's just no way to know that). This would also let us include
|
||||
// other per-register information like how to print it.
|
||||
type Regs interface {
|
||||
// PC returns the value of the program counter.
|
||||
PC() Word
|
||||
|
||||
// SetPC sets the program counter to val.
|
||||
SetPC(val Word) os.Error
|
||||
|
||||
// Link returns the link register, if any.
|
||||
Link() Word
|
||||
|
||||
// SetLink sets the link register to val.
|
||||
SetLink(val Word) os.Error
|
||||
|
||||
// SP returns the value of the stack pointer.
|
||||
SP() Word
|
||||
|
||||
// SetSP sets the stack pointer register to val.
|
||||
SetSP(val Word) os.Error
|
||||
|
||||
// Names returns the names of all of the registers.
|
||||
Names() []string
|
||||
|
||||
// Get returns the value of a register, where i corresponds to
|
||||
// the index of the register's name in the array returned by
|
||||
// Names.
|
||||
Get(i int) Word
|
||||
|
||||
// Set sets the value of a register.
|
||||
Set(i int, val Word) os.Error
|
||||
}
|
||||
|
||||
// Thread is a thread in the process being traced.
|
||||
type Thread interface {
|
||||
// Step steps this thread by a single instruction. The thread
|
||||
// must be stopped. If the thread is currently stopped on a
|
||||
// breakpoint, this will step over the breakpoint.
|
||||
//
|
||||
// XXX What if it's stopped because of a signal?
|
||||
Step() os.Error
|
||||
|
||||
// Stopped returns the reason that this thread is stopped. It
|
||||
// is an error is the thread not stopped.
|
||||
Stopped() (Cause, os.Error)
|
||||
|
||||
// Regs retrieves the current register values from this
|
||||
// thread. The thread must be stopped.
|
||||
Regs() (Regs, os.Error)
|
||||
|
||||
// Peek reads len(out) bytes from the address addr in this
|
||||
// thread into out. The thread must be stopped. It returns
|
||||
// the number of bytes successfully read. If an error occurs,
|
||||
// such as attempting to read unmapped memory, this count
|
||||
// could be short and an error will be returned. If this does
|
||||
// encounter unmapped memory, it will read up to the byte
|
||||
// preceding the unmapped area.
|
||||
Peek(addr Word, out []byte) (int, os.Error)
|
||||
|
||||
// Poke writes b to the address addr in this thread. The
|
||||
// thread must be stopped. It returns the number of bytes
|
||||
// successfully written. If an error occurs, such as
|
||||
// attempting to write to unmapped memory, this count could be
|
||||
// short and an error will be returned. If this does
|
||||
// encounter unmapped memory, it will write up to the byte
|
||||
// preceding the unmapped area.
|
||||
Poke(addr Word, b []byte) (int, os.Error)
|
||||
}
|
||||
|
||||
// Process is a process being traced. It consists of a set of
|
||||
// threads. A process can be running, stopped, or terminated. The
|
||||
// process's state extends to all of its threads.
|
||||
type Process interface {
|
||||
// Threads returns an array of all threads in this process.
|
||||
Threads() []Thread
|
||||
|
||||
// AddBreakpoint creates a new breakpoint at program counter
|
||||
// pc. Breakpoints can only be created when the process is
|
||||
// stopped. It is an error if a breakpoint already exists at
|
||||
// pc.
|
||||
AddBreakpoint(pc Word) os.Error
|
||||
|
||||
// RemoveBreakpoint removes the breakpoint at the program
|
||||
// counter pc. It is an error if no breakpoint exists at pc.
|
||||
RemoveBreakpoint(pc Word) os.Error
|
||||
|
||||
// Stop stops all running threads in this process before
|
||||
// returning.
|
||||
Stop() os.Error
|
||||
|
||||
// Continue resumes execution of all threads in this process.
|
||||
// Any thread that is stopped on a breakpoint will be stepped
|
||||
// over that breakpoint. Any thread that is stopped because
|
||||
// of a signal (other than SIGSTOP or SIGTRAP) will receive
|
||||
// the pending signal.
|
||||
Continue() os.Error
|
||||
|
||||
// WaitStop waits until all threads in process p are stopped
|
||||
// as a result of some thread hitting a breakpoint, receiving
|
||||
// a signal, creating a new thread, or exiting.
|
||||
WaitStop() os.Error
|
||||
|
||||
// Detach detaches from this process. All stopped threads
|
||||
// will be resumed.
|
||||
Detach() os.Error
|
||||
}
|
||||
|
||||
// Stopped is a stop cause used for threads that are stopped either by
|
||||
// user request (e.g., from the Stop method or after single stepping),
|
||||
// or that are stopped because some other thread caused the program to
|
||||
// stop.
|
||||
type Stopped struct{}
|
||||
|
||||
func (c Stopped) String() string { return "stopped" }
|
||||
|
||||
// Breakpoint is a stop cause resulting from a thread reaching a set
|
||||
// breakpoint.
|
||||
type Breakpoint Word
|
||||
|
||||
// PC returns the program counter that the program is stopped at.
|
||||
func (c Breakpoint) PC() Word { return Word(c) }
|
||||
|
||||
func (c Breakpoint) String() string {
|
||||
return "breakpoint at 0x" + strconv.Uitob64(uint64(c.PC()), 16)
|
||||
}
|
||||
|
||||
// Signal is a stop cause resulting from a thread receiving a signal.
|
||||
// When the process is continued, the signal will be delivered.
|
||||
type Signal string
|
||||
|
||||
// Signal returns the signal being delivered to the thread.
|
||||
func (c Signal) Name() string { return string(c) }
|
||||
|
||||
func (c Signal) String() string { return c.Name() }
|
||||
|
||||
// ThreadCreate is a stop cause returned from an existing thread when
|
||||
// it creates a new thread. The new thread exists in a primordial
|
||||
// form at this point and will begin executing in earnest when the
|
||||
// process is continued.
|
||||
type ThreadCreate struct {
|
||||
thread Thread
|
||||
}
|
||||
|
||||
func (c *ThreadCreate) NewThread() Thread { return c.thread }
|
||||
|
||||
func (c *ThreadCreate) String() string { return "thread create" }
|
||||
|
||||
// ThreadExit is a stop cause resulting from a thread exiting. When
|
||||
// this cause first arises, the thread will still be in the list of
|
||||
// process threads and its registers and memory will still be
|
||||
// accessible.
|
||||
type ThreadExit struct {
|
||||
exitStatus int
|
||||
signal string
|
||||
}
|
||||
|
||||
// Exited returns true if the thread exited normally.
|
||||
func (c *ThreadExit) Exited() bool { return c.exitStatus != -1 }
|
||||
|
||||
// ExitStatus returns the exit status of the thread if it exited
|
||||
// normally or -1 otherwise.
|
||||
func (c *ThreadExit) ExitStatus() int { return c.exitStatus }
|
||||
|
||||
// Signaled returns true if the thread was terminated by a signal.
|
||||
func (c *ThreadExit) Signaled() bool { return c.exitStatus == -1 }
|
||||
|
||||
// StopSignal returns the signal that terminated the thread, or "" if
|
||||
// it was not terminated by a signal.
|
||||
func (c *ThreadExit) StopSignal() string { return c.signal }
|
||||
|
||||
func (c *ThreadExit) String() string {
|
||||
res := "thread exited "
|
||||
switch {
|
||||
case c.Exited():
|
||||
res += "with status " + strconv.Itoa(c.ExitStatus())
|
||||
case c.Signaled():
|
||||
res += "from signal " + c.StopSignal()
|
||||
default:
|
||||
res += "from unknown cause"
|
||||
}
|
||||
return res
|
||||
}
|
@ -1,17 +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.
|
||||
|
||||
package proc
|
||||
|
||||
import "os"
|
||||
|
||||
// Process tracing is not supported on OS X yet.
|
||||
|
||||
func Attach(pid int) (Process, os.Error) {
|
||||
return nil, os.NewError("debug/proc not implemented on OS X")
|
||||
}
|
||||
|
||||
func StartProcess(argv0 string, argv []string, attr *os.ProcAttr) (Process, os.Error) {
|
||||
return Attach(0)
|
||||
}
|
@ -1,17 +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.
|
||||
|
||||
package proc
|
||||
|
||||
import "os"
|
||||
|
||||
// Process tracing is not supported on FreeBSD yet.
|
||||
|
||||
func Attach(pid int) (Process, os.Error) {
|
||||
return nil, os.NewError("debug/proc not implemented on FreeBSD")
|
||||
}
|
||||
|
||||
func StartProcess(argv0 string, argv []string, attr *os.ProcAttr) (Process, os.Error) {
|
||||
return Attach(0)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,17 +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.
|
||||
|
||||
package proc
|
||||
|
||||
import "os"
|
||||
|
||||
// Process tracing is not supported on windows yet.
|
||||
|
||||
func Attach(pid int) (Process, os.Error) {
|
||||
return nil, os.NewError("debug/proc not implemented on windows")
|
||||
}
|
||||
|
||||
func StartProcess(argv0 string, argv []string, attr *os.ProcAttr) (Process, os.Error) {
|
||||
return Attach(0)
|
||||
}
|
@ -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.
|
@ -1,5 +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.
|
||||
|
||||
package proc
|
@ -1,5 +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.
|
||||
|
||||
package proc
|
@ -1,5 +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.
|
||||
|
||||
package proc
|
@ -1,5 +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.
|
||||
|
||||
package proc
|
@ -1,143 +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.
|
||||
|
||||
package proc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type _386Regs struct {
|
||||
syscall.PtraceRegs
|
||||
setter func(*syscall.PtraceRegs) os.Error
|
||||
}
|
||||
|
||||
var names = []string{
|
||||
"eax",
|
||||
"ebx",
|
||||
"ecx",
|
||||
"edx",
|
||||
"esi",
|
||||
"edi",
|
||||
"ebp",
|
||||
"esp",
|
||||
"eip",
|
||||
"eflags",
|
||||
"cs",
|
||||
"ss",
|
||||
"ds",
|
||||
"es",
|
||||
"fs",
|
||||
"gs",
|
||||
}
|
||||
|
||||
func (r *_386Regs) PC() Word { return Word(r.Eip) }
|
||||
|
||||
func (r *_386Regs) SetPC(val Word) os.Error {
|
||||
r.Eip = int32(val)
|
||||
return r.setter(&r.PtraceRegs)
|
||||
}
|
||||
|
||||
func (r *_386Regs) Link() Word {
|
||||
// TODO(austin)
|
||||
panic("No link register")
|
||||
}
|
||||
|
||||
func (r *_386Regs) SetLink(val Word) os.Error { panic("No link register") }
|
||||
|
||||
func (r *_386Regs) SP() Word { return Word(r.Esp) }
|
||||
|
||||
func (r *_386Regs) SetSP(val Word) os.Error {
|
||||
r.Esp = int32(val)
|
||||
return r.setter(&r.PtraceRegs)
|
||||
}
|
||||
|
||||
func (r *_386Regs) Names() []string { return names }
|
||||
|
||||
func (r *_386Regs) Get(i int) Word {
|
||||
switch i {
|
||||
case 0:
|
||||
return Word(uint32(r.Eax))
|
||||
case 1:
|
||||
return Word(uint32(r.Ebx))
|
||||
case 2:
|
||||
return Word(uint32(r.Ecx))
|
||||
case 3:
|
||||
return Word(uint32(r.Edx))
|
||||
case 4:
|
||||
return Word(uint32(r.Esi))
|
||||
case 5:
|
||||
return Word(uint32(r.Edi))
|
||||
case 6:
|
||||
return Word(uint32(r.Ebp))
|
||||
case 7:
|
||||
return Word(uint32(r.Esp))
|
||||
case 8:
|
||||
return Word(uint32(r.Eip))
|
||||
case 9:
|
||||
return Word(uint32(r.Eflags))
|
||||
case 10:
|
||||
return Word(r.Xcs)
|
||||
case 11:
|
||||
return Word(r.Xss)
|
||||
case 12:
|
||||
return Word(r.Xds)
|
||||
case 13:
|
||||
return Word(r.Xes)
|
||||
case 14:
|
||||
return Word(r.Xfs)
|
||||
case 15:
|
||||
return Word(r.Xgs)
|
||||
}
|
||||
panic("invalid register index " + strconv.Itoa(i))
|
||||
}
|
||||
|
||||
func (r *_386Regs) Set(i int, val Word) os.Error {
|
||||
switch i {
|
||||
case 0:
|
||||
r.Eax = int32(val)
|
||||
case 1:
|
||||
r.Ebx = int32(val)
|
||||
case 2:
|
||||
r.Ecx = int32(val)
|
||||
case 3:
|
||||
r.Edx = int32(val)
|
||||
case 4:
|
||||
r.Esi = int32(val)
|
||||
case 5:
|
||||
r.Edi = int32(val)
|
||||
case 6:
|
||||
r.Ebp = int32(val)
|
||||
case 7:
|
||||
r.Esp = int32(val)
|
||||
case 8:
|
||||
r.Eip = int32(val)
|
||||
case 9:
|
||||
r.Eflags = int32(val)
|
||||
case 10:
|
||||
r.Xcs = int32(val)
|
||||
case 11:
|
||||
r.Xss = int32(val)
|
||||
case 12:
|
||||
r.Xds = int32(val)
|
||||
case 13:
|
||||
r.Xes = int32(val)
|
||||
case 14:
|
||||
r.Xfs = int32(val)
|
||||
case 15:
|
||||
r.Xgs = int32(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 := _386Regs{}
|
||||
res.PtraceRegs = *regs
|
||||
res.setter = setter
|
||||
return &res
|
||||
}
|
@ -1,191 +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.
|
||||
|
||||
package proc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type amd64Regs struct {
|
||||
syscall.PtraceRegs
|
||||
setter func(*syscall.PtraceRegs) os.Error
|
||||
}
|
||||
|
||||
var names = [...]string{
|
||||
"rax",
|
||||
"rbx",
|
||||
"rcx",
|
||||
"rdx",
|
||||
"rsi",
|
||||
"rdi",
|
||||
"rbp",
|
||||
"rsp",
|
||||
"r8",
|
||||
"r9",
|
||||
"r10",
|
||||
"r11",
|
||||
"r12",
|
||||
"r13",
|
||||
"r14",
|
||||
"r15",
|
||||
"rip",
|
||||
"eflags",
|
||||
"cs",
|
||||
"ss",
|
||||
"ds",
|
||||
"es",
|
||||
"fs",
|
||||
"gs",
|
||||
|
||||
// PtraceRegs contains these registers, but I don't think
|
||||
// they're actually meaningful.
|
||||
//"orig_rax",
|
||||
//"fs_base",
|
||||
//"gs_base",
|
||||
}
|
||||
|
||||
func (r *amd64Regs) PC() Word { return Word(r.Rip) }
|
||||
|
||||
func (r *amd64Regs) SetPC(val Word) os.Error {
|
||||
r.Rip = uint64(val)
|
||||
return r.setter(&r.PtraceRegs)
|
||||
}
|
||||
|
||||
func (r *amd64Regs) Link() Word {
|
||||
// TODO(austin)
|
||||
panic("No link register")
|
||||
}
|
||||
|
||||
func (r *amd64Regs) SetLink(val Word) os.Error {
|
||||
panic("No link register")
|
||||
}
|
||||
|
||||
func (r *amd64Regs) SP() Word { return Word(r.Rsp) }
|
||||
|
||||
func (r *amd64Regs) SetSP(val Word) os.Error {
|
||||
r.Rsp = uint64(val)
|
||||
return r.setter(&r.PtraceRegs)
|
||||
}
|
||||
|
||||
func (r *amd64Regs) Names() []string { return names[0:] }
|
||||
|
||||
func (r *amd64Regs) Get(i int) Word {
|
||||
switch i {
|
||||
case 0:
|
||||
return Word(r.Rax)
|
||||
case 1:
|
||||
return Word(r.Rbx)
|
||||
case 2:
|
||||
return Word(r.Rcx)
|
||||
case 3:
|
||||
return Word(r.Rdx)
|
||||
case 4:
|
||||
return Word(r.Rsi)
|
||||
case 5:
|
||||
return Word(r.Rdi)
|
||||
case 6:
|
||||
return Word(r.Rbp)
|
||||
case 7:
|
||||
return Word(r.Rsp)
|
||||
case 8:
|
||||
return Word(r.R8)
|
||||
case 9:
|
||||
return Word(r.R9)
|
||||
case 10:
|
||||
return Word(r.R10)
|
||||
case 11:
|
||||
return Word(r.R11)
|
||||
case 12:
|
||||
return Word(r.R12)
|
||||
case 13:
|
||||
return Word(r.R13)
|
||||
case 14:
|
||||
return Word(r.R14)
|
||||
case 15:
|
||||
return Word(r.R15)
|
||||
case 16:
|
||||
return Word(r.Rip)
|
||||
case 17:
|
||||
return Word(r.Eflags)
|
||||
case 18:
|
||||
return Word(r.Cs)
|
||||
case 19:
|
||||
return Word(r.Ss)
|
||||
case 20:
|
||||
return Word(r.Ds)
|
||||
case 21:
|
||||
return Word(r.Es)
|
||||
case 22:
|
||||
return Word(r.Fs)
|
||||
case 23:
|
||||
return Word(r.Gs)
|
||||
}
|
||||
panic("invalid register index " + strconv.Itoa(i))
|
||||
}
|
||||
|
||||
func (r *amd64Regs) Set(i int, val Word) os.Error {
|
||||
switch i {
|
||||
case 0:
|
||||
r.Rax = uint64(val)
|
||||
case 1:
|
||||
r.Rbx = uint64(val)
|
||||
case 2:
|
||||
r.Rcx = uint64(val)
|
||||
case 3:
|
||||
r.Rdx = uint64(val)
|
||||
case 4:
|
||||
r.Rsi = uint64(val)
|
||||
case 5:
|
||||
r.Rdi = uint64(val)
|
||||
case 6:
|
||||
r.Rbp = uint64(val)
|
||||
case 7:
|
||||
r.Rsp = uint64(val)
|
||||
case 8:
|
||||
r.R8 = uint64(val)
|
||||
case 9:
|
||||
r.R9 = uint64(val)
|
||||
case 10:
|
||||
r.R10 = uint64(val)
|
||||
case 11:
|
||||
r.R11 = uint64(val)
|
||||
case 12:
|
||||
r.R12 = uint64(val)
|
||||
case 13:
|
||||
r.R13 = uint64(val)
|
||||
case 14:
|
||||
r.R14 = uint64(val)
|
||||
case 15:
|
||||
r.R15 = uint64(val)
|
||||
case 16:
|
||||
r.Rip = uint64(val)
|
||||
case 17:
|
||||
r.Eflags = uint64(val)
|
||||
case 18:
|
||||
r.Cs = uint64(val)
|
||||
case 19:
|
||||
r.Ss = uint64(val)
|
||||
case 20:
|
||||
r.Ds = uint64(val)
|
||||
case 21:
|
||||
r.Es = uint64(val)
|
||||
case 22:
|
||||
r.Fs = uint64(val)
|
||||
case 23:
|
||||
r.Gs = 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 := amd64Regs{}
|
||||
res.PtraceRegs = *regs
|
||||
res.setter = setter
|
||||
return &res
|
||||
}
|
@ -1,39 +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.
|
||||
|
||||
package proc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// TODO(kaib): add support
|
||||
|
||||
type armRegs struct{}
|
||||
|
||||
func (r *armRegs) PC() Word { return Word(0) }
|
||||
|
||||
func (r *armRegs) SetPC(val Word) os.Error { return nil }
|
||||
|
||||
func (r *armRegs) Link() Word { return Word(0) }
|
||||
|
||||
func (r *armRegs) SetLink(val Word) os.Error { return nil }
|
||||
|
||||
func (r *armRegs) SP() Word { return Word(0) }
|
||||
|
||||
func (r *armRegs) SetSP(val Word) os.Error { return nil }
|
||||
|
||||
func (r *armRegs) Names() []string { return nil }
|
||||
|
||||
func (r *armRegs) Get(i int) Word { return Word(0) }
|
||||
|
||||
func (r *armRegs) Set(i int, val Word) os.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newRegs(regs *syscall.PtraceRegs, setter func(*syscall.PtraceRegs) os.Error) Regs {
|
||||
res := armRegs{}
|
||||
return &res
|
||||
}
|
@ -1,5 +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.
|
||||
|
||||
package proc
|
@ -1,5 +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.
|
||||
|
||||
package proc
|
Loading…
Reference in New Issue
Block a user