diff --git a/pkg/target/target.go b/pkg/target/target.go new file mode 100644 index 00000000..14929008 --- /dev/null +++ b/pkg/target/target.go @@ -0,0 +1,84 @@ +package target + +import ( + "debug/gosym" + "go/ast" + "time" + + "github.com/derekparker/delve/proc" +) + +// Target represents the target of the debugger. This +// target could be a system process, core file, etc. +type Interface interface { + Info + ProcessManipulation + BreakpointManipulation + VariableEval +} + +// Info is an interface that provides general information on the target. +type Info interface { + Pid() int + Exited() bool + Running() bool + + BinaryInfo + ThreadInfo + GoroutineInfo +} + +// BinaryInfo is an interface for accessing information on the binary file +// and the contents of binary sections. +type BinaryInfo interface { + LastModified() time.Time + Sources() map[string]*gosym.Obj + FindFileLocation(fileName string, lineNumber int) (uint64, error) + FindFunctionLocation(funcName string, firstLine bool, lineOffset int) (uint64, error) + Funcs() []gosym.Func + Types() ([]string, error) + PCToLine(uint64) (string, int, *gosym.Func) + FirstPCAfterPrologue(fn *gosym.Func, sameline bool) (uint64, error) +} + +// ThreadInfo is an interface for getting information on active threads +// in the process. +type ThreadInfo interface { + Threads() map[int]*proc.Thread + CurrentThread() *proc.Thread +} + +// GoroutineInfo is an interface for getting information on running goroutines. +type GoroutineInfo interface { + GoroutinesInfo() ([]*proc.G, error) + SelectedGoroutine() *proc.G + FindGoroutine(int) (*proc.G, error) +} + +// ProcessManipulation is an interface for changing the execution state of a process. +type ProcessManipulation interface { + Continue() error + Next() error + Step() error + StepOut() error + StepInstruction() error + SwitchThread(int) error + SwitchGoroutine(int) error + RequestManualStop() error + Halt() error + Kill() error + Detach(bool) error +} + +// BreakpointManipulation is an interface for managing breakpoints. +type BreakpointManipulation interface { + Breakpoints() map[uint64]*proc.Breakpoint + SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error) + ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) + ClearInternalBreakpoints() error +} + +// VariableEval is an interface for dealing with eval scopes. +type VariableEval interface { + ConvertEvalScope(gid, frame int) (*proc.EvalScope, error) +} diff --git a/proc/disasm.go b/proc/disasm.go index be2db19f..731336e2 100644 --- a/proc/disasm.go +++ b/proc/disasm.go @@ -41,7 +41,7 @@ func (thread *Thread) Disassemble(startPC, endPC uint64, currentGoroutine bool) } for len(mem) > 0 { - bp, atbp := thread.dbp.Breakpoints[pc] + bp, atbp := thread.dbp.breakpoints[pc] if atbp { for i := range bp.OriginalData { mem[i] = bp.OriginalData[i] diff --git a/proc/disasm_amd64.go b/proc/disasm_amd64.go index cebf51b6..ebe085be 100644 --- a/proc/disasm_amd64.go +++ b/proc/disasm_amd64.go @@ -3,6 +3,7 @@ package proc import ( "debug/gosym" "encoding/binary" + "rsc.io/x86/x86asm" ) @@ -145,7 +146,7 @@ func init() { // FirstPCAfterPrologue returns the address of the first instruction after the prologue for function fn // If sameline is set FirstPCAfterPrologue will always return an address associated with the same line as fn.Entry func (dbp *Process) FirstPCAfterPrologue(fn *gosym.Func, sameline bool) (uint64, error) { - text, err := dbp.CurrentThread.Disassemble(fn.Entry, fn.End, false) + text, err := dbp.CurrentThread().Disassemble(fn.Entry, fn.End, false) if err != nil { return fn.Entry, err } diff --git a/proc/moduledata.go b/proc/moduledata.go index 8652a5a5..ae9d8402 100644 --- a/proc/moduledata.go +++ b/proc/moduledata.go @@ -13,7 +13,7 @@ type moduleData struct { func (dbp *Process) loadModuleData() (err error) { dbp.loadModuleDataOnce.Do(func() { - scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0} + scope := &EvalScope{Thread: dbp.currentThread, PC: 0, CFA: 0} var md *Variable md, err = scope.packageVarAddr("runtime.firstmoduledata") if err != nil { @@ -84,13 +84,13 @@ func (dbp *Process) resolveTypeOff(typeAddr uintptr, off uintptr) (*Variable, er return v.newVariable(v.Name, uintptr(addr), rtyp), nil } - if t, _ := md.typemapVar.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.CurrentThread)); t != nil { + if t, _ := md.typemapVar.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.currentThread)); t != nil { return t, nil } res := md.types + uintptr(off) - return dbp.CurrentThread.newVariable("", res, rtyp), nil + return dbp.currentThread.newVariable("", res, rtyp), nil } func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (name, tag string, pkgpathoff int32, err error) { @@ -119,7 +119,7 @@ func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (name, tag str } func (dbp *Process) reflectOffsMapAccess(off uintptr) (*Variable, error) { - scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0} + scope := &EvalScope{Thread: dbp.currentThread, PC: 0, CFA: 0} reflectOffs, err := scope.packageVarAddr("runtime.reflectOffs") if err != nil { return nil, err @@ -130,7 +130,7 @@ func (dbp *Process) reflectOffsMapAccess(off uintptr) (*Variable, error) { return nil, err } - return reflectOffsm.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.CurrentThread)) + return reflectOffsm.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.currentThread)) } const ( @@ -142,7 +142,7 @@ const ( func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32, err error) { off := addr - namedata, err := dbp.CurrentThread.readMemory(off, 3) + namedata, err := dbp.currentThread.readMemory(off, 3) off += 3 if err != nil { return "", "", 0, err @@ -150,7 +150,7 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32, namelen := uint16(namedata[1]<<8) | uint16(namedata[2]) - rawstr, err := dbp.CurrentThread.readMemory(off, int(namelen)) + rawstr, err := dbp.currentThread.readMemory(off, int(namelen)) off += uintptr(namelen) if err != nil { return "", "", 0, err @@ -159,14 +159,14 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32, name = string(rawstr) if namedata[0]&nameflagHasTag != 0 { - taglendata, err := dbp.CurrentThread.readMemory(off, 2) + taglendata, err := dbp.currentThread.readMemory(off, 2) off += 2 if err != nil { return "", "", 0, err } taglen := uint16(taglendata[0]<<8) | uint16(taglendata[1]) - rawstr, err := dbp.CurrentThread.readMemory(off, int(taglen)) + rawstr, err := dbp.currentThread.readMemory(off, int(taglen)) off += uintptr(taglen) if err != nil { return "", "", 0, err @@ -176,7 +176,7 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32, } if namedata[0]&nameflagHasPkg != 0 { - pkgdata, err := dbp.CurrentThread.readMemory(off, 4) + pkgdata, err := dbp.currentThread.readMemory(off, 4) if err != nil { return "", "", 0, err } diff --git a/proc/proc.go b/proc/proc.go index 36b747e4..1dfe2513 100644 --- a/proc/proc.go +++ b/proc/proc.go @@ -25,23 +25,23 @@ import ( // Process represents all of the information the debugger // is holding onto regarding the process we are debugging. type Process struct { - Pid int // Process Pid + pid int // Process Pid Process *os.Process // Pointer to process struct for the actual process we are debugging - LastModified time.Time // Time the executable of this process was last modified + lastModified time.Time // Time the executable of this process was last modified // Breakpoint table, holds information on breakpoints. // Maps instruction address to Breakpoint struct. - Breakpoints map[uint64]*Breakpoint + breakpoints map[uint64]*Breakpoint // List of threads mapped as such: pid -> *Thread - Threads map[int]*Thread + threads map[int]*Thread // Active thread - CurrentThread *Thread + currentThread *Thread // Goroutine that will be used by default to set breakpoint, eval variables, etc... - // Normally SelectedGoroutine is CurrentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread - SelectedGoroutine *G + // Normally selectedGoroutine is currentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread + selectedGoroutine *G // Maps package names to package paths, needed to lookup types inside DWARF info packageMap map[string]string @@ -81,9 +81,9 @@ var NotExecutableErr = errors.New("not an executable file") // `handlePtraceFuncs`. func New(pid int) *Process { dbp := &Process{ - Pid: pid, - Threads: make(map[int]*Thread), - Breakpoints: make(map[uint64]*Breakpoint), + pid: pid, + threads: make(map[int]*Thread), + breakpoints: make(map[uint64]*Breakpoint), firstStart: true, os: new(OSProcessDetails), ptraceChan: make(chan func()), @@ -119,7 +119,7 @@ func (dbp *Process) Detach(kill bool) (err error) { } if !kill { // Clean up any breakpoints we've set. - for _, bp := range dbp.Breakpoints { + for _, bp := range dbp.breakpoints { if bp != nil { _, err := dbp.ClearBreakpoint(bp.Addr) if err != nil { @@ -129,12 +129,12 @@ func (dbp *Process) Detach(kill bool) (err error) { } } dbp.execPtraceFunc(func() { - err = PtraceDetach(dbp.Pid, 0) + err = PtraceDetach(dbp.pid, 0) if err != nil { return } if kill { - err = killProcess(dbp.Pid) + err = killProcess(dbp.pid) } }) return @@ -149,7 +149,7 @@ func (dbp *Process) Exited() bool { // Running returns whether the debugged // process is currently executing. func (dbp *Process) Running() bool { - for _, th := range dbp.Threads { + for _, th := range dbp.threads { if th.running { return true } @@ -157,6 +157,30 @@ func (dbp *Process) Running() bool { return false } +func (dbp *Process) LastModified() time.Time { + return dbp.lastModified +} + +func (dbp *Process) Pid() int { + return dbp.pid +} + +func (dbp *Process) SelectedGoroutine() *G { + return dbp.selectedGoroutine +} + +func (dbp *Process) Threads() map[int]*Thread { + return dbp.threads +} + +func (dbp *Process) CurrentThread() *Thread { + return dbp.currentThread +} + +func (dbp *Process) Breakpoints() map[uint64]*Breakpoint { + return dbp.breakpoints +} + // LoadInformation finds the executable and then uses it // to parse the following information: // * Dwarf .debug_frame section @@ -171,7 +195,7 @@ func (dbp *Process) LoadInformation(path string) error { } fi, err := os.Stat(path) if err == nil { - dbp.LastModified = fi.ModTime() + dbp.lastModified = fi.ModTime() } wg.Add(5) @@ -223,7 +247,7 @@ func (dbp *Process) FindFunctionLocation(funcName string, firstLine bool, lineOf // CurrentLocation returns the location of the current thread. func (dbp *Process) CurrentLocation() (*Location, error) { - return dbp.CurrentThread.Location() + return dbp.currentThread.Location() } // RequestManualStop sets the `halt` flag and @@ -240,7 +264,7 @@ func (dbp *Process) RequestManualStop() error { // break point table. Setting a break point must be thread specific due to // ptrace actions needing the thread to be in a signal-delivery-stop. func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error) { - tid := dbp.CurrentThread.ID + tid := dbp.currentThread.ID if bp, ok := dbp.FindBreakpoint(addr); ok { return nil, BreakpointExistsError{bp.File, bp.Line, bp.Addr} @@ -269,7 +293,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp newBreakpoint.ID = dbp.breakpointIDCounter } - thread := dbp.Threads[tid] + thread := dbp.threads[tid] originalData, err := thread.readMemory(uintptr(addr), dbp.arch.BreakpointSize()) if err != nil { return nil, err @@ -278,7 +302,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp return nil, err } newBreakpoint.OriginalData = originalData - dbp.Breakpoints[addr] = newBreakpoint + dbp.breakpoints[addr] = newBreakpoint return newBreakpoint, nil } @@ -293,18 +317,18 @@ func (dbp *Process) ClearBreakpoint(addr uint64) (*Breakpoint, error) { return nil, NoBreakpointError{addr: addr} } - if _, err := bp.Clear(dbp.CurrentThread); err != nil { + if _, err := bp.Clear(dbp.currentThread); err != nil { return nil, err } - delete(dbp.Breakpoints, addr) + delete(dbp.breakpoints, addr) return bp, nil } // Status returns the status of the current main thread context. func (dbp *Process) Status() *WaitStatus { - return dbp.CurrentThread.Status + return dbp.currentThread.Status } // Next continues execution until the next source line. @@ -312,8 +336,8 @@ func (dbp *Process) Next() (err error) { if dbp.exited { return &ProcessExitedError{} } - for i := range dbp.Breakpoints { - if dbp.Breakpoints[i].Internal() { + for i := range dbp.breakpoints { + if dbp.breakpoints[i].Internal() { return fmt.Errorf("next while nexting") } } @@ -343,7 +367,7 @@ func (dbp *Process) Continue() error { } dbp.allGCache = nil - for _, th := range dbp.Threads { + for _, th := range dbp.threads { th.clearBreakpointState() } @@ -362,42 +386,42 @@ func (dbp *Process) Continue() error { } switch { - case dbp.CurrentThread.CurrentBreakpoint == nil: + case dbp.currentThread.CurrentBreakpoint == nil: // runtime.Breakpoint or manual stop - if dbp.CurrentThread.onRuntimeBreakpoint() { + if dbp.currentThread.onRuntimeBreakpoint() { // Single-step current thread until we exit runtime.breakpoint and // runtime.Breakpoint. // On go < 1.8 it was sufficient to single-step twice on go1.8 a change // to the compiler requires 4 steps. for { - if err = dbp.CurrentThread.StepInstruction(); err != nil { + if err = dbp.currentThread.StepInstruction(); err != nil { return err } - loc, err := dbp.CurrentThread.Location() + loc, err := dbp.currentThread.Location() if err != nil || loc.Fn == nil || (loc.Fn.Name != "runtime.breakpoint" && loc.Fn.Name != "runtime.Breakpoint") { break } } } return dbp.conditionErrors() - case dbp.CurrentThread.onTriggeredInternalBreakpoint(): - if dbp.CurrentThread.CurrentBreakpoint.Kind == StepBreakpoint { + case dbp.currentThread.onTriggeredInternalBreakpoint(): + if dbp.currentThread.CurrentBreakpoint.Kind == StepBreakpoint { // See description of proc.(*Process).next for the meaning of StepBreakpoints if err := dbp.conditionErrors(); err != nil { return err } - pc, err := dbp.CurrentThread.PC() + pc, err := dbp.currentThread.PC() if err != nil { return err } - text, err := dbp.CurrentThread.Disassemble(pc, pc+maxInstructionLength, true) + text, err := dbp.currentThread.Disassemble(pc, pc+maxInstructionLength, true) if err != nil { return err } // here we either set a breakpoint into the destination of the CALL // instruction or we determined that the called function is hidden, // either way we need to resume execution - if err = dbp.setStepIntoBreakpoint(text, sameGoroutineCondition(dbp.SelectedGoroutine)); err != nil { + if err = dbp.setStepIntoBreakpoint(text, sameGoroutineCondition(dbp.selectedGoroutine)); err != nil { return err } } else { @@ -406,8 +430,8 @@ func (dbp *Process) Continue() error { } return dbp.conditionErrors() } - case dbp.CurrentThread.onTriggeredBreakpoint(): - onNextGoroutine, err := dbp.CurrentThread.onNextGoroutine() + case dbp.currentThread.onTriggeredBreakpoint(): + onNextGoroutine, err := dbp.currentThread.onNextGoroutine() if err != nil { return err } @@ -426,7 +450,7 @@ func (dbp *Process) Continue() error { func (dbp *Process) conditionErrors() error { var condErr error - for _, th := range dbp.Threads { + for _, th := range dbp.threads { if th.CurrentBreakpoint != nil && th.BreakpointConditionError != nil { if condErr == nil { condErr = th.BreakpointConditionError @@ -438,12 +462,12 @@ func (dbp *Process) conditionErrors() error { return condErr } -// pick a new dbp.CurrentThread, with the following priority: +// pick a new dbp.currentThread, with the following priority: // - a thread with onTriggeredInternalBreakpoint() == true // - a thread with onTriggeredBreakpoint() == true (prioritizing trapthread) // - trapthread func (dbp *Process) pickCurrentThread(trapthread *Thread) error { - for _, th := range dbp.Threads { + for _, th := range dbp.threads { if th.onTriggeredInternalBreakpoint() { return dbp.SwitchThread(th.ID) } @@ -451,7 +475,7 @@ func (dbp *Process) pickCurrentThread(trapthread *Thread) error { if trapthread.onTriggeredBreakpoint() { return dbp.SwitchThread(trapthread.ID) } - for _, th := range dbp.Threads { + for _, th := range dbp.threads { if th.onTriggeredBreakpoint() { return dbp.SwitchThread(th.ID) } @@ -465,8 +489,8 @@ func (dbp *Process) Step() (err error) { if dbp.exited { return &ProcessExitedError{} } - for i := range dbp.Breakpoints { - if dbp.Breakpoints[i].Internal() { + for i := range dbp.breakpoints { + if dbp.breakpoints[i].Internal() { return fmt.Errorf("next while nexting") } } @@ -506,12 +530,12 @@ func sameGoroutineCondition(g *G) ast.Expr { // asssociated with the selected goroutine. All other // threads will remain stopped. func (dbp *Process) StepInstruction() (err error) { - if dbp.SelectedGoroutine == nil { + if dbp.selectedGoroutine == nil { return errors.New("cannot single step: no selected goroutine") } - if dbp.SelectedGoroutine.thread == nil { + if dbp.selectedGoroutine.thread == nil { // Step called on parked goroutine - if _, err := dbp.SetBreakpoint(dbp.SelectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.SelectedGoroutine)); err != nil { + if _, err := dbp.SetBreakpoint(dbp.selectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.selectedGoroutine)); err != nil { return err } return dbp.Continue() @@ -520,20 +544,20 @@ func (dbp *Process) StepInstruction() (err error) { if dbp.exited { return &ProcessExitedError{} } - dbp.SelectedGoroutine.thread.clearBreakpointState() - err = dbp.SelectedGoroutine.thread.StepInstruction() + dbp.selectedGoroutine.thread.clearBreakpointState() + err = dbp.selectedGoroutine.thread.StepInstruction() if err != nil { return err } - return dbp.SelectedGoroutine.thread.SetCurrentBreakpoint() + return dbp.selectedGoroutine.thread.SetCurrentBreakpoint() } // StepOut will continue until the current goroutine exits the // function currently being executed or a deferred function is executed func (dbp *Process) StepOut() error { - cond := sameGoroutineCondition(dbp.SelectedGoroutine) + cond := sameGoroutineCondition(dbp.selectedGoroutine) - topframe, err := topframe(dbp.SelectedGoroutine, dbp.CurrentThread) + topframe, err := topframe(dbp.selectedGoroutine, dbp.currentThread) if err != nil { return err } @@ -542,8 +566,8 @@ func (dbp *Process) StepOut() error { var deferpc uint64 = 0 if filepath.Ext(topframe.Current.File) == ".go" { - if dbp.SelectedGoroutine != nil { - deferPCEntry := dbp.SelectedGoroutine.DeferPC() + if dbp.selectedGoroutine != nil { + deferPCEntry := dbp.selectedGoroutine.DeferPC() if deferPCEntry != 0 { _, _, deferfn := dbp.goSymTable.PCToLine(deferPCEntry) deferpc, err = dbp.FirstPCAfterPrologue(deferfn, false) @@ -589,9 +613,9 @@ func (dbp *Process) SwitchThread(tid int) error { if dbp.exited { return &ProcessExitedError{} } - if th, ok := dbp.Threads[tid]; ok { - dbp.CurrentThread = th - dbp.SelectedGoroutine, _ = dbp.CurrentThread.GetG() + if th, ok := dbp.threads[tid]; ok { + dbp.currentThread = th + dbp.selectedGoroutine, _ = dbp.currentThread.GetG() return nil } return fmt.Errorf("thread %d does not exist", tid) @@ -608,13 +632,13 @@ func (dbp *Process) SwitchGoroutine(gid int) error { return err } if g == nil { - // user specified -1 and SelectedGoroutine is nil + // user specified -1 and selectedGoroutine is nil return nil } if g.thread != nil { return dbp.SwitchThread(g.thread.ID) } - dbp.SelectedGoroutine = g + dbp.selectedGoroutine = g return nil } @@ -634,13 +658,13 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) { rdr = dbp.DwarfReader() ) - for i := range dbp.Threads { - if dbp.Threads[i].blocked() { + for i := range dbp.threads { + if dbp.threads[i].blocked() { continue } - g, _ := dbp.Threads[i].GetG() + g, _ := dbp.threads[i].GetG() if g != nil { - threadg[g.ID] = dbp.Threads[i] + threadg[g.ID] = dbp.threads[i] } } @@ -648,7 +672,7 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) { if err != nil { return nil, err } - allglenBytes, err := dbp.CurrentThread.readMemory(uintptr(addr), 8) + allglenBytes, err := dbp.currentThread.readMemory(uintptr(addr), 8) if err != nil { return nil, err } @@ -663,11 +687,11 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) { return nil, err } } - faddr, err := dbp.CurrentThread.readMemory(uintptr(allgentryaddr), dbp.arch.PtrSize()) + faddr, err := dbp.currentThread.readMemory(uintptr(allgentryaddr), dbp.arch.PtrSize()) allgptr := binary.LittleEndian.Uint64(faddr) for i := uint64(0); i < allglen; i++ { - gvar, err := dbp.CurrentThread.newGVariable(uintptr(allgptr+(i*uint64(dbp.arch.PtrSize()))), true) + gvar, err := dbp.currentThread.newGVariable(uintptr(allgptr+(i*uint64(dbp.arch.PtrSize()))), true) if err != nil { return nil, err } @@ -701,7 +725,7 @@ func (dbp *Process) Halt() (err error) { if dbp.exited { return &ProcessExitedError{} } - for _, th := range dbp.Threads { + for _, th := range dbp.threads { if err := th.Halt(); err != nil { return err } @@ -712,18 +736,18 @@ func (dbp *Process) Halt() (err error) { // Registers obtains register values from the // "current" thread of the traced process. func (dbp *Process) Registers() (Registers, error) { - return dbp.CurrentThread.Registers(false) + return dbp.currentThread.Registers(false) } // PC returns the PC of the current thread. func (dbp *Process) PC() (uint64, error) { - return dbp.CurrentThread.PC() + return dbp.currentThread.PC() } // CurrentBreakpoint returns the breakpoint the current thread // is stopped at. func (dbp *Process) CurrentBreakpoint() *Breakpoint { - return dbp.CurrentThread.CurrentBreakpoint + return dbp.currentThread.CurrentBreakpoint } // DwarfReader returns a reader for the dwarf data @@ -757,7 +781,7 @@ func (dbp *Process) PCToLine(pc uint64) (string, int, *gosym.Func) { // FindBreakpointByID finds the breakpoint for the given ID. func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) { - for _, bp := range dbp.Breakpoints { + for _, bp := range dbp.breakpoints { if bp.ID == id { return bp, true } @@ -768,11 +792,11 @@ func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) { // FindBreakpoint finds the breakpoint for the given pc. func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) { // Check to see if address is past the breakpoint, (i.e. breakpoint was hit). - if bp, ok := dbp.Breakpoints[pc-uint64(dbp.arch.BreakpointSize())]; ok { + if bp, ok := dbp.breakpoints[pc-uint64(dbp.arch.BreakpointSize())]; ok { return bp, true } // Directly use addr to lookup breakpoint. - if bp, ok := dbp.Breakpoints[pc]; ok { + if bp, ok := dbp.breakpoints[pc]; ok { return bp, true } return nil, false @@ -782,17 +806,17 @@ func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) { func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, error) { if attach { var err error - dbp.execPtraceFunc(func() { err = PtraceAttach(dbp.Pid) }) + dbp.execPtraceFunc(func() { err = PtraceAttach(dbp.pid) }) if err != nil { return nil, err } - _, _, err = dbp.wait(dbp.Pid, 0) + _, _, err = dbp.wait(dbp.pid, 0) if err != nil { return nil, err } } - proc, err := os.FindProcess(dbp.Pid) + proc, err := os.FindProcess(dbp.pid) if err != nil { return nil, err } @@ -813,11 +837,11 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e } dbp.arch.SetGStructOffset(ver, isextld) - // SelectedGoroutine can not be set correctly by the call to updateThreadList - // because without calling SetGStructOffset we can not read the G struct of CurrentThread + // selectedGoroutine can not be set correctly by the call to updateThreadList + // because without calling SetGStructOffset we can not read the G struct of currentThread // but without calling updateThreadList we can not examine memory to determine // the offset of g struct inside TLS - dbp.SelectedGoroutine, _ = dbp.CurrentThread.GetG() + dbp.selectedGoroutine, _ = dbp.currentThread.GetG() panicpc, err := dbp.FindFunctionLocation("runtime.startpanic", true, 0) if err == nil { @@ -833,7 +857,7 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e } func (dbp *Process) ClearInternalBreakpoints() error { - for _, bp := range dbp.Breakpoints { + for _, bp := range dbp.breakpoints { if !bp.Internal() { continue } @@ -841,9 +865,9 @@ func (dbp *Process) ClearInternalBreakpoints() error { return err } } - for i := range dbp.Threads { - if dbp.Threads[i].CurrentBreakpoint != nil && dbp.Threads[i].CurrentBreakpoint.Internal() { - dbp.Threads[i].CurrentBreakpoint = nil + for i := range dbp.threads { + if dbp.threads[i].CurrentBreakpoint != nil && dbp.threads[i].CurrentBreakpoint.Internal() { + dbp.threads[i].CurrentBreakpoint = nil } } return nil @@ -901,7 +925,7 @@ func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error) // specified by `gid`. func (dbp *Process) FindGoroutine(gid int) (*G, error) { if gid == -1 { - return dbp.SelectedGoroutine, nil + return dbp.selectedGoroutine, nil } gs, err := dbp.GoroutinesInfo() @@ -927,13 +951,13 @@ func (dbp *Process) ConvertEvalScope(gid, frame int) (*EvalScope, error) { return nil, err } if g == nil { - return dbp.CurrentThread.Scope() + return dbp.currentThread.Scope() } var out EvalScope if g.thread == nil { - out.Thread = dbp.CurrentThread + out.Thread = dbp.currentThread } else { out.Thread = g.thread } diff --git a/proc/proc_darwin.go b/proc/proc_darwin.go index 50b39685..0a49f145 100644 --- a/proc/proc_darwin.go +++ b/proc/proc_darwin.go @@ -77,7 +77,7 @@ func Launch(cmd []string, wd string) (*Process, error) { if pid <= 0 { return nil, fmt.Errorf("could not fork/exec") } - dbp.Pid = pid + dbp.pid = pid for i := range argvSlice { C.free(unsafe.Pointer(argvSlice[i])) } @@ -86,7 +86,7 @@ func Launch(cmd []string, wd string) (*Process, error) { // trapWait to wait until the child process calls execve. for { - err = dbp.updateThreadListForTask(C.get_task_for_pid(C.int(dbp.Pid))) + err = dbp.updateThreadListForTask(C.get_task_for_pid(C.int(dbp.pid))) if err == nil { break } @@ -100,7 +100,7 @@ func Launch(cmd []string, wd string) (*Process, error) { } dbp.allGCache = nil - for _, th := range dbp.Threads { + for _, th := range dbp.threads { th.clearBreakpointState() } @@ -152,11 +152,11 @@ func (dbp *Process) Kill() (err error) { if dbp.exited { return nil } - err = sys.Kill(-dbp.Pid, sys.SIGKILL) + err = sys.Kill(-dbp.pid, sys.SIGKILL) if err != nil { return errors.New("could not deliver signal: " + err.Error()) } - for port := range dbp.Threads { + for port := range dbp.threads { if C.thread_resume(C.thread_act_t(port)) != C.KERN_SUCCESS { return errors.New("could not resume task") } @@ -218,12 +218,12 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error { return couldNotGetThreadList } - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { thread.os.exists = false } for _, port := range list { - thread, ok := dbp.Threads[int(port)] + thread, ok := dbp.threads[int(port)] if !ok { thread, err = dbp.addThread(int(port), false) if err != nil { @@ -233,9 +233,9 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error { thread.os.exists = true } - for threadID, thread := range dbp.Threads { + for threadID, thread := range dbp.threads { if !thread.os.exists { - delete(dbp.Threads, threadID) + delete(dbp.threads, threadID) } } @@ -243,7 +243,7 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error { } func (dbp *Process) addThread(port int, attach bool) (*Thread, error) { - if thread, ok := dbp.Threads[port]; ok { + if thread, ok := dbp.threads[port]; ok { return thread, nil } thread := &Thread{ @@ -251,7 +251,7 @@ func (dbp *Process) addThread(port int, attach bool) (*Thread, error) { dbp: dbp, os: new(OSSpecificDetails), } - dbp.Threads[port] = thread + dbp.threads[port] = thread thread.os.threadAct = C.thread_act_t(port) if dbp.CurrentThread == nil { dbp.SwitchThread(thread.ID) @@ -338,7 +338,7 @@ var UnsupportedArchErr = errors.New("unsupported architecture - only darwin/amd6 func (dbp *Process) findExecutable(path string) (*macho.File, string, error) { if path == "" { - path = C.GoString(C.find_executable(C.int(dbp.Pid))) + path = C.GoString(C.find_executable(C.int(dbp.pid))) } exe, err := macho.Open(path) if err != nil { @@ -369,16 +369,16 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { continue } if !dbp.os.initialized { - if pidtask := C.get_task_for_pid(C.int(dbp.Pid)); pidtask != 0 && dbp.os.task != pidtask { + if pidtask := C.get_task_for_pid(C.int(dbp.pid)); pidtask != 0 && dbp.os.task != pidtask { continue } } - _, status, err := dbp.wait(dbp.Pid, 0) + _, status, err := dbp.wait(dbp.pid, 0) if err != nil { return nil, err } dbp.postExit() - return nil, ProcessExitedError{Pid: dbp.Pid, Status: status.ExitStatus()} + return nil, ProcessExitedError{Pid: dbp.pid, Status: status.ExitStatus()} case C.MACH_RCV_INTERRUPTED: if !dbp.halt { @@ -407,7 +407,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { // Since we cannot be notified of new threads on OS X // this is as good a time as any to check for them. dbp.updateThreadList() - th, ok := dbp.Threads[int(port)] + th, ok := dbp.threads[int(port)] if !ok { if dbp.halt { dbp.halt = false @@ -427,7 +427,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { } func (dbp *Process) waitForStop() ([]int, error) { - ports := make([]int, 0, len(dbp.Threads)) + ports := make([]int, 0, len(dbp.threads)) count := 0 for { var task C.task_t @@ -455,7 +455,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error { } trapthread.SetCurrentBreakpoint() for _, port := range ports { - if th, ok := dbp.Threads[port]; ok { + if th, ok := dbp.threads[port]; ok { err := th.SetCurrentBreakpoint() if err != nil { return err @@ -483,17 +483,17 @@ func (dbp *Process) exitGuard(err error) error { if err != ErrContinueThread { return err } - _, status, werr := dbp.wait(dbp.Pid, sys.WNOHANG) + _, status, werr := dbp.wait(dbp.pid, sys.WNOHANG) if werr == nil && status.Exited() { dbp.postExit() - return ProcessExitedError{Pid: dbp.Pid, Status: status.ExitStatus()} + return ProcessExitedError{Pid: dbp.pid, Status: status.ExitStatus()} } return err } func (dbp *Process) resume() error { // all threads stopped over a breakpoint are made to step over it - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { if thread.CurrentBreakpoint != nil { if err := thread.StepInstruction(); err != nil { return err @@ -502,7 +502,7 @@ func (dbp *Process) resume() error { } } // everything is resumed - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { if err := thread.resume(); err != nil { return dbp.exitGuard(err) } diff --git a/proc/proc_linux.go b/proc/proc_linux.go index 0a3d4fea..c21beb4b 100644 --- a/proc/proc_linux.go +++ b/proc/proc_linux.go @@ -70,7 +70,7 @@ func Launch(cmd []string, wd string) (*Process, error) { if err != nil { return nil, err } - dbp.Pid = proc.Process.Pid + dbp.pid = proc.Process.Pid _, _, err = dbp.wait(proc.Process.Pid, 0) if err != nil { return nil, fmt.Errorf("waiting for target execve failed: %s", err) @@ -88,13 +88,13 @@ func (dbp *Process) Kill() (err error) { if dbp.exited { return nil } - if !dbp.Threads[dbp.Pid].Stopped() { + if !dbp.threads[dbp.pid].Stopped() { return errors.New("process must be stopped in order to kill it") } - if err = sys.Kill(-dbp.Pid, sys.SIGKILL); err != nil { + if err = sys.Kill(-dbp.pid, sys.SIGKILL); err != nil { return errors.New("could not deliver signal " + err.Error()) } - if _, _, err = dbp.wait(dbp.Pid, 0); err != nil { + if _, _, err = dbp.wait(dbp.pid, 0); err != nil { return } dbp.postExit() @@ -102,13 +102,13 @@ func (dbp *Process) Kill() (err error) { } func (dbp *Process) requestManualStop() (err error) { - return sys.Kill(dbp.Pid, sys.SIGTRAP) + return sys.Kill(dbp.pid, sys.SIGTRAP) } // Attach to a newly created thread, and store that thread in our list of // known threads. func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) { - if thread, ok := dbp.Threads[tid]; ok { + if thread, ok := dbp.threads[tid]; ok { return thread, nil } @@ -145,26 +145,26 @@ func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) { } } - dbp.Threads[tid] = &Thread{ + dbp.threads[tid] = &Thread{ ID: tid, dbp: dbp, os: new(OSSpecificDetails), } - if dbp.CurrentThread == nil { + if dbp.currentThread == nil { dbp.SwitchThread(tid) } - return dbp.Threads[tid], nil + return dbp.threads[tid], nil } func (dbp *Process) updateThreadList() error { - tids, _ := filepath.Glob(fmt.Sprintf("/proc/%d/task/*", dbp.Pid)) + tids, _ := filepath.Glob(fmt.Sprintf("/proc/%d/task/*", dbp.pid)) for _, tidpath := range tids { tidstr := filepath.Base(tidpath) tid, err := strconv.Atoi(tidstr) if err != nil { return err } - if _, err := dbp.addThread(tid, tid != dbp.Pid); err != nil { + if _, err := dbp.addThread(tid, tid != dbp.pid); err != nil { return err } } @@ -175,7 +175,7 @@ var UnsupportedArchErr = errors.New("unsupported architecture - only linux/amd64 func (dbp *Process) findExecutable(path string) (*elf.File, string, error) { if path == "" { - path = fmt.Sprintf("/proc/%d/exe", dbp.Pid) + path = fmt.Sprintf("/proc/%d/exe", dbp.pid) } f, err := os.OpenFile(path, 0, os.ModePerm) if err != nil { @@ -279,16 +279,16 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { if wpid == 0 { continue } - th, ok := dbp.Threads[wpid] + th, ok := dbp.threads[wpid] if ok { th.Status = (*WaitStatus)(status) } if status.Exited() { - if wpid == dbp.Pid { + if wpid == dbp.pid { dbp.postExit() return nil, ProcessExitedError{Pid: wpid, Status: status.ExitStatus()} } - delete(dbp.Threads, wpid) + delete(dbp.threads, wpid) continue } if status.StopSignal() == sys.SIGTRAP && status.TrapCause() == sys.PTRACE_EVENT_CLONE { @@ -314,12 +314,12 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { if err = th.Continue(); err != nil { if err == sys.ESRCH { // thread died while we were adding it - delete(dbp.Threads, th.ID) + delete(dbp.threads, th.ID) continue } return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err) } - if err = dbp.Threads[int(wpid)].Continue(); err != nil { + if err = dbp.threads[int(wpid)].Continue(); err != nil { if err != sys.ESRCH { return nil, fmt.Errorf("could not continue existing thread %d %s", wpid, err) } @@ -343,7 +343,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { // TODO(dp) alert user about unexpected signals here. if err := th.resumeWithSig(int(status.StopSignal())); err != nil { if err == sys.ESRCH { - return nil, ProcessExitedError{Pid: dbp.Pid} + return nil, ProcessExitedError{Pid: dbp.pid} } return nil, err } @@ -354,19 +354,19 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { func (dbp *Process) loadProcessInformation(wg *sync.WaitGroup) { defer wg.Done() - comm, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/comm", dbp.Pid)) + comm, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/comm", dbp.pid)) if err == nil { // removes newline character comm = bytes.TrimSuffix(comm, []byte("\n")) } if comm == nil || len(comm) <= 0 { - stat, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", dbp.Pid)) + stat, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", dbp.pid)) if err != nil { fmt.Printf("Could not read proc stat: %v\n", err) os.Exit(1) } - expr := fmt.Sprintf("%d\\s*\\((.*)\\)", dbp.Pid) + expr := fmt.Sprintf("%d\\s*\\((.*)\\)", dbp.pid) rexp, err := regexp.Compile(expr) if err != nil { fmt.Printf("Regexp compile error: %v\n", err) @@ -374,7 +374,7 @@ func (dbp *Process) loadProcessInformation(wg *sync.WaitGroup) { } match := rexp.FindSubmatch(stat) if match == nil { - fmt.Printf("No match found using regexp '%s' in /proc/%d/stat\n", expr, dbp.Pid) + fmt.Printf("No match found using regexp '%s' in /proc/%d/stat\n", expr, dbp.pid) os.Exit(1) } comm = match[1] @@ -411,7 +411,7 @@ func (dbp *Process) waitFast(pid int) (int, *sys.WaitStatus, error) { func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) { var s sys.WaitStatus - if (pid != dbp.Pid) || (options != 0) { + if (pid != dbp.pid) || (options != 0) { wpid, err := sys.Wait4(pid, &s, sys.WALL|options, nil) return wpid, &s, err } @@ -442,7 +442,7 @@ func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) { } func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error { - for _, th := range dbp.Threads { + for _, th := range dbp.threads { if th.CurrentBreakpoint == nil { err := th.SetCurrentBreakpoint() if err != nil { @@ -457,7 +457,7 @@ func (dbp *Process) exitGuard(err error) error { if err != sys.ESRCH { return err } - if status(dbp.Pid, dbp.os.comm) == StatusZombie { + if status(dbp.pid, dbp.os.comm) == StatusZombie { _, err := dbp.trapWait(-1) return err } @@ -467,7 +467,7 @@ func (dbp *Process) exitGuard(err error) error { func (dbp *Process) resume() error { // all threads stopped over a breakpoint are made to step over it - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { if thread.CurrentBreakpoint != nil { if err := thread.StepInstruction(); err != nil { return err @@ -476,7 +476,7 @@ func (dbp *Process) resume() error { } } // everything is resumed - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { if err := thread.resume(); err != nil && err != sys.ESRCH { return err } diff --git a/proc/proc_test.go b/proc/proc_test.go index 0d4be1b4..ca8c32b3 100644 --- a/proc/proc_test.go +++ b/proc/proc_test.go @@ -108,7 +108,7 @@ func TestExit(t *testing.T) { if pe.Status != 0 { t.Errorf("Unexpected error status: %d", pe.Status) } - if pe.Pid != p.Pid { + if pe.Pid != p.pid { t.Errorf("Unexpected process id: %d", pe.Pid) } }) @@ -127,7 +127,7 @@ func TestExitAfterContinue(t *testing.T) { if pe.Status != 0 { t.Errorf("Unexpected error status: %d", pe.Status) } - if pe.Pid != p.Pid { + if pe.Pid != p.pid { t.Errorf("Unexpected process id: %d", pe.Pid) } }) @@ -159,7 +159,7 @@ func TestHalt(t *testing.T) { _, err := setFunctionBreakpoint(p, "main.loop") assertNoError(err, t, "SetBreakpoint") assertNoError(p.Continue(), t, "Continue") - for _, th := range p.Threads { + for _, th := range p.threads { if th.running != false { t.Fatal("expected running = false for thread", th.ID) } @@ -182,7 +182,7 @@ func TestHalt(t *testing.T) { // Loop through threads and make sure they are all // actually stopped, err will not be nil if the process // is still running. - for _, th := range p.Threads { + for _, th := range p.threads { if !th.Stopped() { t.Fatal("expected thread to be stopped, but was not") } @@ -207,7 +207,7 @@ func TestStep(t *testing.T) { regs := getRegisters(p, t) rip := regs.PC() - err = p.CurrentThread.StepInstruction() + err = p.currentThread.StepInstruction() assertNoError(err, t, "Step()") regs = getRegisters(p, t) @@ -289,7 +289,7 @@ func TestClearBreakpointBreakpoint(t *testing.T) { bp, err = p.ClearBreakpoint(fn.Entry) assertNoError(err, t, "ClearBreakpoint()") - data, err := dataAtAddr(p.CurrentThread, bp.Addr) + data, err := dataAtAddr(p.currentThread, bp.Addr) if err != nil { t.Fatal(err) } @@ -311,7 +311,7 @@ type nextTest struct { func countBreakpoints(p *Process) int { bpcount := 0 - for _, bp := range p.Breakpoints { + for _, bp := range p.breakpoints { if bp.ID >= 0 { bpcount++ } @@ -341,11 +341,11 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc assertNoError(err, t, "SetBreakpoint()") assertNoError(p.Continue(), t, "Continue()") p.ClearBreakpoint(bp.Addr) - p.CurrentThread.SetPC(bp.Addr) + p.currentThread.SetPC(bp.Addr) f, ln := currentLineNumber(p, t) for _, tc := range testcases { - pc, _ := p.CurrentThread.PC() + pc, _ := p.currentThread.PC() if ln != tc.begin { t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, filepath.Base(f), ln) } @@ -358,14 +358,14 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc } f, ln = currentLineNumber(p, t) - pc, _ = p.CurrentThread.PC() + pc, _ = p.currentThread.PC() if ln != tc.end { t.Fatalf("Program did not continue to correct next location expected %d was %s:%d (%#x)", tc.end, filepath.Base(f), ln, pc) } } if countBreakpoints(p) != 0 { - t.Fatal("Not all breakpoints were cleaned up", len(p.Breakpoints)) + t.Fatal("Not all breakpoints were cleaned up", len(p.breakpoints)) } }) } @@ -434,10 +434,10 @@ func TestNextConcurrent(t *testing.T) { _, err = p.ClearBreakpoint(bp.Addr) assertNoError(err, t, "ClearBreakpoint()") for _, tc := range testcases { - g, err := p.CurrentThread.GetG() + g, err := p.currentThread.GetG() assertNoError(err, t, "GetG()") - if p.SelectedGoroutine.ID != g.ID { - t.Fatalf("SelectedGoroutine not CurrentThread's goroutine: %d %d", g.ID, p.SelectedGoroutine.ID) + if p.selectedGoroutine.ID != g.ID { + t.Fatalf("SelectedGoroutine not CurrentThread's goroutine: %d %d", g.ID, p.selectedGoroutine.ID) } if ln != tc.begin { t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, filepath.Base(f), ln) @@ -473,10 +473,10 @@ func TestNextConcurrentVariant2(t *testing.T) { initVval, _ := constant.Int64Val(initV.Value) assertNoError(err, t, "EvalVariable") for _, tc := range testcases { - g, err := p.CurrentThread.GetG() + g, err := p.currentThread.GetG() assertNoError(err, t, "GetG()") - if p.SelectedGoroutine.ID != g.ID { - t.Fatalf("SelectedGoroutine not CurrentThread's goroutine: %d %d", g.ID, p.SelectedGoroutine.ID) + if p.selectedGoroutine.ID != g.ID { + t.Fatalf("SelectedGoroutine not CurrentThread's goroutine: %d %d", g.ID, p.selectedGoroutine.ID) } if ln != tc.begin { t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, filepath.Base(f), ln) @@ -487,7 +487,7 @@ func TestNextConcurrentVariant2(t *testing.T) { v, err := evalVariable(p, "n") assertNoError(err, t, "EvalVariable") vval, _ = constant.Int64Val(v.Value) - if p.CurrentThread.CurrentBreakpoint == nil { + if p.currentThread.CurrentBreakpoint == nil { if vval != initVval { t.Fatal("Did not end up on same goroutine") } @@ -599,7 +599,7 @@ func TestFindReturnAddress(t *testing.T) { if err != nil { t.Fatal(err) } - addr, err := p.CurrentThread.ReturnAddress() + addr, err := p.currentThread.ReturnAddress() if err != nil { t.Fatal(err) } @@ -623,7 +623,7 @@ func TestFindReturnAddressTopOfStackFn(t *testing.T) { if err := p.Continue(); err != nil { t.Fatal(err) } - if _, err := p.CurrentThread.ReturnAddress(); err == nil { + if _, err := p.currentThread.ReturnAddress(); err == nil { t.Fatal("expected error to be returned") } }) @@ -649,8 +649,8 @@ func TestSwitchThread(t *testing.T) { t.Fatal(err) } var nt int - ct := p.CurrentThread.ID - for tid := range p.Threads { + ct := p.currentThread.ID + for tid := range p.threads { if tid != ct { nt = tid break @@ -664,7 +664,7 @@ func TestSwitchThread(t *testing.T) { if err != nil { t.Fatal(err) } - if p.CurrentThread.ID != nt { + if p.currentThread.ID != nt { t.Fatal("Did not switch threads") } }) @@ -725,7 +725,7 @@ func TestStacktrace(t *testing.T) { for i := range stacks { assertNoError(p.Continue(), t, "Continue()") - locations, err := p.CurrentThread.Stacktrace(40) + locations, err := p.currentThread.Stacktrace(40) assertNoError(err, t, "Stacktrace()") if len(locations) != len(stacks[i])+2 { @@ -753,7 +753,7 @@ func TestStacktrace2(t *testing.T) { withTestProcess("retstack", t, func(p *Process, fixture protest.Fixture) { assertNoError(p.Continue(), t, "Continue()") - locations, err := p.CurrentThread.Stacktrace(40) + locations, err := p.currentThread.Stacktrace(40) assertNoError(err, t, "Stacktrace()") if !stackMatch([]loc{{-1, "main.f"}, {16, "main.main"}}, locations, false) { for i := range locations { @@ -763,7 +763,7 @@ func TestStacktrace2(t *testing.T) { } assertNoError(p.Continue(), t, "Continue()") - locations, err = p.CurrentThread.Stacktrace(40) + locations, err = p.currentThread.Stacktrace(40) assertNoError(err, t, "Stacktrace()") if !stackMatch([]loc{{-1, "main.g"}, {17, "main.main"}}, locations, false) { for i := range locations { @@ -863,9 +863,9 @@ func TestKill(t *testing.T) { t.Fatal("expected process to have exited") } if runtime.GOOS == "linux" { - _, err := os.Open(fmt.Sprintf("/proc/%d/", p.Pid)) + _, err := os.Open(fmt.Sprintf("/proc/%d/", p.pid)) if err == nil { - t.Fatal("process has not exited", p.Pid) + t.Fatal("process has not exited", p.pid) } } }) @@ -877,7 +877,7 @@ func testGSupportFunc(name string, t *testing.T, p *Process, fixture protest.Fix assertNoError(p.Continue(), t, name+": Continue()") - g, err := p.CurrentThread.GetG() + g, err := p.currentThread.GetG() assertNoError(err, t, name+": GetG()") if g == nil { @@ -1005,7 +1005,7 @@ func TestIssue239(t *testing.T) { } func evalVariable(p *Process, symbol string) (*Variable, error) { - scope, err := p.CurrentThread.Scope() + scope, err := p.currentThread.Scope() if err != nil { return nil, err } @@ -1013,7 +1013,7 @@ func evalVariable(p *Process, symbol string) (*Variable, error) { } func setVariable(p *Process, symbol, value string) error { - scope, err := p.CurrentThread.Scope() + scope, err := p.currentThread.Scope() if err != nil { return err } @@ -1152,7 +1152,7 @@ func TestFrameEvaluation(t *testing.T) { // Testing evaluation on frames assertNoError(p.Continue(), t, "Continue() 2") - g, err := p.CurrentThread.GetG() + g, err := p.currentThread.GetG() assertNoError(err, t, "GetG()") for i := 0; i <= 3; i++ { @@ -1185,7 +1185,7 @@ func TestPointerSetting(t *testing.T) { pval(1) // change p1 to point to i2 - scope, err := p.CurrentThread.Scope() + scope, err := p.currentThread.Scope() assertNoError(err, t, "Scope()") i2addr, err := scope.EvalExpression("i2", normalLoadConfig) assertNoError(err, t, "EvalExpression()") @@ -1320,7 +1320,7 @@ func TestBreakpointCountsWithDetection(t *testing.T) { } assertNoError(err, t, "Continue()") } - for _, th := range p.Threads { + for _, th := range p.threads { if th.CurrentBreakpoint == nil { continue } @@ -1454,7 +1454,7 @@ func TestIssue341(t *testing.T) { func BenchmarkLocalVariables(b *testing.B) { withTestProcess("testvariables", b, func(p *Process, fixture protest.Fixture) { assertNoError(p.Continue(), b, "Continue() returned an error") - scope, err := p.CurrentThread.Scope() + scope, err := p.currentThread.Scope() assertNoError(err, b, "Scope()") for i := 0; i < b.N; i++ { _, err := scope.LocalVariables(normalLoadConfig) @@ -1588,7 +1588,7 @@ func TestIssue332_Part1(t *testing.T) { assertNoError(err, t, "SetBreakpoint()") assertNoError(p.Continue(), t, "Continue()") assertNoError(p.Next(), t, "first Next()") - locations, err := p.CurrentThread.Stacktrace(2) + locations, err := p.currentThread.Stacktrace(2) assertNoError(err, t, "Stacktrace()") if locations[0].Call.Fn == nil { t.Fatalf("Not on a function") @@ -1617,7 +1617,7 @@ func TestIssue332_Part2(t *testing.T) { // step until we enter changeMe for { assertNoError(p.Step(), t, "Step()") - locations, err := p.CurrentThread.Stacktrace(2) + locations, err := p.currentThread.Stacktrace(2) assertNoError(err, t, "Stacktrace()") if locations[0].Call.Fn == nil { t.Fatalf("Not on a function") @@ -1627,7 +1627,7 @@ func TestIssue332_Part2(t *testing.T) { } } - pc, err := p.CurrentThread.PC() + pc, err := p.currentThread.PC() assertNoError(err, t, "PC()") pcAfterPrologue, err := p.FindFunctionLocation("main.changeMe", true, -1) assertNoError(err, t, "FindFunctionLocation()") @@ -1680,7 +1680,7 @@ func TestPackageVariables(t *testing.T) { withTestProcess("testvariables", t, func(p *Process, fixture protest.Fixture) { err := p.Continue() assertNoError(err, t, "Continue()") - scope, err := p.CurrentThread.Scope() + scope, err := p.currentThread.Scope() assertNoError(err, t, "Scope()") vars, err := scope.PackageVariables(normalLoadConfig) assertNoError(err, t, "PackageVariables()") @@ -1714,7 +1714,7 @@ func TestPanicBreakpoint(t *testing.T) { assertNoError(p.Continue(), t, "Continue()") bp := p.CurrentBreakpoint() if bp == nil || bp.Name != "unrecovered-panic" { - t.Fatalf("not on unrecovered-panic breakpoint: %v", p.CurrentBreakpoint) + t.Fatalf("not on unrecovered-panic breakpoint: %v", p.CurrentBreakpoint()) } }) } @@ -1724,7 +1724,7 @@ func TestCmdLineArgs(t *testing.T) { err := p.Continue() bp := p.CurrentBreakpoint() if bp != nil && bp.Name == "unrecovered-panic" { - t.Fatalf("testing args failed on unrecovered-panic breakpoint: %v", p.CurrentBreakpoint) + t.Fatalf("testing args failed on unrecovered-panic breakpoint: %v", p.CurrentBreakpoint()) } exit, exited := err.(ProcessExitedError) if !exited { @@ -1740,7 +1740,7 @@ func TestCmdLineArgs(t *testing.T) { p.Continue() bp := p.CurrentBreakpoint() if bp == nil || bp.Name != "unrecovered-panic" { - t.Fatalf("not on unrecovered-panic breakpoint: %v", p.CurrentBreakpoint) + t.Fatalf("not on unrecovered-panic breakpoint: %v", p.CurrentBreakpoint()) } } @@ -1783,7 +1783,7 @@ func TestIssue462(t *testing.T) { }() assertNoError(p.Continue(), t, "Continue()") - _, err := p.CurrentThread.Stacktrace(40) + _, err := p.currentThread.Stacktrace(40) assertNoError(err, t, "Stacktrace()") }) } @@ -1828,8 +1828,8 @@ func TestNextParked(t *testing.T) { p.ClearBreakpoint(bp.Addr) assertNoError(p.Next(), t, "Next()") - if p.SelectedGoroutine.ID != parkedg.ID { - t.Fatalf("Next did not continue on the selected goroutine, expected %d got %d", parkedg.ID, p.SelectedGoroutine.ID) + if p.selectedGoroutine.ID != parkedg.ID { + t.Fatalf("Next did not continue on the selected goroutine, expected %d got %d", parkedg.ID, p.selectedGoroutine.ID) } }) } @@ -1865,8 +1865,8 @@ func TestStepParked(t *testing.T) { p.ClearBreakpoint(bp.Addr) assertNoError(p.Step(), t, "Step()") - if p.SelectedGoroutine.ID != parkedg.ID { - t.Fatalf("Step did not continue on the selected goroutine, expected %d got %d", parkedg.ID, p.SelectedGoroutine.ID) + if p.selectedGoroutine.ID != parkedg.ID { + t.Fatalf("Step did not continue on the selected goroutine, expected %d got %d", parkedg.ID, p.selectedGoroutine.ID) } }) } @@ -2093,7 +2093,7 @@ func TestStepConcurrentDirect(t *testing.T) { _, err = p.ClearBreakpoint(bp.Addr) assertNoError(err, t, "ClearBreakpoint()") - gid := p.SelectedGoroutine.ID + gid := p.selectedGoroutine.ID seq := []int{37, 38, 13, 15, 16, 38} @@ -2108,8 +2108,8 @@ func TestStepConcurrentDirect(t *testing.T) { } t.Fatalf("Program did not continue at expected location (%d) %s:%d", seq[i], f, ln) } - if p.SelectedGoroutine.ID != gid { - t.Fatalf("Step switched to different goroutine %d %d\n", gid, p.SelectedGoroutine.ID) + if p.selectedGoroutine.ID != gid { + t.Fatalf("Step switched to different goroutine %d %d\n", gid, p.selectedGoroutine.ID) } i = (i + 1) % len(seq) if i == 0 { @@ -2125,7 +2125,7 @@ func TestStepConcurrentDirect(t *testing.T) { } func nextInProgress(p *Process) bool { - for _, bp := range p.Breakpoints { + for _, bp := range p.breakpoints { if bp.Internal() { return true } @@ -2155,7 +2155,7 @@ func TestStepConcurrentPtr(t *testing.T) { t.Fatalf("Program did not continue at expected location (24): %s:%d", f, ln) } - gid := p.SelectedGoroutine.ID + gid := p.selectedGoroutine.ID kvar, err := evalVariable(p, "k") assertNoError(err, t, "EvalVariable()") @@ -2170,14 +2170,14 @@ func TestStepConcurrentPtr(t *testing.T) { assertNoError(p.Step(), t, "Step()") for nextInProgress(p) { - if p.SelectedGoroutine.ID == gid { - t.Fatalf("step did not step into function call (but internal breakpoints still active?) (%d %d)", gid, p.SelectedGoroutine.ID) + if p.selectedGoroutine.ID == gid { + t.Fatalf("step did not step into function call (but internal breakpoints still active?) (%d %d)", gid, p.selectedGoroutine.ID) } assertNoError(p.Continue(), t, "Continue()") } - if p.SelectedGoroutine.ID != gid { - t.Fatalf("Step switched goroutines (wanted: %d got: %d)", gid, p.SelectedGoroutine.ID) + if p.selectedGoroutine.ID != gid { + t.Fatalf("Step switched goroutines (wanted: %d got: %d)", gid, p.selectedGoroutine.ID) } f, ln = currentLineNumber(p, t) @@ -2256,9 +2256,9 @@ func TestStepOnCallPtrInstr(t *testing.T) { if ln != 10 { break } - pc, err := p.CurrentThread.PC() + pc, err := p.currentThread.PC() assertNoError(err, t, "PC()") - text, err := p.CurrentThread.Disassemble(pc, pc+maxInstructionLength, true) + text, err := p.currentThread.Disassemble(pc, pc+maxInstructionLength, true) assertNoError(err, t, "Disassemble()") if text[0].IsCall() { found = true @@ -2394,7 +2394,7 @@ func BenchmarkTrace(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { assertNoError(p.Continue(), b, "Continue()") - s, err := p.CurrentThread.Scope() + s, err := p.currentThread.Scope() assertNoError(err, b, "Scope()") _, err = s.FunctionArguments(LoadConfig{false, 0, 64, 0, 3}) assertNoError(err, b, "FunctionArguments()") diff --git a/proc/proc_unix_test.go b/proc/proc_unix_test.go index 6c4f395d..b8769d75 100644 --- a/proc/proc_unix_test.go +++ b/proc/proc_unix_test.go @@ -17,7 +17,7 @@ func TestIssue419(t *testing.T) { for { if p.Running() { time.Sleep(2 * time.Second) - err := syscall.Kill(p.Pid, syscall.SIGINT) + err := syscall.Kill(p.pid, syscall.SIGINT) assertNoError(err, t, "syscall.Kill") return } diff --git a/proc/proc_windows.go b/proc/proc_windows.go index aa5518e8..7d21cf42 100644 --- a/proc/proc_windows.go +++ b/proc/proc_windows.go @@ -113,7 +113,7 @@ func Launch(cmd []string, wd string) (*Process, error) { sys.CloseHandle(sys.Handle(pi.Process)) sys.CloseHandle(sys.Handle(pi.Thread)) - dbp.Pid = int(pi.ProcessId) + dbp.pid = int(pi.ProcessId) return newDebugProcess(dbp, argv0Go) } @@ -135,11 +135,11 @@ func newDebugProcess(dbp *Process, exepath string) (*Process, error) { } if tid == 0 { dbp.postExit() - return nil, ProcessExitedError{Pid: dbp.Pid, Status: exitCode} + return nil, ProcessExitedError{Pid: dbp.pid, Status: exitCode} } // Suspend all threads so that the call to _ContinueDebugEvent will // not resume the target. - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { _, err := _SuspendThread(thread.os.hThread) if err != nil { return nil, err @@ -147,7 +147,7 @@ func newDebugProcess(dbp *Process, exepath string) (*Process, error) { } dbp.execPtraceFunc(func() { - err = _ContinueDebugEvent(uint32(dbp.Pid), uint32(dbp.os.breakThread), _DBG_CONTINUE) + err = _ContinueDebugEvent(uint32(dbp.pid), uint32(dbp.os.breakThread), _DBG_CONTINUE) }) if err != nil { return nil, err @@ -209,7 +209,7 @@ func (dbp *Process) Kill() error { if dbp.exited { return nil } - if !dbp.Threads[dbp.Pid].Stopped() { + if !dbp.threads[dbp.pid].Stopped() { return errors.New("process must be stopped in order to kill it") } // TODO: Should not have to ignore failures here, @@ -231,7 +231,7 @@ func (dbp *Process) updateThreadList() error { } func (dbp *Process) addThread(hThread syscall.Handle, threadID int, attach, suspendNewThreads bool) (*Thread, error) { - if thread, ok := dbp.Threads[threadID]; ok { + if thread, ok := dbp.threads[threadID]; ok { return thread, nil } thread := &Thread{ @@ -240,7 +240,7 @@ func (dbp *Process) addThread(hThread syscall.Handle, threadID int, attach, susp os: new(OSSpecificDetails), } thread.os.hThread = hThread - dbp.Threads[threadID] = thread + dbp.threads[threadID] = thread if dbp.CurrentThread == nil { dbp.SwitchThread(thread.ID) } @@ -488,7 +488,7 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e } break case _EXIT_THREAD_DEBUG_EVENT: - delete(dbp.Threads, int(debugEvent.ThreadId)) + delete(dbp.threads, int(debugEvent.ThreadId)) break case _OUTPUT_DEBUG_STRING_EVENT: //TODO: Handle debug output strings @@ -547,9 +547,9 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { } if tid == 0 { dbp.postExit() - return nil, ProcessExitedError{Pid: dbp.Pid, Status: exitCode} + return nil, ProcessExitedError{Pid: dbp.pid, Status: exitCode} } - th := dbp.Threads[tid] + th := dbp.threads[tid] return th, nil } @@ -577,7 +577,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error { return err } - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { thread.running = false _, err := _SuspendThread(thread.os.hThread) if err != nil { @@ -589,7 +589,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error { var err error var tid int dbp.execPtraceFunc(func() { - err = _ContinueDebugEvent(uint32(dbp.Pid), uint32(dbp.os.breakThread), _DBG_CONTINUE) + err = _ContinueDebugEvent(uint32(dbp.pid), uint32(dbp.os.breakThread), _DBG_CONTINUE) if err == nil { tid, _, _ = dbp.waitForDebugEvent(waitSuspendNewThreads) } @@ -600,7 +600,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error { if tid == 0 { break } - err = dbp.Threads[tid].SetCurrentBreakpoint() + err = dbp.threads[tid].SetCurrentBreakpoint() if err != nil { return err } @@ -614,7 +614,7 @@ func (dbp *Process) exitGuard(err error) error { } func (dbp *Process) resume() error { - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { if thread.CurrentBreakpoint != nil { if err := thread.StepInstruction(); err != nil { return err @@ -623,7 +623,7 @@ func (dbp *Process) resume() error { } } - for _, thread := range dbp.Threads { + for _, thread := range dbp.threads { thread.running = true _, err := _ResumeThread(thread.os.hThread) if err != nil { diff --git a/proc/stack.go b/proc/stack.go index 31a75a12..70556d97 100644 --- a/proc/stack.go +++ b/proc/stack.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "errors" "fmt" + "github.com/derekparker/delve/dwarf/frame" ) @@ -222,7 +223,7 @@ func (dbp *Process) frameInfo(pc, sp uint64, top bool) (Stackframe, error) { if retaddr == 0 { return Stackframe{}, NullAddrError{} } - data, err := dbp.CurrentThread.readMemory(retaddr, dbp.arch.PtrSize()) + data, err := dbp.currentThread.readMemory(retaddr, dbp.arch.PtrSize()) if err != nil { return Stackframe{}, err } diff --git a/proc/threads.go b/proc/threads.go index 33623e76..4e44efea 100644 --- a/proc/threads.go +++ b/proc/threads.go @@ -154,7 +154,7 @@ func topframe(g *G, thread *Thread) (Stackframe, error) { // Continue will take care of setting a breakpoint to the destination // once the CALL is reached. func (dbp *Process) next(stepInto bool) error { - topframe, err := topframe(dbp.SelectedGoroutine, dbp.CurrentThread) + topframe, err := topframe(dbp.selectedGoroutine, dbp.currentThread) if err != nil { return err } @@ -167,10 +167,10 @@ func (dbp *Process) next(stepInto bool) error { }() csource := filepath.Ext(topframe.Current.File) != ".go" - thread := dbp.CurrentThread + thread := dbp.currentThread currentGoroutine := false - if dbp.SelectedGoroutine != nil && dbp.SelectedGoroutine.thread != nil { - thread = dbp.SelectedGoroutine.thread + if dbp.selectedGoroutine != nil && dbp.selectedGoroutine.thread != nil { + thread = dbp.selectedGoroutine.thread currentGoroutine = true } @@ -179,7 +179,7 @@ func (dbp *Process) next(stepInto bool) error { return err } - cond := sameGoroutineCondition(dbp.SelectedGoroutine) + cond := sameGoroutineCondition(dbp.selectedGoroutine) if stepInto { for _, instr := range text { @@ -215,8 +215,8 @@ func (dbp *Process) next(stepInto bool) error { // Set breakpoint on the most recently deferred function (if any) var deferpc uint64 = 0 - if dbp.SelectedGoroutine != nil { - deferPCEntry := dbp.SelectedGoroutine.DeferPC() + if dbp.selectedGoroutine != nil { + deferPCEntry := dbp.selectedGoroutine.DeferPC() if deferPCEntry != 0 { _, _, deferfn := dbp.goSymTable.PCToLine(deferPCEntry) var err error @@ -256,7 +256,7 @@ func (dbp *Process) next(stepInto bool) error { if !covered { fn := dbp.goSymTable.PCToFunc(topframe.Ret) - if dbp.SelectedGoroutine != nil && fn != nil && fn.Name == "runtime.goexit" { + if dbp.selectedGoroutine != nil && fn != nil && fn.Name == "runtime.goexit" { return nil } } @@ -342,7 +342,7 @@ func (thread *Thread) getGVariable() (*Variable, error) { if thread.dbp.arch.GStructOffset() == 0 { // GetG was called through SwitchThread / updateThreadList during initialization - // thread.dbp.arch isn't setup yet (it needs a CurrentThread to read global variables from) + // thread.dbp.arch isn't setup yet (it needs a current thread to read global variables from) return nil, fmt.Errorf("g struct offset not initialized") } @@ -490,9 +490,9 @@ func (thread *Thread) onRuntimeBreakpoint() bool { // onNextGorutine returns true if this thread is on the goroutine requested by the current 'next' command func (thread *Thread) onNextGoroutine() (bool, error) { var bp *Breakpoint - for i := range thread.dbp.Breakpoints { - if thread.dbp.Breakpoints[i].Internal() { - bp = thread.dbp.Breakpoints[i] + for i := range thread.dbp.breakpoints { + if thread.dbp.breakpoints[i].Internal() { + bp = thread.dbp.breakpoints[i] break } } diff --git a/proc/threads_linux.go b/proc/threads_linux.go index 560af901..8592a2c5 100644 --- a/proc/threads_linux.go +++ b/proc/threads_linux.go @@ -15,7 +15,7 @@ type OSSpecificDetails struct { } func (t *Thread) halt() (err error) { - err = sys.Tgkill(t.dbp.Pid, t.ID, sys.SIGSTOP) + err = sys.Tgkill(t.dbp.pid, t.ID, sys.SIGSTOP) if err != nil { err = fmt.Errorf("halt err %s on thread %d", err, t.ID) return @@ -53,13 +53,13 @@ func (t *Thread) singleStep() (err error) { if err != nil { return err } - if (status == nil || status.Exited()) && wpid == t.dbp.Pid { + if (status == nil || status.Exited()) && wpid == t.dbp.pid { t.dbp.postExit() rs := 0 if status != nil { rs = status.ExitStatus() } - return ProcessExitedError{Pid: t.dbp.Pid, Status: rs} + return ProcessExitedError{Pid: t.dbp.pid, Status: rs} } if wpid == t.ID && status.StopSignal() == sys.SIGTRAP { return nil diff --git a/proc/threads_windows.go b/proc/threads_windows.go index e0452e79..536a4114 100644 --- a/proc/threads_windows.go +++ b/proc/threads_windows.go @@ -57,7 +57,7 @@ func (t *Thread) singleStep() error { } if tid == 0 { t.dbp.postExit() - return ProcessExitedError{Pid: t.dbp.Pid, Status: exitCode} + return ProcessExitedError{Pid: t.dbp.pid, Status: exitCode} } if t.dbp.os.breakThread == t.ID { @@ -65,7 +65,7 @@ func (t *Thread) singleStep() error { } t.dbp.execPtraceFunc(func() { - err = _ContinueDebugEvent(uint32(t.dbp.Pid), uint32(t.dbp.os.breakThread), _DBG_CONTINUE) + err = _ContinueDebugEvent(uint32(t.dbp.pid), uint32(t.dbp.os.breakThread), _DBG_CONTINUE) }) } @@ -75,7 +75,7 @@ func (t *Thread) singleStep() error { } t.dbp.execPtraceFunc(func() { - err = _ContinueDebugEvent(uint32(t.dbp.Pid), uint32(t.ID), _DBG_CONTINUE) + err = _ContinueDebugEvent(uint32(t.dbp.pid), uint32(t.ID), _DBG_CONTINUE) }) if err != nil { return err @@ -98,7 +98,7 @@ func (t *Thread) resume() error { t.dbp.execPtraceFunc(func() { //TODO: Note that we are ignoring the thread we were asked to continue and are continuing the //thread that we last broke on. - err = _ContinueDebugEvent(uint32(t.dbp.Pid), uint32(t.ID), _DBG_CONTINUE) + err = _ContinueDebugEvent(uint32(t.dbp.pid), uint32(t.ID), _DBG_CONTINUE) }) return err } diff --git a/proc/variables.go b/proc/variables.go index a1bed95d..7bd7b19a 100644 --- a/proc/variables.go +++ b/proc/variables.go @@ -649,7 +649,7 @@ func (scope *EvalScope) PackageVariables(cfg LoadConfig) ([]*Variable, error) { // EvalPackageVariable will evaluate the package level variable // specified by 'name'. func (dbp *Process) EvalPackageVariable(name string, cfg LoadConfig) (*Variable, error) { - scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0} + scope := &EvalScope{Thread: dbp.currentThread, PC: 0, CFA: 0} v, err := scope.packageVarAddr(name) if err != nil { diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index 41fa767b..cb4825ca 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -13,6 +13,7 @@ import ( "sync" "time" + "github.com/derekparker/delve/pkg/target" "github.com/derekparker/delve/proc" "github.com/derekparker/delve/service/api" ) @@ -26,9 +27,10 @@ import ( // functionality needed by clients, but not needed in // lower lever packages such as proc. type Debugger struct { - config *Config + config *Config + // TODO(DO NOT MERGE WITHOUT) rename to targetMutex processMutex sync.Mutex - process *proc.Process + target target.Interface } // Config provides the configuration to start a Debugger. @@ -61,7 +63,7 @@ func New(config *Config) (*Debugger, error) { if err != nil { return nil, attachErrorMessage(d.config.AttachPid, err) } - d.process = p + d.target = p } else { log.Printf("launching process with args: %v", d.config.ProcessArgs) p, err := proc.Launch(d.config.ProcessArgs, d.config.WorkingDir) @@ -71,7 +73,7 @@ func New(config *Config) (*Debugger, error) { } return nil, err } - d.process = p + d.target = p } return d, nil } @@ -79,13 +81,13 @@ func New(config *Config) (*Debugger, error) { // ProcessPid returns the PID of the process // the debugger is debugging. func (d *Debugger) ProcessPid() int { - return d.process.Pid + return d.target.Pid() } // LastModified returns the time that the process' executable was last // modified. func (d *Debugger) LastModified() time.Time { - return d.process.LastModified + return d.target.LastModified() } // Detach detaches from the target process. @@ -100,9 +102,9 @@ func (d *Debugger) Detach(kill bool) error { func (d *Debugger) detach(kill bool) error { if d.config.AttachPid != 0 { - return d.process.Detach(kill) + return d.target.Detach(kill) } - return d.process.Kill() + return d.target.Kill() } // Restart will restart the target process, first killing @@ -111,9 +113,9 @@ func (d *Debugger) Restart() ([]api.DiscardedBreakpoint, error) { d.processMutex.Lock() defer d.processMutex.Unlock() - if !d.process.Exited() { - if d.process.Running() { - d.process.Halt() + if !d.target.Exited() { + if d.target.Running() { + d.target.Halt() } // Ensure the process is in a PTRACE_STOP. if err := stopProcess(d.ProcessPid()); err != nil { @@ -147,7 +149,7 @@ func (d *Debugger) Restart() ([]api.DiscardedBreakpoint, error) { return nil, err } } - d.process = p + d.target = p return discarded, nil } @@ -159,7 +161,7 @@ func (d *Debugger) State() (*api.DebuggerState, error) { } func (d *Debugger) state() (*api.DebuggerState, error) { - if d.process.Exited() { + if d.target.Exited() { return nil, proc.ProcessExitedError{Pid: d.ProcessPid()} } @@ -168,24 +170,24 @@ func (d *Debugger) state() (*api.DebuggerState, error) { goroutine *api.Goroutine ) - if d.process.SelectedGoroutine != nil { - goroutine = api.ConvertGoroutine(d.process.SelectedGoroutine) + if d.target.SelectedGoroutine() != nil { + goroutine = api.ConvertGoroutine(d.target.SelectedGoroutine()) } state = &api.DebuggerState{ SelectedGoroutine: goroutine, - Exited: d.process.Exited(), + Exited: d.target.Exited(), } - for i := range d.process.Threads { - th := api.ConvertThread(d.process.Threads[i]) + for i := range d.target.Threads() { + th := api.ConvertThread(d.target.Threads()[i]) state.Threads = append(state.Threads, th) - if i == d.process.CurrentThread.ID { + if i == d.target.CurrentThread().ID { state.CurrentThread = th } } - for _, bp := range d.process.Breakpoints { + for _, bp := range d.target.Breakpoints() { if bp.Internal() { state.NextInProgress = true break @@ -221,19 +223,19 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin if runtime.GOOS == "windows" { // Accept fileName which is case-insensitive and slash-insensitive match fileNameNormalized := strings.ToLower(filepath.ToSlash(fileName)) - for symFile := range d.process.Sources() { + for symFile := range d.target.Sources() { if fileNameNormalized == strings.ToLower(filepath.ToSlash(symFile)) { fileName = symFile break } } } - addr, err = d.process.FindFileLocation(fileName, requestedBp.Line) + addr, err = d.target.FindFileLocation(fileName, requestedBp.Line) case len(requestedBp.FunctionName) > 0: if requestedBp.Line >= 0 { - addr, err = d.process.FindFunctionLocation(requestedBp.FunctionName, false, requestedBp.Line) + addr, err = d.target.FindFunctionLocation(requestedBp.FunctionName, false, requestedBp.Line) } else { - addr, err = d.process.FindFunctionLocation(requestedBp.FunctionName, true, 0) + addr, err = d.target.FindFunctionLocation(requestedBp.FunctionName, true, 0) } default: addr = requestedBp.Addr @@ -243,12 +245,12 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin return nil, err } - bp, err := d.process.SetBreakpoint(addr, proc.UserBreakpoint, nil) + bp, err := d.target.SetBreakpoint(addr, proc.UserBreakpoint, nil) if err != nil { return nil, err } if err := copyBreakpointInfo(bp, requestedBp); err != nil { - if _, err1 := d.process.ClearBreakpoint(bp.Addr); err1 != nil { + if _, err1 := d.target.ClearBreakpoint(bp.Addr); err1 != nil { err = fmt.Errorf("error while creating breakpoint: %v, additionally the breakpoint could not be properly rolled back: %v", err, err1) } return nil, err @@ -273,7 +275,7 @@ func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error { } func (d *Debugger) CancelNext() error { - return d.process.ClearInternalBreakpoints() + return d.target.ClearInternalBreakpoints() } func copyBreakpointInfo(bp *proc.Breakpoint, requested *api.Breakpoint) (err error) { @@ -297,7 +299,7 @@ func (d *Debugger) ClearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint defer d.processMutex.Unlock() var clearedBp *api.Breakpoint - bp, err := d.process.ClearBreakpoint(requestedBp.Addr) + bp, err := d.target.ClearBreakpoint(requestedBp.Addr) if err != nil { return nil, fmt.Errorf("Can't clear breakpoint @%x: %s", requestedBp.Addr, err) } @@ -315,7 +317,7 @@ func (d *Debugger) Breakpoints() []*api.Breakpoint { func (d *Debugger) breakpoints() []*api.Breakpoint { bps := []*api.Breakpoint{} - for _, bp := range d.process.Breakpoints { + for _, bp := range d.target.Breakpoints() { if bp.Internal() { continue } @@ -337,7 +339,7 @@ func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint { } func (d *Debugger) findBreakpoint(id int) *proc.Breakpoint { - for _, bp := range d.process.Breakpoints { + for _, bp := range d.target.Breakpoints() { if bp.ID == id { return bp } @@ -366,11 +368,11 @@ func (d *Debugger) Threads() ([]*api.Thread, error) { d.processMutex.Lock() defer d.processMutex.Unlock() - if d.process.Exited() { + if d.target.Exited() { return nil, &proc.ProcessExitedError{} } threads := []*api.Thread{} - for _, th := range d.process.Threads { + for _, th := range d.target.Threads() { threads = append(threads, api.ConvertThread(th)) } return threads, nil @@ -381,11 +383,11 @@ func (d *Debugger) FindThread(id int) (*api.Thread, error) { d.processMutex.Lock() defer d.processMutex.Unlock() - if d.process.Exited() { + if d.target.Exited() { return nil, &proc.ProcessExitedError{} } - for _, th := range d.process.Threads { + for _, th := range d.target.Threads() { if th.ID == id { return api.ConvertThread(th), nil } @@ -401,7 +403,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er // RequestManualStop does not invoke any ptrace syscalls, so it's safe to // access the process directly. log.Print("halting") - err = d.process.RequestManualStop() + err = d.target.RequestManualStop() } d.processMutex.Lock() @@ -410,7 +412,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er switch command.Name { case api.Continue: log.Print("continuing") - err = d.process.Continue() + err = d.target.Continue() if err != nil { if exitedErr, exited := err.(proc.ProcessExitedError); exited { state := &api.DebuggerState{} @@ -430,22 +432,22 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er case api.Next: log.Print("nexting") - err = d.process.Next() + err = d.target.Next() case api.Step: log.Print("stepping") - err = d.process.Step() + err = d.target.Step() case api.StepInstruction: log.Print("single stepping") - err = d.process.StepInstruction() + err = d.target.StepInstruction() case api.StepOut: log.Print("step out") - err = d.process.StepOut() + err = d.target.StepOut() case api.SwitchThread: log.Printf("switching to thread %d", command.ThreadID) - err = d.process.SwitchThread(command.ThreadID) + err = d.target.SwitchThread(command.ThreadID) case api.SwitchGoroutine: log.Printf("switching to goroutine %d", command.GoroutineID) - err = d.process.SwitchGoroutine(command.GoroutineID) + err = d.target.SwitchGoroutine(command.GoroutineID) case api.Halt: // RequestManualStop already called } @@ -470,7 +472,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error state.Threads[i].BreakpointInfo = bpi if bp.Goroutine { - g, err := d.process.CurrentThread.GetG() + g, err := d.target.CurrentThread().GetG() if err != nil { return err } @@ -478,7 +480,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error } if bp.Stacktrace > 0 { - rawlocs, err := d.process.CurrentThread.Stacktrace(bp.Stacktrace) + rawlocs, err := d.target.CurrentThread().Stacktrace(bp.Stacktrace) if err != nil { return err } @@ -488,7 +490,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error } } - s, err := d.process.Threads[state.Threads[i].ID].Scope() + s, err := d.target.Threads()[state.Threads[i].ID].Scope() if err != nil { return err } @@ -529,7 +531,7 @@ func (d *Debugger) Sources(filter string) ([]string, error) { } files := []string{} - for f := range d.process.Sources() { + for f := range d.target.Sources() { if regex.Match([]byte(f)) { files = append(files, f) } @@ -542,7 +544,7 @@ func (d *Debugger) Functions(filter string) ([]string, error) { d.processMutex.Lock() defer d.processMutex.Unlock() - return regexFilterFuncs(filter, d.process.Funcs()) + return regexFilterFuncs(filter, d.target.Funcs()) } func (d *Debugger) Types(filter string) ([]string, error) { @@ -554,7 +556,7 @@ func (d *Debugger) Types(filter string) ([]string, error) { return nil, fmt.Errorf("invalid filter argument: %s", err.Error()) } - types, err := d.process.Types() + types, err := d.target.Types() if err != nil { return nil, err } @@ -596,7 +598,7 @@ func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadCo } vars := []api.Variable{} - thread, found := d.process.Threads[threadID] + thread, found := d.target.Threads()[threadID] if !found { return nil, fmt.Errorf("couldn't find thread %d", threadID) } @@ -621,7 +623,7 @@ func (d *Debugger) Registers(threadID int, floatingPoint bool) (api.Registers, e d.processMutex.Lock() defer d.processMutex.Unlock() - thread, found := d.process.Threads[threadID] + thread, found := d.target.Threads()[threadID] if !found { return nil, fmt.Errorf("couldn't find thread %d", threadID) } @@ -645,7 +647,7 @@ func (d *Debugger) LocalVariables(scope api.EvalScope, cfg proc.LoadConfig) ([]a d.processMutex.Lock() defer d.processMutex.Unlock() - s, err := d.process.ConvertEvalScope(scope.GoroutineID, scope.Frame) + s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) if err != nil { return nil, err } @@ -661,7 +663,7 @@ func (d *Debugger) FunctionArguments(scope api.EvalScope, cfg proc.LoadConfig) ( d.processMutex.Lock() defer d.processMutex.Unlock() - s, err := d.process.ConvertEvalScope(scope.GoroutineID, scope.Frame) + s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) if err != nil { return nil, err } @@ -678,7 +680,7 @@ func (d *Debugger) EvalVariableInScope(scope api.EvalScope, symbol string, cfg p d.processMutex.Lock() defer d.processMutex.Unlock() - s, err := d.process.ConvertEvalScope(scope.GoroutineID, scope.Frame) + s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) if err != nil { return nil, err } @@ -695,7 +697,7 @@ func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string) d.processMutex.Lock() defer d.processMutex.Unlock() - s, err := d.process.ConvertEvalScope(scope.GoroutineID, scope.Frame) + s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) if err != nil { return err } @@ -708,7 +710,7 @@ func (d *Debugger) Goroutines() ([]*api.Goroutine, error) { defer d.processMutex.Unlock() goroutines := []*api.Goroutine{} - gs, err := d.process.GoroutinesInfo() + gs, err := d.target.GoroutinesInfo() if err != nil { return nil, err } @@ -727,13 +729,13 @@ func (d *Debugger) Stacktrace(goroutineID, depth int, cfg *proc.LoadConfig) ([]a var rawlocs []proc.Stackframe - g, err := d.process.FindGoroutine(goroutineID) + g, err := d.target.FindGoroutine(goroutineID) if err != nil { return nil, err } if g == nil { - rawlocs, err = d.process.CurrentThread.Stacktrace(depth) + rawlocs, err = d.target.CurrentThread().Stacktrace(depth) } else { rawlocs, err = g.Stacktrace(depth) } @@ -750,7 +752,7 @@ func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadCo frame := api.Stackframe{Location: api.ConvertLocation(rawlocs[i].Call)} if cfg != nil { var err error - scope := rawlocs[i].Scope(d.process.CurrentThread) + scope := rawlocs[i].Scope(d.target.CurrentThread()) locals, err := scope.LocalVariables(*cfg) if err != nil { return nil, err @@ -779,11 +781,11 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat return nil, err } - s, _ := d.process.ConvertEvalScope(scope.GoroutineID, scope.Frame) + s, _ := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame) locs, err := loc.Find(d, s, locStr) for i := range locs { - file, line, fn := d.process.PCToLine(locs[i].PC) + file, line, fn := d.target.PCToLine(locs[i].PC) locs[i].File = file locs[i].Line = line locs[i].Function = api.ConvertFunction(fn) @@ -798,7 +800,7 @@ func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavo defer d.processMutex.Unlock() if endPC == 0 { - _, _, fn := d.process.PCToLine(startPC) + _, _, fn := d.target.PCToLine(startPC) if fn == nil { return nil, fmt.Errorf("Address 0x%x does not belong to any function", startPC) } @@ -807,9 +809,9 @@ func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavo } currentGoroutine := true - thread := d.process.CurrentThread + thread := d.target.CurrentThread() - if s, err := d.process.ConvertEvalScope(scope.GoroutineID, scope.Frame); err == nil { + if s, err := d.target.ConvertEvalScope(scope.GoroutineID, scope.Frame); err == nil { thread = s.Thread if scope.GoroutineID != -1 { g, _ := s.Thread.GetG() diff --git a/service/debugger/locations.go b/service/debugger/locations.go index 0c85ae51..0a8db23c 100644 --- a/service/debugger/locations.go +++ b/service/debugger/locations.go @@ -243,14 +243,14 @@ func (spec *FuncLocationSpec) Match(sym *gosym.Sym) bool { } func (loc *RegexLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) { - funcs := d.process.Funcs() + funcs := d.target.Funcs() matches, err := regexFilterFuncs(loc.FuncRegex, funcs) if err != nil { return nil, err } r := make([]api.Location, 0, len(matches)) for i := range matches { - addr, err := d.process.FindFunctionLocation(matches[i], true, 0) + addr, err := d.target.FindFunctionLocation(matches[i], true, 0) if err == nil { r = append(r, api.Location{PC: addr}) } @@ -278,8 +278,8 @@ func (loc *AddrLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str addr, _ := constant.Uint64Val(v.Value) return []api.Location{{PC: addr}}, nil case reflect.Func: - _, _, fn := d.process.PCToLine(uint64(v.Base)) - pc, err := d.process.FirstPCAfterPrologue(fn, false) + _, _, fn := d.target.PCToLine(uint64(v.Base)) + pc, err := d.target.FirstPCAfterPrologue(fn, false) if err != nil { return nil, err } @@ -327,8 +327,8 @@ func (ale AmbiguousLocationError) Error() string { } func (loc *NormalLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) { - funcs := d.process.Funcs() - files := d.process.Sources() + funcs := d.target.Funcs() + files := d.target.Sources() candidates := []string{} for file := range files { @@ -366,12 +366,12 @@ func (loc *NormalLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s if loc.LineOffset < 0 { return nil, fmt.Errorf("Malformed breakpoint location, no line offset specified") } - addr, err = d.process.FindFileLocation(candidates[0], loc.LineOffset) + addr, err = d.target.FindFileLocation(candidates[0], loc.LineOffset) } else { if loc.LineOffset < 0 { - addr, err = d.process.FindFunctionLocation(candidates[0], true, 0) + addr, err = d.target.FindFunctionLocation(candidates[0], true, 0) } else { - addr, err = d.process.FindFunctionLocation(candidates[0], false, loc.LineOffset) + addr, err = d.target.FindFunctionLocation(candidates[0], false, loc.LineOffset) } } if err != nil { @@ -390,11 +390,11 @@ func (loc *OffsetLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s if scope == nil { return nil, fmt.Errorf("could not determine current location (scope is nil)") } - file, line, fn := d.process.PCToLine(scope.PC) + file, line, fn := d.target.PCToLine(scope.PC) if fn == nil { return nil, fmt.Errorf("could not determine current location") } - addr, err := d.process.FindFileLocation(file, line+loc.Offset) + addr, err := d.target.FindFileLocation(file, line+loc.Offset) return []api.Location{{PC: addr}}, err } @@ -402,10 +402,10 @@ func (loc *LineLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str if scope == nil { return nil, fmt.Errorf("could not determine current location (scope is nil)") } - file, _, fn := d.process.PCToLine(scope.PC) + file, _, fn := d.target.PCToLine(scope.PC) if fn == nil { return nil, fmt.Errorf("could not determine current location") } - addr, err := d.process.FindFileLocation(file, loc.Line) + addr, err := d.target.FindFileLocation(file, loc.Line) return []api.Location{{PC: addr}}, err } diff --git a/service/test/variables_test.go b/service/test/variables_test.go index e4b5da57..e88a739d 100644 --- a/service/test/variables_test.go +++ b/service/test/variables_test.go @@ -54,7 +54,7 @@ func assertVariable(t *testing.T, variable *proc.Variable, expected varTest) { } func evalVariable(p *proc.Process, symbol string, cfg proc.LoadConfig) (*proc.Variable, error) { - scope, err := p.CurrentThread.Scope() + scope, err := p.CurrentThread().Scope() if err != nil { return nil, err } @@ -68,7 +68,7 @@ func (tc *varTest) alternateVarTest() varTest { } func setVariable(p *proc.Process, symbol, value string) error { - scope, err := p.CurrentThread.Scope() + scope, err := p.CurrentThread().Scope() if err != nil { return err } @@ -348,7 +348,7 @@ func TestLocalVariables(t *testing.T) { assertNoError(err, t, "Continue() returned an error") for _, tc := range testcases { - scope, err := p.CurrentThread.Scope() + scope, err := p.CurrentThread().Scope() assertNoError(err, t, "AsScope()") vars, err := tc.fn(scope, pnormalLoadConfig) assertNoError(err, t, "LocalVariables() returned an error")