提交 42a57ad2 编写于 作者: D Derek Parker

Move print goroutine info into command

* DebuggedProcess method: `PrintGoroutinesInfo` -> `GoroutinesInfo`
* `goroutines` command in command/command.go now responsible for
  printing info.
上级 22ac63f0
......@@ -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) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册