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_call_frame_cfa = 0x9c
|
||||||
DW_OP_plus = 0x22
|
DW_OP_plus = 0x22
|
||||||
DW_OP_consts = 0x11
|
DW_OP_consts = 0x11
|
||||||
|
DW_OP_plus_uconsts = 0x23
|
||||||
)
|
)
|
||||||
|
|
||||||
type stackfn func(*bytes.Buffer, []int64, int64) ([]int64, error)
|
type stackfn func(*bytes.Buffer, []int64, int64) ([]int64, error)
|
||||||
@ -22,6 +23,7 @@ var oplut = map[byte]stackfn{
|
|||||||
DW_OP_plus: plus,
|
DW_OP_plus: plus,
|
||||||
DW_OP_consts: consts,
|
DW_OP_consts: consts,
|
||||||
DW_OP_addr: addr,
|
DW_OP_addr: addr,
|
||||||
|
DW_OP_plus_uconsts: plusuconsts,
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecuteStackProgram(cfa int64, instructions []byte) (int64, error) {
|
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) {
|
func plus(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||||
if len(stack) == 1 {
|
|
||||||
return stack, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
slen = len(stack)
|
slen = len(stack)
|
||||||
digits = stack[slen-2 : slen]
|
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
|
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) {
|
func consts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||||
num, _ := util.DecodeSLEB128(buf)
|
num, _ := util.DecodeSLEB128(buf)
|
||||||
return append(stack, num), nil
|
return append(stack, num), nil
|
||||||
|
|||||||
@ -31,17 +31,7 @@ func (dbp *DebuggedProcess) PrintGoroutinesInfo() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
reader.Seek(0)
|
reader.Seek(0)
|
||||||
goidoffset, err := parsegoidoffset(dbp, reader)
|
allgentryaddr, err := addressFor(dbp, "runtime.allg", 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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -50,7 +40,7 @@ func (dbp *DebuggedProcess) PrintGoroutinesInfo() error {
|
|||||||
allg := binary.LittleEndian.Uint64(faddr)
|
allg := binary.LittleEndian.Uint64(faddr)
|
||||||
|
|
||||||
for i := uint64(0); i < allglen; i++ {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -59,29 +49,44 @@ func (dbp *DebuggedProcess) PrintGoroutinesInfo() error {
|
|||||||
return nil
|
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)
|
gaddrbytes, err := dbp.CurrentThread.readMemory(uintptr(addr), 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error derefing *G %s", err)
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading goid %s", err)
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading goid %s", err)
|
return fmt.Errorf("error reading sched %s", err)
|
||||||
}
|
}
|
||||||
gopc := binary.LittleEndian.Uint64(schedbytes)
|
gopc := binary.LittleEndian.Uint64(schedbytes)
|
||||||
f, l, _ := dbp.GoSymTable.PCToLine(gopc)
|
f, l, fn := dbp.GoSymTable.PCToLine(gopc)
|
||||||
fmt.Printf("Goroutine %d - %s:%d\n", binary.LittleEndian.Uint64(goidbytes), f, l)
|
fname := ""
|
||||||
|
if fn != nil {
|
||||||
|
fname = fn.Name
|
||||||
|
}
|
||||||
|
fmt.Printf("Goroutine %d - %s:%d %s\n", binary.LittleEndian.Uint64(goidbytes), f, l, fname)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func allglenval(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -101,8 +106,8 @@ func allglenval(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
|||||||
return binary.LittleEndian.Uint64(val), nil
|
return binary.LittleEndian.Uint64(val), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func allgentryptr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
func addressFor(dbp *DebuggedProcess, name string, reader *dwarf.Reader) (uint64, error) {
|
||||||
entry, err := findDwarfEntry("runtime.allg", reader)
|
entry, err := findDwarfEntry(name, reader, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -119,8 +124,8 @@ func allgentryptr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
|||||||
return uint64(addr), nil
|
return uint64(addr), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsegoidoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
func offsetFor(dbp *DebuggedProcess, name string, reader *dwarf.Reader, parentinstr []byte) (uint64, error) {
|
||||||
entry, err := findDwarfEntry("goid", reader)
|
entry, err := findDwarfEntry(name, reader, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -128,24 +133,7 @@ func parsegoidoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error)
|
|||||||
if !ok {
|
if !ok {
|
||||||
return 0, fmt.Errorf("type assertion failed")
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -171,7 +159,7 @@ func (thread *ThreadContext) EvalSymbol(name string) (*Variable, error) {
|
|||||||
reader := data.Reader()
|
reader := data.Reader()
|
||||||
err = findFunction(fn.Name, reader)
|
err = findFunction(fn.Name, reader)
|
||||||
|
|
||||||
entry, err := findDwarfEntry(name, reader)
|
entry, err := findDwarfEntry(name, reader, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -226,15 +214,21 @@ func findFunction(name string, reader *dwarf.Reader) error {
|
|||||||
return nil
|
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() {
|
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.Tag != dwarf.TagVariable && entry.Tag != dwarf.TagFormalParameter && entry.Tag != dwarf.TagMember {
|
if member {
|
||||||
|
if entry.Tag != dwarf.TagMember {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if entry.Tag != dwarf.TagVariable && entry.Tag != dwarf.TagFormalParameter {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
n, ok := entry.Val(dwarf.AttrName).(string)
|
n, ok := entry.Val(dwarf.AttrName).(string)
|
||||||
if !ok || n != name {
|
if !ok || n != name {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user