diff --git a/pkg/proc/disasm.go b/pkg/proc/disasm.go index b62c9d3025918c6a64890b7da4e4f8457a66a11d..07b25866bdee61ee248db9597b140ffb292a5584 100644 --- a/pkg/proc/disasm.go +++ b/pkg/proc/disasm.go @@ -21,6 +21,9 @@ const ( // If currentGoroutine is set and thread is stopped at a CALL instruction Disassemble will evaluate the argument of the CALL instruction using the thread's registers // Be aware that the Bytes field of each returned instruction is a slice of a larger array of size endPC - startPC func Disassemble(dbp Process, g *G, startPC, endPC uint64) ([]AsmInstruction, error) { + if dbp.Exited() { + return nil, &ProcessExitedError{Pid: dbp.Pid()} + } if g == nil { ct := dbp.CurrentThread() regs, _ := ct.Registers(false) diff --git a/pkg/proc/native/proc.go b/pkg/proc/native/proc.go index 39428b759402919c45b4ab17479d22bd9afca168..3f3854ec18ac0ab002382c3ad4648ad65c0a407d 100644 --- a/pkg/proc/native/proc.go +++ b/pkg/proc/native/proc.go @@ -173,7 +173,7 @@ func (dbp *Process) LoadInformation(path string) error { // sends SIGSTOP to all threads. func (dbp *Process) RequestManualStop() error { if dbp.exited { - return &proc.ProcessExitedError{} + return &proc.ProcessExitedError{Pid: dbp.Pid()} } dbp.haltMu.Lock() defer dbp.haltMu.Unlock() @@ -241,7 +241,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond as // ClearBreakpoint clears the breakpoint at addr. func (dbp *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) { if dbp.exited { - return nil, &proc.ProcessExitedError{} + return nil, &proc.ProcessExitedError{Pid: dbp.Pid()} } bp, ok := dbp.FindBreakpoint(addr) if !ok { @@ -259,7 +259,7 @@ func (dbp *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) { func (dbp *Process) ContinueOnce() (proc.Thread, error) { if dbp.exited { - return nil, &proc.ProcessExitedError{} + return nil, &proc.ProcessExitedError{Pid: dbp.Pid()} } if err := dbp.resume(); err != nil { @@ -307,7 +307,7 @@ func (dbp *Process) StepInstruction() (err error) { } dbp.allGCache = nil if dbp.exited { - return &proc.ProcessExitedError{} + return &proc.ProcessExitedError{Pid: dbp.Pid()} } thread.clearBreakpointState() err = thread.StepInstruction() @@ -327,7 +327,7 @@ func (dbp *Process) StepInstruction() (err error) { // SwitchThread changes from current thread to the thread specified by `tid`. func (dbp *Process) SwitchThread(tid int) error { if dbp.exited { - return &proc.ProcessExitedError{} + return &proc.ProcessExitedError{Pid: dbp.Pid()} } if th, ok := dbp.threads[tid]; ok { dbp.currentThread = th @@ -341,7 +341,7 @@ func (dbp *Process) SwitchThread(tid int) error { // running the specified goroutine. func (dbp *Process) SwitchGoroutine(gid int) error { if dbp.exited { - return &proc.ProcessExitedError{} + return &proc.ProcessExitedError{Pid: dbp.Pid()} } g, err := proc.FindGoroutine(dbp, gid) if err != nil { @@ -361,7 +361,7 @@ func (dbp *Process) SwitchGoroutine(gid int) error { // Halt stops all threads. func (dbp *Process) Halt() (err error) { if dbp.exited { - return &proc.ProcessExitedError{} + return &proc.ProcessExitedError{Pid: dbp.Pid()} } for _, th := range dbp.threads { if err := th.Halt(); err != nil { diff --git a/pkg/proc/proc.go b/pkg/proc/proc.go index 959370e15db48bfac8112265c3f22cf86d710c50..93d29b6881996a6b62579b24cc4c80a8a431a60e 100644 --- a/pkg/proc/proc.go +++ b/pkg/proc/proc.go @@ -71,7 +71,7 @@ func FindFunctionLocation(p Process, funcName string, firstLine bool, lineOffset // Next continues execution until the next source line. func Next(dbp Process) (err error) { if dbp.Exited() { - return &ProcessExitedError{} + return &ProcessExitedError{Pid: dbp.Pid()} } for _, bp := range dbp.Breakpoints() { if bp.Internal() { @@ -91,6 +91,9 @@ func Next(dbp Process) (err error) { // process. It will continue until it hits a breakpoint // or is otherwise stopped. func Continue(dbp Process) error { + if dbp.Exited() { + return &ProcessExitedError{Pid: dbp.Pid()} + } dbp.ManualStopRequested() for { if dbp.ManualStopRequested() { @@ -213,7 +216,7 @@ func pickCurrentThread(dbp Process, trapthread Thread, threads []Thread) error { // Will step into functions. func Step(dbp Process) (err error) { if dbp.Exited() { - return &ProcessExitedError{} + return &ProcessExitedError{Pid: dbp.Pid()} } for _, bp := range dbp.Breakpoints() { if bp.Internal() { @@ -277,6 +280,9 @@ func andFrameoffCondition(cond ast.Expr, frameoff int64) ast.Expr { // StepOut will continue until the current goroutine exits the // function currently being executed or a deferred function is executed func StepOut(dbp Process) error { + if dbp.Exited() { + return &ProcessExitedError{Pid: dbp.Pid()} + } selg := dbp.SelectedGoroutine() curthread := dbp.CurrentThread() @@ -349,7 +355,7 @@ type AllGCache interface { // Delve cares about from the internal runtime G structure. func GoroutinesInfo(dbp Process) ([]*G, error) { if dbp.Exited() { - return nil, &ProcessExitedError{} + return nil, &ProcessExitedError{Pid: dbp.Pid()} } if dbp, ok := dbp.(AllGCache); ok { if allGCache := dbp.AllGCache(); *allGCache != nil { @@ -453,6 +459,9 @@ func FindGoroutine(dbp Process, gid int) (*G, error) { // ConvertEvalScope returns a new EvalScope in the context of the // specified goroutine ID and stack frame. func ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) { + if dbp.Exited() { + return nil, &ProcessExitedError{Pid: dbp.Pid()} + } ct := dbp.CurrentThread() g, err := FindGoroutine(dbp, gid) if err != nil { diff --git a/pkg/proc/stack.go b/pkg/proc/stack.go index 0709c1ff40dccf844657f02f89195b28bcc1cf29..f527b91302a37bd82743845f101bbce47d17fb91 100644 --- a/pkg/proc/stack.go +++ b/pkg/proc/stack.go @@ -42,7 +42,7 @@ type Stackframe struct { Err error } -// Stacktrace returns the stack trace for thread. +// ThreadStacktrace returns the stack trace for thread. // Note the locations in the array are return addresses not call addresses. func ThreadStacktrace(thread Thread, depth int) ([]Stackframe, error) { regs, err := thread.Registers(false) diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index c018c4eaee15386ab3d5ae00c70284979e51d563..289e4182a407439c632c0ad14f23332cfb34005c 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -457,8 +457,9 @@ func (d *Debugger) Threads() ([]*api.Thread, error) { defer d.processMutex.Unlock() if d.target.Exited() { - return nil, &proc.ProcessExitedError{} + return nil, proc.ProcessExitedError{Pid: d.ProcessPid()} } + threads := []*api.Thread{} for _, th := range d.target.ThreadList() { threads = append(threads, api.ConvertThread(th)) @@ -472,7 +473,7 @@ func (d *Debugger) FindThread(id int) (*api.Thread, error) { defer d.processMutex.Unlock() if d.target.Exited() { - return nil, &proc.ProcessExitedError{} + return nil, proc.ProcessExitedError{Pid: d.ProcessPid()} } for _, th := range d.target.ThreadList() { @@ -838,6 +839,10 @@ func (d *Debugger) Stacktrace(goroutineID, depth int, cfg *proc.LoadConfig) ([]a d.processMutex.Lock() defer d.processMutex.Unlock() + if d.target.Exited() { + return nil, proc.ProcessExitedError{Pid: d.ProcessPid()} + } + var rawlocs []proc.Stackframe g, err := proc.FindGoroutine(d.target, goroutineID) @@ -893,6 +898,10 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat d.processMutex.Lock() defer d.processMutex.Unlock() + if d.target.Exited() { + return nil, &proc.ProcessExitedError{Pid: d.target.Pid()} + } + loc, err := parseLocationSpec(locStr) if err != nil { return nil, err @@ -910,12 +919,16 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat return locs, err } -// Disassembles code between startPC and endPC +// Disassemble code between startPC and endPC // if endPC == 0 it will find the function containing startPC and disassemble the whole function func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) { d.processMutex.Lock() defer d.processMutex.Unlock() + if d.target.Exited() { + return nil, &proc.ProcessExitedError{Pid: d.target.Pid()} + } + if endPC == 0 { _, _, fn := d.target.BinInfo().PCToLine(startPC) if fn == nil {