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
This commit is contained in:
aarzilli 2020-04-22 16:39:06 +02:00 committed by Derek Parker
parent bb2525a7d5
commit cf37512aed
4 changed files with 20 additions and 17 deletions

@ -436,8 +436,8 @@ func (rbpi *returnBreakpointInfo) Collect(thread Thread) []*Variable {
return nil return nil
} }
oldFrameOffset := rbpi.frameOffset + int64(g.stackhi) oldFrameOffset := rbpi.frameOffset + int64(g.stack.hi)
oldSP := uint64(rbpi.spOffset + int64(g.stackhi)) oldSP := uint64(rbpi.spOffset + int64(g.stack.hi))
err = fakeFunctionEntryScope(scope, rbpi.fn, oldFrameOffset, oldSP) err = fakeFunctionEntryScope(scope, rbpi.fn, oldFrameOffset, oldSP)
if err != nil { if err != nil {
return returnInfoError("could not read function entry", err, thread) return returnInfoError("could not read function entry", err, thread)

@ -257,7 +257,7 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
return nil, err return nil, err
} }
regs = regs.Copy() regs = regs.Copy()
if regs.SP()-256 <= scope.g.stacklo { if regs.SP()-256 <= scope.g.stack.lo {
return nil, errNotEnoughStack return nil, errNotEnoughStack
} }
_, err = regs.Get(int(x86asm.RAX)) _, 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) fncallLog("function call initiated %v frame size %d", fncall.fn, fncall.argFrameSize)
spoff := int64(scope.Regs.Uint64Val(scope.Regs.SPRegNum)) - 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.stackhi) bpoff := int64(scope.Regs.Uint64Val(scope.Regs.BPRegNum)) - int64(scope.g.stack.hi)
fboff := scope.Regs.FrameBase - int64(scope.g.stackhi) fboff := scope.Regs.FrameBase - int64(scope.g.stack.hi)
for { for {
scope.g = scope.callCtx.doContinue() 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.SPRegNum].Uint64Val = uint64(spoff + int64(scope.g.stack.hi))
scope.Regs.Regs[scope.Regs.BPRegNum].Uint64Val = uint64(bpoff + int64(scope.g.stackhi)) scope.Regs.Regs[scope.Regs.BPRegNum].Uint64Val = uint64(bpoff + int64(scope.g.stack.hi))
scope.Regs.FrameBase = fboff + int64(scope.g.stackhi) scope.Regs.FrameBase = fboff + int64(scope.g.stack.hi)
scope.Regs.CFA = scope.frameOffset + int64(scope.g.stackhi) scope.Regs.CFA = scope.frameOffset + int64(scope.g.stack.hi)
finished := funcCallStep(scope, &fncall) finished := funcCallStep(scope, &fncall)
if finished { if finished {
@ -635,7 +635,7 @@ func escapeCheck(v *Variable, name string, g *G) error {
} }
func escapeCheckPointer(addr uintptr, 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 fmt.Errorf("stack object passed to escaping pointer: %s", name)
} }
return nil return nil

@ -122,13 +122,13 @@ func (g *G) stackIterator(opts StacktraceOptions) (*stackIterator, error) {
return newStackIterator( return newStackIterator(
bi, g.Thread, bi, g.Thread,
bi.Arch.RegistersToDwarfRegisters(so.StaticBase, regs), 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) so := g.variable.bi.PCToImage(g.PC)
return newStackIterator( return newStackIterator(
bi, g.variable.mem, bi, g.variable.mem,
bi.Arch.addrAndStackRegsToDwarfRegisters(so.StaticBase, g.PC, g.SP, g.BP, g.LR), 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 type StacktraceOptions uint16

@ -195,8 +195,7 @@ type G struct {
Status uint64 Status uint64
stkbarVar *Variable // stkbar field of g struct stkbarVar *Variable // stkbar field of g struct
stkbarPos int // stkbarPos field of g struct stkbarPos int // stkbarPos field of g struct
stackhi uint64 // value of stack.hi stack stack // value of stack
stacklo uint64 // value of stack.lo
SystemStack bool // SystemStack is true if this goroutine is currently executing on a system 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 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. // 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 // 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, variable: v,
stkbarVar: stkbarVar, stkbarVar: stkbarVar,
stkbarPos: int(stkbarPos), stkbarPos: int(stkbarPos),
stackhi: stackhi, stack: stack{hi: stackhi, lo: stacklo},
stacklo: stacklo,
} }
return g, nil return g, nil
} }