diff --git a/pkg/proc/bininfo.go b/pkg/proc/bininfo.go index 475bdb1a..05196c9a 100644 --- a/pkg/proc/bininfo.go +++ b/pkg/proc/bininfo.go @@ -809,29 +809,51 @@ func (bi *BinaryInfo) LoadImageFromData(dwdata *dwarf.Data, debugFrameBytes, deb bi.Images = append(bi.Images, image) } -func (bi *BinaryInfo) locationExpr(entry godwarf.Entry, attr dwarf.Attr, pc uint64) ([]byte, string, error) { +func (bi *BinaryInfo) locationExpr(entry godwarf.Entry, attr dwarf.Attr, pc uint64) ([]byte, *locationExpr, error) { a := entry.Val(attr) if a == nil { - return nil, "", fmt.Errorf("no location attribute %s", attr) + return nil, nil, fmt.Errorf("no location attribute %s", attr) } if instr, ok := a.([]byte); ok { - var descr bytes.Buffer - fmt.Fprintf(&descr, "[block] ") - op.PrettyPrint(&descr, instr) - return instr, descr.String(), nil + return instr, &locationExpr{isBlock: true, instr: instr}, nil } off, ok := a.(int64) if !ok { - return nil, "", fmt.Errorf("could not interpret location attribute %s", attr) + return nil, nil, fmt.Errorf("could not interpret location attribute %s", attr) } instr := bi.loclistEntry(off, pc) if instr == nil { - return nil, "", fmt.Errorf("could not find loclist entry at %#x for address %#x", off, pc) + return nil, nil, fmt.Errorf("could not find loclist entry at %#x for address %#x", off, pc) + } + return instr, &locationExpr{pc: pc, off: off, instr: instr}, nil +} + +type locationExpr struct { + isBlock bool + isEscaped bool + off int64 + pc uint64 + instr []byte +} + +func (le *locationExpr) String() string { + if le == nil { + return "" } var descr bytes.Buffer - fmt.Fprintf(&descr, "[%#x:%#x] ", off, pc) - op.PrettyPrint(&descr, instr) - return instr, descr.String(), nil + + if le.isBlock { + fmt.Fprintf(&descr, "[block] ") + op.PrettyPrint(&descr, le.instr) + } else { + fmt.Fprintf(&descr, "[%#x:%#x] ", le.off, le.pc) + op.PrettyPrint(&descr, le.instr) + } + + if le.isEscaped { + fmt.Fprintf(&descr, " (escaped)") + } + return descr.String() } // LocationCovers returns the list of PC addresses that is covered by the @@ -877,10 +899,10 @@ func (bi *BinaryInfo) LocationCovers(entry *dwarf.Entry, attr dwarf.Attr) ([][2] // This will either be an int64 address or a slice of Pieces for locations // that don't correspond to a single memory address (registers, composite // locations). -func (bi *BinaryInfo) Location(entry godwarf.Entry, attr dwarf.Attr, pc uint64, regs op.DwarfRegisters) (int64, []op.Piece, string, error) { +func (bi *BinaryInfo) Location(entry godwarf.Entry, attr dwarf.Attr, pc uint64, regs op.DwarfRegisters) (int64, []op.Piece, *locationExpr, error) { instr, descr, err := bi.locationExpr(entry, attr, pc) if err != nil { - return 0, nil, "", err + return 0, nil, nil, err } addr, pieces, err := op.ExecuteStackProgram(regs, instr, bi.Arch.PtrSize()) return addr, pieces, descr, err diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go index 175d4558..ce85f597 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -266,7 +266,8 @@ func (scope *EvalScope) Locals() ([]*Variable, error) { } v.Name = name[1:] v.Flags |= VariableEscaped - v.LocationExpr = locationExpr + " (escaped)" + locationExpr.isEscaped = true + v.LocationExpr = locationExpr v.DeclLine = declLine vars[i] = v } diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index a1c68508..dfc1a58b 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -118,8 +118,8 @@ type Variable struct { loaded bool Unreadable error - LocationExpr string // location expression - DeclLine int64 // line number of this variable's declaration + LocationExpr *locationExpr // location expression + DeclLine int64 // line number of this variable's declaration } // LoadConfig controls how variables are loaded from the targets memory. @@ -441,8 +441,6 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) { return nil, err } - name := "" - if deref { typ = &godwarf.PtrType{ CommonType: godwarf.CommonType{ @@ -453,11 +451,9 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) { }, Type: typ, } - } else { - name = "runtime.curg" } - return newVariableFromThread(thread, name, gaddr, typ), nil + return newVariableFromThread(thread, "", gaddr, typ), nil } // Defer returns the top-most defer of the goroutine. @@ -851,6 +847,8 @@ func (v *Variable) parseG() (*G, error) { f, l, fn := v.bi.PCToLine(uint64(pc)) + v.Name = "runtime.curg" + g := &G{ ID: int(id), GoPC: uint64(gopc), diff --git a/service/api/conversions.go b/service/api/conversions.go index 0c0a205b..25470633 100644 --- a/service/api/conversions.go +++ b/service/api/conversions.go @@ -148,7 +148,7 @@ func ConvertVar(v *proc.Variable) *Variable { Flags: VariableFlags(v.Flags), Base: v.Base, - LocationExpr: v.LocationExpr, + LocationExpr: v.LocationExpr.String(), DeclLine: v.DeclLine, }