mirror of
https://github.com/go-delve/delve.git
synced 2025-10-31 02:36:18 +08:00
Move print goroutine info into command
* DebuggedProcess method: `PrintGoroutinesInfo` -> `GoroutinesInfo` * `goroutines` command in command/command.go now responsible for printing info.
This commit is contained in:
@ -158,7 +158,21 @@ func thread(p *proctl.DebuggedProcess, args ...string) error {
|
||||
}
|
||||
|
||||
func goroutines(p *proctl.DebuggedProcess, args ...string) error {
|
||||
return p.PrintGoroutinesInfo()
|
||||
var fname string
|
||||
gs, err := p.GoroutinesInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("[%d goroutines]\n", len(gs))
|
||||
for _, g := range gs {
|
||||
if g.Func != nil {
|
||||
fname = g.Func.Name
|
||||
}
|
||||
fmt.Printf("Goroutine %d - %s:%d %s\n", g.Id, g.File, g.Line, fname)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func cont(p *proctl.DebuggedProcess, args ...string) error {
|
||||
|
||||
@ -5,6 +5,7 @@ package proctl
|
||||
import (
|
||||
"debug/dwarf"
|
||||
"debug/gosym"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -296,7 +297,7 @@ func (dbp *DebuggedProcess) next() error {
|
||||
}
|
||||
// Make sure we're on the same goroutine.
|
||||
// TODO(dp) take into account goroutine exit.
|
||||
if tg.id == curg.id {
|
||||
if tg.Id == curg.Id {
|
||||
if dbp.CurrentThread != thread {
|
||||
dbp.SwitchThread(thread.Id)
|
||||
}
|
||||
@ -377,6 +378,34 @@ func (dbp *DebuggedProcess) SwitchThread(tid int) error {
|
||||
return fmt.Errorf("thread %d does not exist", tid)
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) GoroutinesInfo() ([]*G, error) {
|
||||
var (
|
||||
allg []*G
|
||||
reader = dbp.dwarf.Reader()
|
||||
)
|
||||
|
||||
allglen, err := allglenval(dbp, reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reader.Seek(0)
|
||||
allgentryaddr, err := addressFor(dbp, "runtime.allg", reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
faddr, err := dbp.CurrentThread.readMemory(uintptr(allgentryaddr), ptrsize)
|
||||
allgptr := binary.LittleEndian.Uint64(faddr)
|
||||
|
||||
for i := uint64(0); i < allglen; i++ {
|
||||
g, err := parseG(dbp, allgptr+(i*uint64(ptrsize)), reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allg = append(allg, g)
|
||||
}
|
||||
return allg, nil
|
||||
}
|
||||
|
||||
// Obtains register values from what Delve considers to be the current
|
||||
// thread of the traced process.
|
||||
func (dbp *DebuggedProcess) Registers() (Registers, error) {
|
||||
|
||||
@ -3,6 +3,7 @@ package proctl
|
||||
import (
|
||||
"bytes"
|
||||
"debug/dwarf"
|
||||
"debug/gosym"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
@ -32,8 +33,11 @@ type M struct {
|
||||
}
|
||||
|
||||
type G struct {
|
||||
id int
|
||||
pc uint64
|
||||
Id int
|
||||
PC uint64
|
||||
File string
|
||||
Line int
|
||||
Func *gosym.Func
|
||||
}
|
||||
|
||||
const ptrsize uintptr = unsafe.Sizeof(int(1))
|
||||
@ -205,37 +209,6 @@ func parseAllMPtr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
return uint64(addr), nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) PrintGoroutinesInfo() error {
|
||||
reader := dbp.dwarf.Reader()
|
||||
|
||||
allglen, err := allglenval(dbp, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reader.Seek(0)
|
||||
allgentryaddr, err := addressFor(dbp, "runtime.allg", reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("[%d goroutines]\n", allglen)
|
||||
faddr, err := dbp.CurrentThread.readMemory(uintptr(allgentryaddr), ptrsize)
|
||||
allg := binary.LittleEndian.Uint64(faddr)
|
||||
|
||||
for i := uint64(0); i < allglen; i++ {
|
||||
g, err := parseG(dbp, allg+(i*uint64(ptrsize)), reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, l, fn := dbp.goSymTable.PCToLine(g.pc)
|
||||
fname := ""
|
||||
if fn != nil {
|
||||
fname = fn.Name
|
||||
}
|
||||
fmt.Printf("Goroutine %d - %s:%d %s\n", g.id, f, l, fname)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseG(dbp *DebuggedProcess, addr uint64, reader *dwarf.Reader) (*G, error) {
|
||||
gaddrbytes, err := dbp.CurrentThread.readMemory(uintptr(addr), ptrsize)
|
||||
if err != nil {
|
||||
@ -263,7 +236,15 @@ func parseG(dbp *DebuggedProcess, addr uint64, reader *dwarf.Reader) (*G, error)
|
||||
return nil, fmt.Errorf("error reading sched %s", err)
|
||||
}
|
||||
gopc := binary.LittleEndian.Uint64(schedbytes)
|
||||
return &G{id: int(binary.LittleEndian.Uint64(goidbytes)), pc: gopc}, nil
|
||||
f, l, fn := dbp.goSymTable.PCToLine(gopc)
|
||||
g := &G{
|
||||
Id: int(binary.LittleEndian.Uint64(goidbytes)),
|
||||
PC: gopc,
|
||||
File: f,
|
||||
Line: l,
|
||||
Func: fn,
|
||||
}
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func allglenval(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
|
||||
Reference in New Issue
Block a user