Improve Go 1.4 support / cleanup goroutine printing
This commit is contained in:
parent
04097af74d
commit
13a3112b6b
@ -13,6 +13,7 @@ const (
|
||||
DW_OP_call_frame_cfa = 0x9c
|
||||
DW_OP_plus = 0x22
|
||||
DW_OP_consts = 0x11
|
||||
DW_OP_plus_uconsts = 0x23
|
||||
)
|
||||
|
||||
type stackfn func(*bytes.Buffer, []int64, int64) ([]int64, error)
|
||||
@ -22,6 +23,7 @@ var oplut = map[byte]stackfn{
|
||||
DW_OP_plus: plus,
|
||||
DW_OP_consts: consts,
|
||||
DW_OP_addr: addr,
|
||||
DW_OP_plus_uconsts: plusuconsts,
|
||||
}
|
||||
|
||||
func ExecuteStackProgram(cfa int64, instructions []byte) (int64, error) {
|
||||
@ -52,10 +54,6 @@ func addr(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
}
|
||||
|
||||
func plus(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
if len(stack) == 1 {
|
||||
return stack, nil
|
||||
}
|
||||
|
||||
var (
|
||||
slen = len(stack)
|
||||
digits = stack[slen-2 : slen]
|
||||
@ -65,6 +63,13 @@ func plus(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
return append(st, digits[0]+digits[1]), nil
|
||||
}
|
||||
|
||||
func plusuconsts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
slen := len(stack)
|
||||
num, _ := util.DecodeULEB128(buf)
|
||||
stack[slen-1] = stack[slen-1] + int64(num)
|
||||
return stack, nil
|
||||
}
|
||||
|
||||
func consts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
num, _ := util.DecodeSLEB128(buf)
|
||||
return append(stack, num), nil
|
||||
|
||||
@ -31,17 +31,7 @@ func (dbp *DebuggedProcess) PrintGoroutinesInfo() error {
|
||||
return err
|
||||
}
|
||||
reader.Seek(0)
|
||||
goidoffset, err := parsegoidoffset(dbp, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reader.Seek(0)
|
||||
schedoffset, err := parseschedoffset(dbp, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reader.Seek(0)
|
||||
allgentryaddr, err := allgentryptr(dbp, reader)
|
||||
allgentryaddr, err := addressFor(dbp, "runtime.allg", reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -50,7 +40,7 @@ func (dbp *DebuggedProcess) PrintGoroutinesInfo() error {
|
||||
allg := binary.LittleEndian.Uint64(faddr)
|
||||
|
||||
for i := uint64(0); i < allglen; i++ {
|
||||
err = printGoroutineInfo(dbp, allg+(i*8), goidoffset, schedoffset)
|
||||
err = printGoroutineInfo(dbp, allg+(i*8), reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -59,29 +49,44 @@ func (dbp *DebuggedProcess) PrintGoroutinesInfo() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func printGoroutineInfo(dbp *DebuggedProcess, addr uint64, goidoffset, schedoffset uint64) error {
|
||||
func printGoroutineInfo(dbp *DebuggedProcess, addr uint64, reader *dwarf.Reader) error {
|
||||
gaddrbytes, err := dbp.CurrentThread.readMemory(uintptr(addr), 8)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error derefing *G %s", err)
|
||||
}
|
||||
gaddr := binary.LittleEndian.Uint64(gaddrbytes)
|
||||
initialInstructions := append([]byte{op.DW_OP_addr}, gaddrbytes...)
|
||||
|
||||
goidbytes, err := dbp.CurrentThread.readMemory(uintptr(gaddr+goidoffset), 8)
|
||||
reader.Seek(0)
|
||||
goidaddr, err := offsetFor(dbp, "goid", reader, initialInstructions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reader.Seek(0)
|
||||
schedaddr, err := offsetFor(dbp, "sched", reader, initialInstructions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
goidbytes, err := dbp.CurrentThread.readMemory(uintptr(goidaddr), 8)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading goid %s", err)
|
||||
}
|
||||
schedbytes, err := dbp.CurrentThread.readMemory(uintptr(gaddr+schedoffset+8), 8)
|
||||
schedbytes, err := dbp.CurrentThread.readMemory(uintptr(schedaddr+8), 8)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading goid %s", err)
|
||||
return fmt.Errorf("error reading sched %s", err)
|
||||
}
|
||||
gopc := binary.LittleEndian.Uint64(schedbytes)
|
||||
f, l, _ := dbp.GoSymTable.PCToLine(gopc)
|
||||
fmt.Printf("Goroutine %d - %s:%d\n", binary.LittleEndian.Uint64(goidbytes), f, l)
|
||||
f, l, fn := dbp.GoSymTable.PCToLine(gopc)
|
||||
fname := ""
|
||||
if fn != nil {
|
||||
fname = fn.Name
|
||||
}
|
||||
fmt.Printf("Goroutine %d - %s:%d %s\n", binary.LittleEndian.Uint64(goidbytes), f, l, fname)
|
||||
return nil
|
||||
}
|
||||
|
||||
func allglenval(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry("runtime.allglen", reader)
|
||||
entry, err := findDwarfEntry("runtime.allglen", reader, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -101,8 +106,8 @@ func allglenval(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
return binary.LittleEndian.Uint64(val), nil
|
||||
}
|
||||
|
||||
func allgentryptr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry("runtime.allg", reader)
|
||||
func addressFor(dbp *DebuggedProcess, name string, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry(name, reader, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -119,8 +124,8 @@ func allgentryptr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
return uint64(addr), nil
|
||||
}
|
||||
|
||||
func parsegoidoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry("goid", reader)
|
||||
func offsetFor(dbp *DebuggedProcess, name string, reader *dwarf.Reader, parentinstr []byte) (uint64, error) {
|
||||
entry, err := findDwarfEntry(name, reader, true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -128,24 +133,7 @@ func parsegoidoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("type assertion failed")
|
||||
}
|
||||
offset, err := op.ExecuteStackProgram(0, instructions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uint64(offset), nil
|
||||
}
|
||||
|
||||
func parseschedoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry("sched", reader)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
instructions, ok := entry.Val(dwarf.AttrDataMemberLoc).([]byte)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("type assertion failed")
|
||||
}
|
||||
offset, err := op.ExecuteStackProgram(0, instructions)
|
||||
offset, err := op.ExecuteStackProgram(0, append(parentinstr, instructions...))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -171,7 +159,7 @@ func (thread *ThreadContext) EvalSymbol(name string) (*Variable, error) {
|
||||
reader := data.Reader()
|
||||
err = findFunction(fn.Name, reader)
|
||||
|
||||
entry, err := findDwarfEntry(name, reader)
|
||||
entry, err := findDwarfEntry(name, reader, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -226,14 +214,20 @@ func findFunction(name string, reader *dwarf.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func findDwarfEntry(name string, reader *dwarf.Reader) (*dwarf.Entry, error) {
|
||||
func findDwarfEntry(name string, reader *dwarf.Reader, member bool) (*dwarf.Entry, error) {
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if entry.Tag != dwarf.TagVariable && entry.Tag != dwarf.TagFormalParameter && entry.Tag != dwarf.TagMember {
|
||||
continue
|
||||
if member {
|
||||
if entry.Tag != dwarf.TagMember {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if entry.Tag != dwarf.TagVariable && entry.Tag != dwarf.TagFormalParameter {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
n, ok := entry.Val(dwarf.AttrName).(string)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user