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 { | ||||
| 	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
	 Derek Parker
					Derek Parker