mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 18:57: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 { | 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 { | func cont(p *proctl.DebuggedProcess, args ...string) error { | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ package proctl | |||||||
| import ( | import ( | ||||||
| 	"debug/dwarf" | 	"debug/dwarf" | ||||||
| 	"debug/gosym" | 	"debug/gosym" | ||||||
|  | 	"encoding/binary" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
| @ -296,7 +297,7 @@ func (dbp *DebuggedProcess) next() error { | |||||||
| 		} | 		} | ||||||
| 		// Make sure we're on the same goroutine. | 		// Make sure we're on the same goroutine. | ||||||
| 		// TODO(dp) take into account goroutine exit. | 		// TODO(dp) take into account goroutine exit. | ||||||
| 		if tg.id == curg.id { | 		if tg.Id == curg.Id { | ||||||
| 			if dbp.CurrentThread != thread { | 			if dbp.CurrentThread != thread { | ||||||
| 				dbp.SwitchThread(thread.Id) | 				dbp.SwitchThread(thread.Id) | ||||||
| 			} | 			} | ||||||
| @ -377,6 +378,34 @@ func (dbp *DebuggedProcess) SwitchThread(tid int) error { | |||||||
| 	return fmt.Errorf("thread %d does not exist", tid) | 	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 | // Obtains register values from what Delve considers to be the current | ||||||
| // thread of the traced process. | // thread of the traced process. | ||||||
| func (dbp *DebuggedProcess) Registers() (Registers, error) { | func (dbp *DebuggedProcess) Registers() (Registers, error) { | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package proctl | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"debug/dwarf" | 	"debug/dwarf" | ||||||
|  | 	"debug/gosym" | ||||||
| 	"encoding/binary" | 	"encoding/binary" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| @ -32,8 +33,11 @@ type M struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type G struct { | type G struct { | ||||||
| 	id int | 	Id   int | ||||||
| 	pc uint64 | 	PC   uint64 | ||||||
|  | 	File string | ||||||
|  | 	Line int | ||||||
|  | 	Func *gosym.Func | ||||||
| } | } | ||||||
|  |  | ||||||
| const ptrsize uintptr = unsafe.Sizeof(int(1)) | const ptrsize uintptr = unsafe.Sizeof(int(1)) | ||||||
| @ -205,37 +209,6 @@ func parseAllMPtr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) { | |||||||
| 	return uint64(addr), nil | 	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) { | func parseG(dbp *DebuggedProcess, addr uint64, reader *dwarf.Reader) (*G, error) { | ||||||
| 	gaddrbytes, err := dbp.CurrentThread.readMemory(uintptr(addr), ptrsize) | 	gaddrbytes, err := dbp.CurrentThread.readMemory(uintptr(addr), ptrsize) | ||||||
| 	if err != nil { | 	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) | 		return nil, fmt.Errorf("error reading sched %s", err) | ||||||
| 	} | 	} | ||||||
| 	gopc := binary.LittleEndian.Uint64(schedbytes) | 	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) { | func allglenval(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Derek Parker
					Derek Parker