From cf37512aed935c6ce497ca14440d5c80231f0e8a Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 22 Apr 2020 16:39:06 +0200 Subject: [PATCH] proc: move g.stackhi/g.stacklo to a struct Mirroring the way this is implemented in the Go runtime and introducing a type that will be useful to support the call injection changes in Go 1.15 --- pkg/proc/breakpoints.go | 4 ++-- pkg/proc/fncall.go | 18 +++++++++--------- pkg/proc/stack.go | 4 ++-- pkg/proc/variables.go | 11 +++++++---- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/pkg/proc/breakpoints.go b/pkg/proc/breakpoints.go index f3fcfb50..3e01bea5 100644 --- a/pkg/proc/breakpoints.go +++ b/pkg/proc/breakpoints.go @@ -436,8 +436,8 @@ func (rbpi *returnBreakpointInfo) Collect(thread Thread) []*Variable { return nil } - oldFrameOffset := rbpi.frameOffset + int64(g.stackhi) - oldSP := uint64(rbpi.spOffset + int64(g.stackhi)) + oldFrameOffset := rbpi.frameOffset + int64(g.stack.hi) + oldSP := uint64(rbpi.spOffset + int64(g.stack.hi)) err = fakeFunctionEntryScope(scope, rbpi.fn, oldFrameOffset, oldSP) if err != nil { return returnInfoError("could not read function entry", err, thread) diff --git a/pkg/proc/fncall.go b/pkg/proc/fncall.go index eac9c2fa..26d0a756 100644 --- a/pkg/proc/fncall.go +++ b/pkg/proc/fncall.go @@ -257,7 +257,7 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) { return nil, err } regs = regs.Copy() - if regs.SP()-256 <= scope.g.stacklo { + if regs.SP()-256 <= scope.g.stack.lo { return nil, errNotEnoughStack } _, err = regs.Get(int(x86asm.RAX)) @@ -285,9 +285,9 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) { fncallLog("function call initiated %v frame size %d", fncall.fn, fncall.argFrameSize) - spoff := int64(scope.Regs.Uint64Val(scope.Regs.SPRegNum)) - int64(scope.g.stackhi) - bpoff := int64(scope.Regs.Uint64Val(scope.Regs.BPRegNum)) - int64(scope.g.stackhi) - fboff := scope.Regs.FrameBase - int64(scope.g.stackhi) + spoff := int64(scope.Regs.Uint64Val(scope.Regs.SPRegNum)) - int64(scope.g.stack.hi) + bpoff := int64(scope.Regs.Uint64Val(scope.Regs.BPRegNum)) - int64(scope.g.stack.hi) + fboff := scope.Regs.FrameBase - int64(scope.g.stack.hi) for { scope.g = scope.callCtx.doContinue() @@ -303,10 +303,10 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) { } } - scope.Regs.Regs[scope.Regs.SPRegNum].Uint64Val = uint64(spoff + int64(scope.g.stackhi)) - scope.Regs.Regs[scope.Regs.BPRegNum].Uint64Val = uint64(bpoff + int64(scope.g.stackhi)) - scope.Regs.FrameBase = fboff + int64(scope.g.stackhi) - scope.Regs.CFA = scope.frameOffset + int64(scope.g.stackhi) + scope.Regs.Regs[scope.Regs.SPRegNum].Uint64Val = uint64(spoff + int64(scope.g.stack.hi)) + scope.Regs.Regs[scope.Regs.BPRegNum].Uint64Val = uint64(bpoff + int64(scope.g.stack.hi)) + scope.Regs.FrameBase = fboff + int64(scope.g.stack.hi) + scope.Regs.CFA = scope.frameOffset + int64(scope.g.stack.hi) finished := funcCallStep(scope, &fncall) if finished { @@ -635,7 +635,7 @@ func escapeCheck(v *Variable, name string, g *G) error { } func escapeCheckPointer(addr uintptr, name string, g *G) error { - if uint64(addr) >= g.stacklo && uint64(addr) < g.stackhi { + if uint64(addr) >= g.stack.lo && uint64(addr) < g.stack.hi { return fmt.Errorf("stack object passed to escaping pointer: %s", name) } return nil diff --git a/pkg/proc/stack.go b/pkg/proc/stack.go index 27be3c76..907d2d56 100644 --- a/pkg/proc/stack.go +++ b/pkg/proc/stack.go @@ -122,13 +122,13 @@ func (g *G) stackIterator(opts StacktraceOptions) (*stackIterator, error) { return newStackIterator( bi, g.Thread, bi.Arch.RegistersToDwarfRegisters(so.StaticBase, regs), - g.stackhi, stkbar, g.stkbarPos, g, opts), nil + g.stack.hi, stkbar, g.stkbarPos, g, opts), nil } so := g.variable.bi.PCToImage(g.PC) return newStackIterator( bi, g.variable.mem, bi.Arch.addrAndStackRegsToDwarfRegisters(so.StaticBase, g.PC, g.SP, g.BP, g.LR), - g.stackhi, stkbar, g.stkbarPos, g, opts), nil + g.stack.hi, stkbar, g.stkbarPos, g, opts), nil } type StacktraceOptions uint16 diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index dfc1a58b..7453ba26 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -195,8 +195,7 @@ type G struct { Status uint64 stkbarVar *Variable // stkbar field of g struct stkbarPos int // stkbarPos field of g struct - stackhi uint64 // value of stack.hi - stacklo uint64 // value of stack.lo + stack stack // value of stack SystemStack bool // SystemStack is true if this goroutine is currently executing on a system stack. @@ -213,6 +212,11 @@ type G struct { labels *map[string]string // G's pprof labels, computed on demand in Labels() method } +// stack represents a stack span in the target process. +type stack struct { + hi, lo uint64 +} + // GetG returns information on the G (goroutine) that is executing on this thread. // // The G structure for a thread is stored in thread local storage. Here we simply @@ -862,8 +866,7 @@ func (v *Variable) parseG() (*G, error) { variable: v, stkbarVar: stkbarVar, stkbarPos: int(stkbarPos), - stackhi: stackhi, - stacklo: stacklo, + stack: stack{hi: stackhi, lo: stacklo}, } return g, nil }