diff --git a/command/command.go b/command/command.go index 44b549bf..d16b60c5 100644 --- a/command/command.go +++ b/command/command.go @@ -31,6 +31,7 @@ func DebugCommands() *Commands { "step": step, "clear": clear, "print": printVar, + "threads": threads, "": nullCommand, } @@ -82,6 +83,11 @@ func help(p *proctl.DebuggedProcess, ars ...string) error { return nil } + +func threads(p *proctl.DebuggedProcess, ars ...string) error { + return p.PrintThreadInfo() +} + func cont(p *proctl.DebuggedProcess, ars ...string) error { err := p.Continue() if err != nil { diff --git a/proctl/proctl_linux_amd64.go b/proctl/proctl_linux_amd64.go index ab73cfbe..febd1946 100644 --- a/proctl/proctl_linux_amd64.go +++ b/proctl/proctl_linux_amd64.go @@ -198,6 +198,15 @@ func (dbp *DebuggedProcess) Status() *syscall.WaitStatus { return dbp.CurrentThread.Status } +func (dbp *DebuggedProcess) PrintThreadInfo() error { + for _, th := range dbp.Threads { + if err := th.PrintInfo(); err != nil { + return err + } + } + return nil +} + // Finds the executable from /proc//exe and then // uses that to parse the following information: // * Dwarf .debug_frame section diff --git a/proctl/threads_linux_amd64.go b/proctl/threads_linux_amd64.go index 8cfe9e25..ce33ba44 100644 --- a/proctl/threads_linux_amd64.go +++ b/proctl/threads_linux_amd64.go @@ -48,6 +48,16 @@ func (thread *ThreadContext) CurrentPC() (uint64, error) { return regs.PC(), nil } +func (thread *ThreadContext) PrintInfo() error { + pc, err := thread.CurrentPC() + if err != nil { + return err + } + f, l, fn := thread.Process.GoSymTable.PCToLine(pc) + fmt.Printf("Thread %d at %#v %s:%d %s\n", thread.Id, pc, f, l, fn.Name) + return nil +} + // Sets a software breakpoint at addr, and stores it in the process wide // 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 in order