From c4413308227f24fc07d3513620ff9e95ff428b9b Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Sun, 11 Aug 2019 22:56:16 +0200 Subject: [PATCH] proc: remove (*EvalScope).globalFor (#1658) --- pkg/proc/dwarf_expr_test.go | 6 ++-- pkg/proc/eval.go | 63 ++++++++----------------------------- pkg/proc/fncall.go | 6 ++-- pkg/proc/variables.go | 38 ++++++++++++++++++++++ 4 files changed, 58 insertions(+), 55 deletions(-) diff --git a/pkg/proc/dwarf_expr_test.go b/pkg/proc/dwarf_expr_test.go index 04fabe8e..29e2135e 100644 --- a/pkg/proc/dwarf_expr_test.go +++ b/pkg/proc/dwarf_expr_test.go @@ -212,12 +212,14 @@ func TestDwarfExprLoclist(t *testing.T) { mainfn := bi.LookupFunc["main.main"] mem := newFakeMemory(defaultCFA, uint16(before), uint16(after)) - regs := linutil.AMD64Registers{Regs: &linutil.AMD64PtraceRegs{}} + const PC = 0x40100 + regs := linutil.AMD64Registers{Regs: &linutil.AMD64PtraceRegs{Rip: PC}} - scope := &proc.EvalScope{Location: proc.Location{PC: 0x40100, Fn: mainfn}, Regs: dwarfRegisters(bi, ®s), Mem: mem, BinInfo: bi} + scope := &proc.EvalScope{Location: proc.Location{PC: PC, Fn: mainfn}, Regs: dwarfRegisters(bi, ®s), Mem: mem, BinInfo: bi} uintExprCheck(t, scope, "a", before) scope.PC = 0x40800 + scope.Regs.Regs[scope.Regs.PCRegNum].Uint64Val = scope.PC uintExprCheck(t, scope, "a", after) } diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go index 5897f753..f321bc89 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -108,7 +108,7 @@ func (scope *EvalScope) Locals() ([]*Variable, error) { hasScopes := false for varReader.Next() { entry := varReader.Entry() - val, err := scope.extractVarInfoFromEntry(entry) + val, err := extractVarInfoFromEntry(scope.BinInfo, scope.image(), scope.Regs, scope.Mem, entry) if err != nil { // skip variables that we can't parse yet continue @@ -249,45 +249,6 @@ func (scope *EvalScope) setValue(dstv, srcv *Variable, srcExpr string) error { return fmt.Errorf("can not set variables of type %s (not implemented)", dstv.Kind.String()) } -// Extracts the name and type of a variable from a dwarf entry -// then executes the instructions given in the DW_AT_location attribute to grab the variable's address -func (scope *EvalScope) extractVarInfoFromEntry(varEntry *dwarf.Entry) (*Variable, error) { - if varEntry == nil { - return nil, fmt.Errorf("invalid entry") - } - - if varEntry.Tag != dwarf.TagFormalParameter && varEntry.Tag != dwarf.TagVariable { - return nil, fmt.Errorf("invalid entry tag, only supports FormalParameter and Variable, got %s", varEntry.Tag.String()) - } - - entry, n, t, err := readVarEntry(varEntry, scope.image()) - if err != nil { - return nil, err - } - - addr, pieces, descr, err := scope.BinInfo.Location(entry, dwarf.AttrLocation, scope.PC, scope.Regs) - mem := scope.Mem - if pieces != nil { - addr = fakeAddress - var cmem *compositeMemory - cmem, err = newCompositeMemory(scope.Mem, scope.Regs, pieces) - if cmem != nil { - mem = cmem - } - } - - v := scope.newVariable(n, uintptr(addr), t, mem) - if pieces != nil { - v.Flags |= VariableFakeAddress - } - v.LocationExpr = descr - v.DeclLine, _ = entry.Val(dwarf.AttrDeclLine).(int64) - if err != nil { - v.Unreadable = err - } - return v, nil -} - // EvalVariable returns the value of the given expression (backwards compatibility). func (scope *EvalScope) EvalVariable(name string, cfg LoadConfig) (*Variable, error) { return scope.EvalExpression(name, cfg) @@ -364,6 +325,11 @@ func filterVariables(vars []*Variable, pred func(v *Variable) bool) []*Variable return r } +func regsReplaceStaticBase(regs op.DwarfRegisters, image *Image) op.DwarfRegisters { + regs.StaticBase = image.StaticBase + return regs +} + // PackageVariables returns the name, value, and type of all package variables in the application. func (scope *EvalScope) PackageVariables(cfg LoadConfig) ([]*Variable, error) { var vars []*Variable @@ -389,7 +355,7 @@ func (scope *EvalScope) PackageVariables(cfg LoadConfig) ([]*Variable, error) { } // Ignore errors trying to extract values - val, err := scope.globalFor(image).extractVarInfoFromEntry(entry) + val, err := extractVarInfoFromEntry(scope.BinInfo, image, regsReplaceStaticBase(scope.Regs, image), scope.Mem, entry) if err != nil { continue } @@ -410,13 +376,13 @@ func (scope *EvalScope) findGlobal(name string) (*Variable, error) { if err != nil { return nil, err } - return scope.globalFor(pkgvar.cu.image).extractVarInfoFromEntry(entry) + return extractVarInfoFromEntry(scope.BinInfo, pkgvar.cu.image, regsReplaceStaticBase(scope.Regs, pkgvar.cu.image), scope.Mem, entry) } } for _, fn := range scope.BinInfo.Functions { if fn.Name == name || strings.HasSuffix(fn.Name, "/"+name) { //TODO(aarzilli): convert function entry into a function type? - r := scope.globalFor(fn.cu.image).newVariable(fn.Name, uintptr(fn.Entry), &godwarf.FuncType{}, scope.Mem) + r := newVariable(fn.Name, uintptr(fn.Entry), &godwarf.FuncType{}, scope.BinInfo, scope.Mem) r.Value = constant.MakeString(fn.Name) r.Base = uintptr(fn.Entry) r.loaded = true @@ -430,7 +396,7 @@ func (scope *EvalScope) findGlobal(name string) (*Variable, error) { if err != nil { return nil, err } - v := scope.globalFor(scope.BinInfo.Images[0]).newVariable(name, 0x0, t, scope.Mem) + v := newVariable(name, 0x0, t, scope.BinInfo, scope.Mem) switch v.Kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: v.Value = constant.MakeInt64(cval.value) @@ -447,9 +413,6 @@ func (scope *EvalScope) findGlobal(name string) (*Variable, error) { } return nil, fmt.Errorf("could not find symbol value for %s", name) } -func (scope *EvalScope) newVariable(name string, addr uintptr, dwarfType godwarf.Type, mem MemoryReadWriter) *Variable { - return newVariable(name, addr, dwarfType, scope.BinInfo, mem) -} // image returns the image containing the current function. func (scope *EvalScope) image() *Image { @@ -522,7 +485,7 @@ func (scope *EvalScope) evalToplevelTypeCast(t ast.Expr, cfg LoadConfig) (*Varia return nil, converr } for i, ch := range []byte(constant.StringVal(argv.Value)) { - e := scope.newVariable("", argv.Addr+uintptr(i), targetType.(*godwarf.SliceType).ElemType, argv.mem) + e := newVariable("", argv.Addr+uintptr(i), targetType.(*godwarf.SliceType).ElemType, scope.BinInfo, argv.mem) e.loaded = true e.Value = constant.MakeInt64(int64(ch)) v.Children = append(v.Children, *e) @@ -536,7 +499,7 @@ func (scope *EvalScope) evalToplevelTypeCast(t ast.Expr, cfg LoadConfig) (*Varia return nil, converr } for i, ch := range constant.StringVal(argv.Value) { - e := scope.newVariable("", argv.Addr+uintptr(i), targetType.(*godwarf.SliceType).ElemType, argv.mem) + e := newVariable("", argv.Addr+uintptr(i), targetType.(*godwarf.SliceType).ElemType, scope.BinInfo, argv.mem) e.loaded = true e.Value = constant.MakeInt64(int64(ch)) v.Children = append(v.Children, *e) @@ -741,7 +704,7 @@ func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) { n, _ := constant.Int64Val(argv.Value) - v.Children = []Variable{*(scope.newVariable("", uintptr(n), ttyp.Type, scope.Mem))} + v.Children = []Variable{*(newVariable("", uintptr(n), ttyp.Type, scope.BinInfo, scope.Mem))} return v, nil case *godwarf.UintType: diff --git a/pkg/proc/fncall.go b/pkg/proc/fncall.go index 6b86518b..f9ab607e 100644 --- a/pkg/proc/fncall.go +++ b/pkg/proc/fncall.go @@ -315,7 +315,7 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) { } switch len(fncall.retvars) { case 0: - r := scope.newVariable("", 0, nil, nil) + r := newVariable("", 0, nil, scope.BinInfo, nil) r.loaded = true r.Unreadable = errors.New("no return values") return r, nil @@ -323,7 +323,7 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) { return fncall.retvars[0], nil default: // create a fake variable without address or type to return multiple values - r := scope.newVariable("", 0, nil, nil) + r := newVariable("", 0, nil, scope.BinInfo, nil) r.loaded = true r.Children = make([]Variable, len(fncall.retvars)) for i := range fncall.retvars { @@ -778,7 +778,7 @@ func readTopstackVariable(thread Thread, regs Registers, typename string, loadCf if err != nil { return nil, err } - v := scope.newVariable("", uintptr(regs.SP()), typ, scope.Mem) + v := newVariable("", uintptr(regs.SP()), typ, scope.BinInfo, scope.Mem) v.loadValue(loadCfg) if v.Unreadable != nil { return nil, v.Unreadable diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index d12b346d..eb7d1d29 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -812,6 +812,44 @@ func readVarEntry(varEntry *dwarf.Entry, image *Image) (entry reader.Entry, name return entry, name, typ, nil } +// Extracts the name and type of a variable from a dwarf entry +// then executes the instructions given in the DW_AT_location attribute to grab the variable's address +func extractVarInfoFromEntry(bi *BinaryInfo, image *Image, regs op.DwarfRegisters, mem MemoryReadWriter, varEntry *dwarf.Entry) (*Variable, error) { + if varEntry == nil { + return nil, fmt.Errorf("invalid entry") + } + + if varEntry.Tag != dwarf.TagFormalParameter && varEntry.Tag != dwarf.TagVariable { + return nil, fmt.Errorf("invalid entry tag, only supports FormalParameter and Variable, got %s", varEntry.Tag.String()) + } + + entry, n, t, err := readVarEntry(varEntry, image) + if err != nil { + return nil, err + } + + addr, pieces, descr, err := bi.Location(entry, dwarf.AttrLocation, regs.PC(), regs) + if pieces != nil { + addr = fakeAddress + var cmem *compositeMemory + cmem, err = newCompositeMemory(mem, regs, pieces) + if cmem != nil { + mem = cmem + } + } + + v := newVariable(n, uintptr(addr), t, bi, mem) + if pieces != nil { + v.Flags |= VariableFakeAddress + } + v.LocationExpr = descr + v.DeclLine, _ = entry.Val(dwarf.AttrDeclLine).(int64) + if err != nil { + v.Unreadable = err + } + return v, nil +} + // If v is a pointer a new variable is returned containing the value pointed by v. func (v *Variable) maybeDereference() *Variable { if v.Unreadable != nil {