s/DebuggedProcess/Process/
This commit is contained in:
parent
d265fa764f
commit
102d4c89ae
@ -63,7 +63,7 @@ func (iae InvalidAddressError) Error() string {
|
||||
return fmt.Sprintf("Invalid address %#v\n", iae.address)
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64, temp bool) (*Breakpoint, error) {
|
||||
func (dbp *Process) setBreakpoint(tid int, addr uint64, temp bool) (*Breakpoint, error) {
|
||||
if bp, ok := dbp.FindBreakpoint(addr); ok {
|
||||
return nil, BreakpointExistsError{bp.File, bp.Line, bp.Addr}
|
||||
}
|
||||
@ -141,7 +141,7 @@ func (nbp NoBreakpointError) Error() string {
|
||||
return fmt.Sprintf("no breakpoint at %#v", nbp.addr)
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) clearBreakpoint(tid int, addr uint64) (*Breakpoint, error) {
|
||||
func (dbp *Process) clearBreakpoint(tid int, addr uint64) (*Breakpoint, error) {
|
||||
thread := dbp.Threads[tid]
|
||||
if bp, ok := dbp.Breakpoints[addr]; ok {
|
||||
if _, err := bp.Clear(thread); err != nil {
|
||||
|
@ -3,11 +3,11 @@ package proc
|
||||
import "fmt"
|
||||
|
||||
// TODO(darwin)
|
||||
func (dbp *DebuggedProcess) setHardwareBreakpoint(reg, tid int, addr uint64) error {
|
||||
func (dbp *Process) setHardwareBreakpoint(reg, tid int, addr uint64) error {
|
||||
return fmt.Errorf("not implemented on darwin")
|
||||
}
|
||||
|
||||
// TODO(darwin)
|
||||
func (dbp *DebuggedProcess) clearHardwareBreakpoint(reg, tid int) error {
|
||||
func (dbp *Process) clearHardwareBreakpoint(reg, tid int) error {
|
||||
return fmt.Errorf("not implemented on darwin")
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import "fmt"
|
||||
// debug register `reg` with the address of the instruction
|
||||
// that we want to break at. There are only 4 debug registers
|
||||
// DR0-DR3. Debug register 7 is the control register.
|
||||
func (dbp *DebuggedProcess) setHardwareBreakpoint(reg, tid int, addr uint64) error {
|
||||
func (dbp *Process) setHardwareBreakpoint(reg, tid int, addr uint64) error {
|
||||
if reg < 0 || reg > 3 {
|
||||
return fmt.Errorf("invalid debug register value")
|
||||
}
|
||||
@ -72,6 +72,6 @@ func (dbp *DebuggedProcess) setHardwareBreakpoint(reg, tid int, addr uint64) err
|
||||
// Clears a hardware breakpoint. Essentially sets
|
||||
// the debug reg to 0 and clears the control register
|
||||
// flags for that reg.
|
||||
func (dbp *DebuggedProcess) clearHardwareBreakpoint(reg, tid int) error {
|
||||
func (dbp *Process) clearHardwareBreakpoint(reg, tid int) error {
|
||||
return dbp.setHardwareBreakpoint(reg, tid, 0)
|
||||
}
|
||||
|
86
proc/proc.go
86
proc/proc.go
@ -20,9 +20,9 @@ import (
|
||||
"github.com/derekparker/delve/source"
|
||||
)
|
||||
|
||||
// DebuggedProcess represents all of the information the debugger
|
||||
// Process represents all of the information the debugger
|
||||
// is holding onto regarding the process we are debugging.
|
||||
type DebuggedProcess struct {
|
||||
type Process struct {
|
||||
Pid int // Process Pid
|
||||
Process *os.Process // Pointer to process struct for the actual process we are debugging
|
||||
|
||||
@ -53,8 +53,8 @@ type DebuggedProcess struct {
|
||||
ptraceDoneChan chan interface{}
|
||||
}
|
||||
|
||||
func New(pid int) *DebuggedProcess {
|
||||
dbp := &DebuggedProcess{
|
||||
func New(pid int) *Process {
|
||||
dbp := &Process{
|
||||
Pid: pid,
|
||||
Threads: make(map[int]*Thread),
|
||||
Breakpoints: make(map[uint64]*Breakpoint),
|
||||
@ -88,7 +88,7 @@ func (pe ProcessExitedError) Error() string {
|
||||
}
|
||||
|
||||
// Attach to an existing process with the given PID.
|
||||
func Attach(pid int) (*DebuggedProcess, error) {
|
||||
func Attach(pid int) (*Process, error) {
|
||||
dbp, err := initializeDebugProcess(New(pid), "", true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -96,7 +96,7 @@ func Attach(pid int) (*DebuggedProcess, error) {
|
||||
return dbp, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) Detach(kill bool) (err error) {
|
||||
func (dbp *Process) Detach(kill bool) (err error) {
|
||||
// Clean up any breakpoints we've set.
|
||||
for _, bp := range dbp.Breakpoints {
|
||||
if bp != nil {
|
||||
@ -115,13 +115,13 @@ func (dbp *DebuggedProcess) Detach(kill bool) (err error) {
|
||||
|
||||
// Returns whether or not Delve thinks the debugged
|
||||
// process has exited.
|
||||
func (dbp *DebuggedProcess) Exited() bool {
|
||||
func (dbp *Process) Exited() bool {
|
||||
return dbp.exited
|
||||
}
|
||||
|
||||
// Returns whether or not Delve thinks the debugged
|
||||
// process is currently executing.
|
||||
func (dbp *DebuggedProcess) Running() bool {
|
||||
func (dbp *Process) Running() bool {
|
||||
return dbp.running
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ func (dbp *DebuggedProcess) Running() bool {
|
||||
// * Dwarf .debug_frame section
|
||||
// * Dwarf .debug_line section
|
||||
// * Go symbol table.
|
||||
func (dbp *DebuggedProcess) LoadInformation(path string) error {
|
||||
func (dbp *Process) LoadInformation(path string) error {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
exe, err := dbp.findExecutable(path)
|
||||
@ -148,7 +148,7 @@ func (dbp *DebuggedProcess) LoadInformation(path string) error {
|
||||
}
|
||||
|
||||
// Find a location by string (file+line, function, breakpoint id, addr)
|
||||
func (dbp *DebuggedProcess) FindLocation(str string) (uint64, error) {
|
||||
func (dbp *Process) FindLocation(str string) (uint64, error) {
|
||||
// File + Line
|
||||
if strings.ContainsRune(str, ':') {
|
||||
fl := strings.Split(str, ":")
|
||||
@ -194,7 +194,7 @@ func (dbp *DebuggedProcess) FindLocation(str string) (uint64, error) {
|
||||
|
||||
// Sends out a request that the debugged process halt
|
||||
// execution. Sends SIGSTOP to all threads.
|
||||
func (dbp *DebuggedProcess) RequestManualStop() error {
|
||||
func (dbp *Process) RequestManualStop() error {
|
||||
dbp.halt = true
|
||||
err := dbp.requestManualStop()
|
||||
if err != nil {
|
||||
@ -217,17 +217,17 @@ func (dbp *DebuggedProcess) RequestManualStop() error {
|
||||
// hardware supports it, and there are free debug registers, Delve
|
||||
// will set a hardware breakpoint. Otherwise we fall back to software
|
||||
// breakpoints, which are a bit more work for us.
|
||||
func (dbp *DebuggedProcess) Break(addr uint64) (*Breakpoint, error) {
|
||||
func (dbp *Process) Break(addr uint64) (*Breakpoint, error) {
|
||||
return dbp.setBreakpoint(dbp.CurrentThread.Id, addr, false)
|
||||
}
|
||||
|
||||
// Sets a temp breakpoint, for the 'next' command.
|
||||
func (dbp *DebuggedProcess) TempBreak(addr uint64) (*Breakpoint, error) {
|
||||
func (dbp *Process) TempBreak(addr uint64) (*Breakpoint, error) {
|
||||
return dbp.setBreakpoint(dbp.CurrentThread.Id, addr, true)
|
||||
}
|
||||
|
||||
// Sets a breakpoint by location string (function, file+line, address)
|
||||
func (dbp *DebuggedProcess) BreakByLocation(loc string) (*Breakpoint, error) {
|
||||
func (dbp *Process) BreakByLocation(loc string) (*Breakpoint, error) {
|
||||
addr, err := dbp.FindLocation(loc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -236,12 +236,12 @@ func (dbp *DebuggedProcess) BreakByLocation(loc string) (*Breakpoint, error) {
|
||||
}
|
||||
|
||||
// Clears a breakpoint in the current thread.
|
||||
func (dbp *DebuggedProcess) Clear(addr uint64) (*Breakpoint, error) {
|
||||
func (dbp *Process) Clear(addr uint64) (*Breakpoint, error) {
|
||||
return dbp.clearBreakpoint(dbp.CurrentThread.Id, addr)
|
||||
}
|
||||
|
||||
// Clears a breakpoint by location (function, file+line, address, breakpoint id)
|
||||
func (dbp *DebuggedProcess) ClearByLocation(loc string) (*Breakpoint, error) {
|
||||
func (dbp *Process) ClearByLocation(loc string) (*Breakpoint, error) {
|
||||
addr, err := dbp.FindLocation(loc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -250,16 +250,16 @@ func (dbp *DebuggedProcess) ClearByLocation(loc string) (*Breakpoint, error) {
|
||||
}
|
||||
|
||||
// Returns the status of the current main thread context.
|
||||
func (dbp *DebuggedProcess) Status() *sys.WaitStatus {
|
||||
func (dbp *Process) Status() *sys.WaitStatus {
|
||||
return dbp.CurrentThread.Status
|
||||
}
|
||||
|
||||
// Step over function calls.
|
||||
func (dbp *DebuggedProcess) Next() error {
|
||||
func (dbp *Process) Next() error {
|
||||
return dbp.run(dbp.next)
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) next() error {
|
||||
func (dbp *Process) next() error {
|
||||
// Make sure we clean up the temp breakpoints created by thread.Next
|
||||
defer dbp.clearTempBreakpoints()
|
||||
|
||||
@ -325,7 +325,7 @@ func (dbp *DebuggedProcess) next() error {
|
||||
return dbp.Halt()
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) setChanRecvBreakpoints() (int, error) {
|
||||
func (dbp *Process) setChanRecvBreakpoints() (int, error) {
|
||||
var count int
|
||||
allg, err := dbp.GoroutinesInfo()
|
||||
if err != nil {
|
||||
@ -350,7 +350,7 @@ func (dbp *DebuggedProcess) setChanRecvBreakpoints() (int, error) {
|
||||
}
|
||||
|
||||
// Resume process.
|
||||
func (dbp *DebuggedProcess) Continue() error {
|
||||
func (dbp *Process) Continue() error {
|
||||
for _, thread := range dbp.Threads {
|
||||
err := thread.Continue()
|
||||
if err != nil {
|
||||
@ -360,7 +360,7 @@ func (dbp *DebuggedProcess) Continue() error {
|
||||
return dbp.run(dbp.resume)
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) resume() error {
|
||||
func (dbp *Process) resume() error {
|
||||
thread, err := dbp.trapWait(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -391,7 +391,7 @@ func (dbp *DebuggedProcess) resume() error {
|
||||
}
|
||||
|
||||
// Single step, will execute a single instruction.
|
||||
func (dbp *DebuggedProcess) Step() (err error) {
|
||||
func (dbp *Process) Step() (err error) {
|
||||
fn := func() error {
|
||||
dbp.singleStepping = true
|
||||
defer func() { dbp.singleStepping = false }()
|
||||
@ -411,7 +411,7 @@ func (dbp *DebuggedProcess) Step() (err error) {
|
||||
}
|
||||
|
||||
// Change from current thread to the thread specified by `tid`.
|
||||
func (dbp *DebuggedProcess) SwitchThread(tid int) error {
|
||||
func (dbp *Process) SwitchThread(tid int) error {
|
||||
if th, ok := dbp.Threads[tid]; ok {
|
||||
fmt.Printf("thread context changed from %d to %d\n", dbp.CurrentThread.Id, tid)
|
||||
dbp.CurrentThread = th
|
||||
@ -422,7 +422,7 @@ func (dbp *DebuggedProcess) SwitchThread(tid int) error {
|
||||
|
||||
// Returns an array of G structures representing the information
|
||||
// Delve cares about from the internal runtime G structure.
|
||||
func (dbp *DebuggedProcess) GoroutinesInfo() ([]*G, error) {
|
||||
func (dbp *Process) GoroutinesInfo() ([]*G, error) {
|
||||
var (
|
||||
threadg = map[int]*Thread{}
|
||||
allg []*G
|
||||
@ -471,7 +471,7 @@ func (dbp *DebuggedProcess) GoroutinesInfo() ([]*G, error) {
|
||||
}
|
||||
|
||||
// Stop all threads.
|
||||
func (dbp *DebuggedProcess) Halt() (err error) {
|
||||
func (dbp *Process) Halt() (err error) {
|
||||
for _, th := range dbp.Threads {
|
||||
if err := th.Halt(); err != nil {
|
||||
return err
|
||||
@ -482,47 +482,47 @@ func (dbp *DebuggedProcess) Halt() (err error) {
|
||||
|
||||
// Obtains register values from what Delve considers to be the current
|
||||
// thread of the traced process.
|
||||
func (dbp *DebuggedProcess) Registers() (Registers, error) {
|
||||
func (dbp *Process) Registers() (Registers, error) {
|
||||
return dbp.CurrentThread.Registers()
|
||||
}
|
||||
|
||||
// Returns the PC of the current thread.
|
||||
func (dbp *DebuggedProcess) PC() (uint64, error) {
|
||||
func (dbp *Process) PC() (uint64, error) {
|
||||
return dbp.CurrentThread.PC()
|
||||
}
|
||||
|
||||
// Returns the PC of the current thread.
|
||||
func (dbp *DebuggedProcess) CurrentBreakpoint() *Breakpoint {
|
||||
func (dbp *Process) CurrentBreakpoint() *Breakpoint {
|
||||
return dbp.CurrentThread.CurrentBreakpoint
|
||||
}
|
||||
|
||||
// Returns the value of the named symbol.
|
||||
func (dbp *DebuggedProcess) EvalVariable(name string) (*Variable, error) {
|
||||
func (dbp *Process) EvalVariable(name string) (*Variable, error) {
|
||||
return dbp.CurrentThread.EvalVariable(name)
|
||||
}
|
||||
|
||||
// Returns a reader for the dwarf data
|
||||
func (dbp *DebuggedProcess) DwarfReader() *reader.Reader {
|
||||
func (dbp *Process) DwarfReader() *reader.Reader {
|
||||
return reader.New(dbp.dwarf)
|
||||
}
|
||||
|
||||
// Returns list of source files that comprise the debugged binary.
|
||||
func (dbp *DebuggedProcess) Sources() map[string]*gosym.Obj {
|
||||
func (dbp *Process) Sources() map[string]*gosym.Obj {
|
||||
return dbp.goSymTable.Files
|
||||
}
|
||||
|
||||
// Returns list of functions present in the debugged program.
|
||||
func (dbp *DebuggedProcess) Funcs() []gosym.Func {
|
||||
func (dbp *Process) Funcs() []gosym.Func {
|
||||
return dbp.goSymTable.Funcs
|
||||
}
|
||||
|
||||
// Converts an instruction address to a file/line/function.
|
||||
func (dbp *DebuggedProcess) PCToLine(pc uint64) (string, int, *gosym.Func) {
|
||||
func (dbp *Process) PCToLine(pc uint64) (string, int, *gosym.Func) {
|
||||
return dbp.goSymTable.PCToLine(pc)
|
||||
}
|
||||
|
||||
// Finds the breakpoint for the given ID.
|
||||
func (dbp *DebuggedProcess) FindBreakpointByID(id int) (*Breakpoint, bool) {
|
||||
func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) {
|
||||
for _, bp := range dbp.Breakpoints {
|
||||
if bp.ID == id {
|
||||
return bp, true
|
||||
@ -532,7 +532,7 @@ func (dbp *DebuggedProcess) FindBreakpointByID(id int) (*Breakpoint, bool) {
|
||||
}
|
||||
|
||||
// Finds the breakpoint for the given pc.
|
||||
func (dbp *DebuggedProcess) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
|
||||
func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
|
||||
// Check for software breakpoint. PC will be at
|
||||
// breakpoint instruction + size of breakpoint.
|
||||
if bp, ok := dbp.Breakpoints[pc-uint64(dbp.arch.BreakpointSize())]; ok {
|
||||
@ -548,8 +548,8 @@ func (dbp *DebuggedProcess) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Returns a new DebuggedProcess struct.
|
||||
func initializeDebugProcess(dbp *DebuggedProcess, path string, attach bool) (*DebuggedProcess, error) {
|
||||
// Returns a new Process struct.
|
||||
func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, error) {
|
||||
if attach {
|
||||
var err error
|
||||
dbp.execPtraceFunc(func() { err = sys.PtraceAttach(dbp.Pid) })
|
||||
@ -585,7 +585,7 @@ func initializeDebugProcess(dbp *DebuggedProcess, path string, attach bool) (*De
|
||||
return dbp, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) clearTempBreakpoints() error {
|
||||
func (dbp *Process) clearTempBreakpoints() error {
|
||||
for _, bp := range dbp.Breakpoints {
|
||||
if !bp.Temp {
|
||||
continue
|
||||
@ -597,7 +597,7 @@ func (dbp *DebuggedProcess) clearTempBreakpoints() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) handleBreakpointOnThread(id int) (*Thread, error) {
|
||||
func (dbp *Process) handleBreakpointOnThread(id int) (*Thread, error) {
|
||||
thread, ok := dbp.Threads[id]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("could not find thread for %d", id)
|
||||
@ -631,7 +631,7 @@ func (dbp *DebuggedProcess) handleBreakpointOnThread(id int) (*Thread, error) {
|
||||
return nil, NoBreakpointError{addr: pc}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) run(fn func() error) error {
|
||||
func (dbp *Process) run(fn func() error) error {
|
||||
if dbp.exited {
|
||||
return fmt.Errorf("process has already exited")
|
||||
}
|
||||
@ -649,7 +649,7 @@ func (dbp *DebuggedProcess) run(fn func() error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) handlePtraceFuncs() {
|
||||
func (dbp *Process) handlePtraceFuncs() {
|
||||
// We must ensure here that we are running on the same thread during
|
||||
// the execution of dbg. This is due to the fact that ptrace(2) expects
|
||||
// all commands after PTRACE_ATTACH to come from the same thread.
|
||||
@ -661,7 +661,7 @@ func (dbp *DebuggedProcess) handlePtraceFuncs() {
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) execPtraceFunc(fn func()) {
|
||||
func (dbp *Process) execPtraceFunc(fn func()) {
|
||||
dbp.ptraceChan <- fn
|
||||
<-dbp.ptraceDoneChan
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ type OSProcessDetails struct {
|
||||
// custom fork/exec process in order to take advantage of
|
||||
// PT_SIGEXC on Darwin which will turn Unix signals into
|
||||
// Mach exceptions.
|
||||
func Launch(cmd []string) (*DebuggedProcess, error) {
|
||||
func Launch(cmd []string) (*Process, error) {
|
||||
argv0Go, err := filepath.Abs(cmd[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -70,7 +70,7 @@ func Launch(cmd []string) (*DebuggedProcess, error) {
|
||||
return dbp, err
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) requestManualStop() (err error) {
|
||||
func (dbp *Process) requestManualStop() (err error) {
|
||||
var (
|
||||
task = C.mach_port_t(dbp.os.task)
|
||||
thread = C.mach_port_t(dbp.CurrentThread.os.thread_act)
|
||||
@ -83,7 +83,7 @@ func (dbp *DebuggedProcess) requestManualStop() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) updateThreadList() error {
|
||||
func (dbp *Process) updateThreadList() error {
|
||||
var (
|
||||
err error
|
||||
kret C.kern_return_t
|
||||
@ -116,7 +116,7 @@ func (dbp *DebuggedProcess) updateThreadList() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) addThread(port int, attach bool) (*Thread, error) {
|
||||
func (dbp *Process) addThread(port int, attach bool) (*Thread, error) {
|
||||
if thread, ok := dbp.Threads[port]; ok {
|
||||
return thread, nil
|
||||
}
|
||||
@ -133,7 +133,7 @@ func (dbp *DebuggedProcess) addThread(port int, attach bool) (*Thread, error) {
|
||||
return thread, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) parseDebugFrame(exe *macho.File, wg *sync.WaitGroup) {
|
||||
func (dbp *Process) parseDebugFrame(exe *macho.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if sec := exe.Section("__debug_frame"); sec != nil {
|
||||
@ -149,7 +149,7 @@ func (dbp *DebuggedProcess) parseDebugFrame(exe *macho.File, wg *sync.WaitGroup)
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) obtainGoSymbols(exe *macho.File, wg *sync.WaitGroup) {
|
||||
func (dbp *Process) obtainGoSymbols(exe *macho.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var (
|
||||
@ -184,7 +184,7 @@ func (dbp *DebuggedProcess) obtainGoSymbols(exe *macho.File, wg *sync.WaitGroup)
|
||||
dbp.goSymTable = tab
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) parseDebugLineInfo(exe *macho.File, wg *sync.WaitGroup) {
|
||||
func (dbp *Process) parseDebugLineInfo(exe *macho.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if sec := exe.Section("__debug_line"); sec != nil {
|
||||
@ -200,7 +200,7 @@ func (dbp *DebuggedProcess) parseDebugLineInfo(exe *macho.File, wg *sync.WaitGro
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) findExecutable(path string) (*macho.File, error) {
|
||||
func (dbp *Process) findExecutable(path string) (*macho.File, error) {
|
||||
if path == "" {
|
||||
path = C.GoString(C.find_executable(C.int(dbp.Pid)))
|
||||
}
|
||||
@ -216,7 +216,7 @@ func (dbp *DebuggedProcess) findExecutable(path string) (*macho.File, error) {
|
||||
return exe, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) trapWait(pid int) (*Thread, error) {
|
||||
func (dbp *Process) trapWait(pid int) (*Thread, error) {
|
||||
var (
|
||||
th *Thread
|
||||
err error
|
||||
|
@ -29,7 +29,7 @@ type OSProcessDetails interface{}
|
||||
// Create and begin debugging a new process. First entry in
|
||||
// `cmd` is the program to run, and then rest are the arguments
|
||||
// to be supplied to that process.
|
||||
func Launch(cmd []string) (*DebuggedProcess, error) {
|
||||
func Launch(cmd []string) (*Process, error) {
|
||||
var (
|
||||
proc *exec.Cmd
|
||||
err error
|
||||
@ -54,13 +54,13 @@ func Launch(cmd []string) (*DebuggedProcess, error) {
|
||||
return initializeDebugProcess(dbp, proc.Path, false)
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) requestManualStop() (err error) {
|
||||
func (dbp *Process) requestManualStop() (err error) {
|
||||
return sys.Kill(dbp.Pid, sys.SIGSTOP)
|
||||
}
|
||||
|
||||
// Attach to a newly created thread, and store that thread in our list of
|
||||
// known threads.
|
||||
func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*Thread, error) {
|
||||
func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) {
|
||||
if thread, ok := dbp.Threads[tid]; ok {
|
||||
return thread, nil
|
||||
}
|
||||
@ -112,7 +112,7 @@ func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*Thread, error) {
|
||||
return dbp.Threads[tid], nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) updateThreadList() error {
|
||||
func (dbp *Process) updateThreadList() error {
|
||||
var attach bool
|
||||
tids, _ := filepath.Glob(fmt.Sprintf("/proc/%d/task/*", dbp.Pid))
|
||||
for _, tidpath := range tids {
|
||||
@ -131,7 +131,7 @@ func (dbp *DebuggedProcess) updateThreadList() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) findExecutable(path string) (*elf.File, error) {
|
||||
func (dbp *Process) findExecutable(path string) (*elf.File, error) {
|
||||
if path == "" {
|
||||
path = fmt.Sprintf("/proc/%d/exe", dbp.Pid)
|
||||
}
|
||||
@ -154,7 +154,7 @@ func (dbp *DebuggedProcess) findExecutable(path string) (*elf.File, error) {
|
||||
return elffile, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) {
|
||||
func (dbp *Process) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if sec := exe.Section(".debug_frame"); sec != nil {
|
||||
@ -170,7 +170,7 @@ func (dbp *DebuggedProcess) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) {
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) {
|
||||
func (dbp *Process) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var (
|
||||
@ -205,7 +205,7 @@ func (dbp *DebuggedProcess) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) {
|
||||
dbp.goSymTable = tab
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) parseDebugLineInfo(exe *elf.File, wg *sync.WaitGroup) {
|
||||
func (dbp *Process) parseDebugLineInfo(exe *elf.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if sec := exe.Section(".debug_line"); sec != nil {
|
||||
@ -221,7 +221,7 @@ func (dbp *DebuggedProcess) parseDebugLineInfo(exe *elf.File, wg *sync.WaitGroup
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) trapWait(pid int) (*Thread, error) {
|
||||
func (dbp *Process) trapWait(pid int) (*Thread, error) {
|
||||
for {
|
||||
wpid, status, err := wait(pid, 0)
|
||||
if err != nil {
|
||||
|
@ -18,7 +18,7 @@ func TestMain(m *testing.M) {
|
||||
protest.RunTestsWithFixtures(m)
|
||||
}
|
||||
|
||||
func withTestProcess(name string, t *testing.T, fn func(p *DebuggedProcess, fixture protest.Fixture)) {
|
||||
func withTestProcess(name string, t *testing.T, fn func(p *Process, fixture protest.Fixture)) {
|
||||
fixture := protest.BuildFixture(name)
|
||||
p, err := Launch([]string{fixture.Path})
|
||||
if err != nil {
|
||||
@ -30,7 +30,7 @@ func withTestProcess(name string, t *testing.T, fn func(p *DebuggedProcess, fixt
|
||||
fn(p, fixture)
|
||||
}
|
||||
|
||||
func getRegisters(p *DebuggedProcess, t *testing.T) Registers {
|
||||
func getRegisters(p *Process, t *testing.T) Registers {
|
||||
regs, err := p.Registers()
|
||||
if err != nil {
|
||||
t.Fatal("Registers():", err)
|
||||
@ -57,7 +57,7 @@ func assertNoError(err error, t *testing.T, s string) {
|
||||
}
|
||||
}
|
||||
|
||||
func currentPC(p *DebuggedProcess, t *testing.T) uint64 {
|
||||
func currentPC(p *Process, t *testing.T) uint64 {
|
||||
pc, err := p.PC()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -66,7 +66,7 @@ func currentPC(p *DebuggedProcess, t *testing.T) uint64 {
|
||||
return pc
|
||||
}
|
||||
|
||||
func currentLineNumber(p *DebuggedProcess, t *testing.T) (string, int) {
|
||||
func currentLineNumber(p *Process, t *testing.T) (string, int) {
|
||||
pc := currentPC(p, t)
|
||||
f, l, _ := p.goSymTable.PCToLine(pc)
|
||||
|
||||
@ -74,7 +74,7 @@ func currentLineNumber(p *DebuggedProcess, t *testing.T) (string, int) {
|
||||
}
|
||||
|
||||
func TestExit(t *testing.T) {
|
||||
withTestProcess("continuetestprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("continuetestprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
err := p.Continue()
|
||||
pe, ok := err.(ProcessExitedError)
|
||||
if !ok {
|
||||
@ -91,7 +91,7 @@ func TestExit(t *testing.T) {
|
||||
|
||||
func TestHalt(t *testing.T) {
|
||||
runtime.GOMAXPROCS(2)
|
||||
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
go func() {
|
||||
for {
|
||||
if p.Running() {
|
||||
@ -120,7 +120,7 @@ func TestHalt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStep(t *testing.T) {
|
||||
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
helloworldfunc := p.goSymTable.LookupFunc("main.helloworld")
|
||||
helloworldaddr := helloworldfunc.Entry
|
||||
|
||||
@ -142,7 +142,7 @@ func TestStep(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBreakpoint(t *testing.T) {
|
||||
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
helloworldfunc := p.goSymTable.LookupFunc("main.helloworld")
|
||||
helloworldaddr := helloworldfunc.Entry
|
||||
|
||||
@ -163,7 +163,7 @@ func TestBreakpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBreakpointInSeperateGoRoutine(t *testing.T) {
|
||||
withTestProcess("testthreads", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testthreads", t, func(p *Process, fixture protest.Fixture) {
|
||||
fn := p.goSymTable.LookupFunc("main.anotherthread")
|
||||
if fn == nil {
|
||||
t.Fatal("No fn exists")
|
||||
@ -192,7 +192,7 @@ func TestBreakpointInSeperateGoRoutine(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBreakpointWithNonExistantFunction(t *testing.T) {
|
||||
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
_, err := p.Break(0)
|
||||
if err == nil {
|
||||
t.Fatal("Should not be able to break at non existant function")
|
||||
@ -201,7 +201,7 @@ func TestBreakpointWithNonExistantFunction(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClearBreakpoint(t *testing.T) {
|
||||
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
fn := p.goSymTable.LookupFunc("main.sleepytime")
|
||||
bp, err := p.Break(fn.Entry)
|
||||
assertNoError(err, t, "Break()")
|
||||
@ -230,7 +230,7 @@ type nextTest struct {
|
||||
}
|
||||
|
||||
func testnext(program string, testcases []nextTest, initialLocation string, t *testing.T) {
|
||||
withTestProcess(program, t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess(program, t, func(p *Process, fixture protest.Fixture) {
|
||||
bp, err := p.BreakByLocation(initialLocation)
|
||||
assertNoError(err, t, "Break()")
|
||||
assertNoError(p.Continue(), t, "Continue()")
|
||||
@ -303,7 +303,7 @@ func TestNextFunctionReturnDefer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRuntimeBreakpoint(t *testing.T) {
|
||||
withTestProcess("testruntimebreakpoint", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testruntimebreakpoint", t, func(p *Process, fixture protest.Fixture) {
|
||||
err := p.Continue()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -320,7 +320,7 @@ func TestRuntimeBreakpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFindReturnAddress(t *testing.T) {
|
||||
withTestProcess("testnextprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testnextprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
var (
|
||||
fdes = p.frameEntries
|
||||
gsd = p.goSymTable
|
||||
@ -370,7 +370,7 @@ func TestFindReturnAddress(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSwitchThread(t *testing.T) {
|
||||
withTestProcess("testnextprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testnextprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
// With invalid thread id
|
||||
err := p.SwitchThread(-1)
|
||||
if err == nil {
|
||||
@ -430,7 +430,7 @@ func TestStacktrace(t *testing.T) {
|
||||
[]loc{{8, "main.func1"}, {16, "main.main"}},
|
||||
[]loc{{8, "main.func1"}, {12, "main.func2"}, {17, "main.main"}},
|
||||
}
|
||||
withTestProcess("stacktraceprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("stacktraceprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
bp, err := p.BreakByLocation("main.stacktraceme")
|
||||
assertNoError(err, t, "BreakByLocation()")
|
||||
|
||||
@ -471,7 +471,7 @@ func TestStacktraceGoroutine(t *testing.T) {
|
||||
mainStack := []loc{{21, "main.main"}}
|
||||
agoroutineStack := []loc{{-1, "runtime.goparkunlock"}, {-1, "runtime.chansend"}, {-1, "runtime.chansend1"}, {8, "main.agoroutine"}}
|
||||
|
||||
withTestProcess("goroutinestackprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("goroutinestackprog", t, func(p *Process, fixture protest.Fixture) {
|
||||
bp, err := p.BreakByLocation("main.stacktraceme")
|
||||
assertNoError(err, t, "BreakByLocation()")
|
||||
|
||||
|
@ -30,14 +30,14 @@ func (thread *Thread) Stacktrace(depth int) ([]Location, error) {
|
||||
|
||||
// Returns the stack trace for a goroutine
|
||||
// Note that it doesn't include the current frame and the locations in the array are return addresses not call addresses
|
||||
func (dbp *DebuggedProcess) GoroutineStacktrace(g *G, depth int) ([]Location, error) {
|
||||
func (dbp *Process) GoroutineStacktrace(g *G, depth int) ([]Location, error) {
|
||||
if g.thread != nil {
|
||||
return g.thread.Stacktrace(depth)
|
||||
}
|
||||
return dbp.stacktrace(g.PC, g.SP, depth)
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) GoroutineLocation(g *G) *Location {
|
||||
func (dbp *Process) GoroutineLocation(g *G) *Location {
|
||||
f, l, fn := dbp.PCToLine(g.PC)
|
||||
return &Location{PC: g.PC, File: f, Line: l, Fn: fn}
|
||||
}
|
||||
@ -48,7 +48,7 @@ func (n NullAddrError) Error() string {
|
||||
return "NULL address"
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) stacktrace(pc, sp uint64, depth int) ([]Location, error) {
|
||||
func (dbp *Process) stacktrace(pc, sp uint64, depth int) ([]Location, error) {
|
||||
var (
|
||||
ret = pc
|
||||
data = make([]byte, dbp.arch.PtrSize())
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
|
||||
// Thread represents a single thread in the traced process
|
||||
// Id represents the thread id or port, Process holds a reference to the
|
||||
// DebuggedProcess struct that contains info on the process as
|
||||
// Process struct that contains info on the process as
|
||||
// a whole, and Status represents the last result of a `wait` call
|
||||
// on this thread.
|
||||
type Thread struct {
|
||||
@ -20,7 +20,7 @@ type Thread struct {
|
||||
Status *sys.WaitStatus // Status returned from last wait call
|
||||
CurrentBreakpoint *Breakpoint // Breakpoint thread is currently stopped at
|
||||
|
||||
dbp *DebuggedProcess
|
||||
dbp *Process
|
||||
singleStepping bool
|
||||
running bool
|
||||
os *OSSpecificDetails
|
||||
@ -298,7 +298,7 @@ func (thread *Thread) getG() (g *G, err error) {
|
||||
// we hit a breakpoint that isn't captured in our list of
|
||||
// known breakpoints.
|
||||
thread.dbp.halt = true
|
||||
defer func(dbp *DebuggedProcess) { dbp.halt = false }(thread.dbp)
|
||||
defer func(dbp *Process) { dbp.halt = false }(thread.dbp)
|
||||
if _, err = thread.dbp.trapWait(-1); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func (g *G) ChanRecvBlocked() bool {
|
||||
}
|
||||
|
||||
// chanRecvReturnAddr returns the address of the return from a channel read.
|
||||
func (g *G) chanRecvReturnAddr(dbp *DebuggedProcess) (uint64, error) {
|
||||
func (g *G) chanRecvReturnAddr(dbp *Process) (uint64, error) {
|
||||
locs, err := dbp.stacktrace(g.PC, g.SP, 4)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -67,7 +67,7 @@ func TestVariableEvaluation(t *testing.T) {
|
||||
{"NonExistent", "", "", fmt.Errorf("could not find symbol value for NonExistent")},
|
||||
}
|
||||
|
||||
withTestProcess("testvariables", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testvariables", t, func(p *Process, fixture protest.Fixture) {
|
||||
pc, _, _ := p.goSymTable.LineToPC(fixture.Source, 57)
|
||||
|
||||
_, err := p.Break(pc)
|
||||
@ -91,7 +91,7 @@ func TestVariableEvaluation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVariableFunctionScoping(t *testing.T) {
|
||||
withTestProcess("testvariables", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testvariables", t, func(p *Process, fixture protest.Fixture) {
|
||||
pc, _, _ := p.goSymTable.LineToPC(fixture.Source, 57)
|
||||
|
||||
_, err := p.Break(pc)
|
||||
@ -183,7 +183,7 @@ func TestLocalVariables(t *testing.T) {
|
||||
{"baz", "bazburzum", "struct string", nil}}},
|
||||
}
|
||||
|
||||
withTestProcess("testvariables", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||
withTestProcess("testvariables", t, func(p *Process, fixture protest.Fixture) {
|
||||
pc, _, _ := p.goSymTable.LineToPC(fixture.Source, 57)
|
||||
|
||||
_, err := p.Break(pc)
|
||||
|
@ -12,14 +12,14 @@ import (
|
||||
// Debugger service.
|
||||
//
|
||||
// Debugger provides a higher level of
|
||||
// abstraction over proc.DebuggedProcess.
|
||||
// abstraction over proc.Process.
|
||||
// It handles converting from internal types to
|
||||
// the types expected by clients. It also handles
|
||||
// functionality needed by clients, but not needed in
|
||||
// lower lever packages such as proc.
|
||||
type Debugger struct {
|
||||
config *Config
|
||||
process *proc.DebuggedProcess
|
||||
process *proc.Process
|
||||
}
|
||||
|
||||
// Config provides the configuration to start a Debugger.
|
||||
|
Loading…
Reference in New Issue
Block a user