diff options
Diffstat (limited to 'src/pkg/exp/ogle/frame.go')
-rw-r--r-- | src/pkg/exp/ogle/frame.go | 212 |
1 files changed, 0 insertions, 212 deletions
diff --git a/src/pkg/exp/ogle/frame.go b/src/pkg/exp/ogle/frame.go deleted file mode 100644 index 1538362ba..000000000 --- a/src/pkg/exp/ogle/frame.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ogle - -import ( - "debug/gosym" - "debug/proc" - "fmt" - "os" -) - -// A Frame represents a single frame on a remote call stack. -type Frame struct { - // pc is the PC of the next instruction that will execute in - // this frame. For lower frames, this is the instruction - // following the CALL instruction. - pc, sp, fp proc.Word - // The runtime.Stktop of the active stack segment - stk remoteStruct - // The function this stack frame is in - fn *gosym.Func - // The path and line of the CALL or current instruction. Note - // that this differs slightly from the meaning of Frame.pc. - path string - line int - // The inner and outer frames of this frame. outer is filled - // in lazily. - inner, outer *Frame -} - -// newFrame returns the top-most Frame of the given g's thread. -func newFrame(g remoteStruct) (*Frame, os.Error) { - var f *Frame - err := try(func(a aborter) { f = aNewFrame(a, g) }) - return f, err -} - -func aNewFrame(a aborter, g remoteStruct) *Frame { - p := g.r.p - var pc, sp proc.Word - - // Is this G alive? - switch g.field(p.f.G.Status).(remoteInt).aGet(a) { - case p.runtime.Gidle, p.runtime.Gmoribund, p.runtime.Gdead: - return nil - } - - // Find the OS thread for this G - - // TODO(austin) Ideally, we could look at the G's state and - // figure out if it's on an OS thread or not. However, this - // is difficult because the state isn't updated atomically - // with scheduling changes. - for _, t := range p.proc.Threads() { - regs, err := t.Regs() - if err != nil { - // TODO(austin) What to do? - continue - } - thisg := p.G(regs) - if thisg == g.addr().base { - // Found this G's OS thread - pc = regs.PC() - sp = regs.SP() - - // If this thread crashed, try to recover it - if pc == 0 { - pc = p.peekUintptr(a, pc) - sp += 8 - } - - break - } - } - - if pc == 0 && sp == 0 { - // G is not mapped to an OS thread. Use the - // scheduler's stored PC and SP. - sched := g.field(p.f.G.Sched).(remoteStruct) - pc = proc.Word(sched.field(p.f.Gobuf.Pc).(remoteUint).aGet(a)) - sp = proc.Word(sched.field(p.f.Gobuf.Sp).(remoteUint).aGet(a)) - } - - // Get Stktop - stk := g.field(p.f.G.Stackbase).(remotePtr).aGet(a).(remoteStruct) - - return prepareFrame(a, pc, sp, stk, nil) -} - -// prepareFrame creates a Frame from the PC and SP within that frame, -// as well as the active stack segment. This function takes care of -// traversing stack breaks and unwinding closures. -func prepareFrame(a aborter, pc, sp proc.Word, stk remoteStruct, inner *Frame) *Frame { - // Based on src/pkg/runtime/amd64/traceback.c:traceback - p := stk.r.p - top := inner == nil - - // Get function - var path string - var line int - var fn *gosym.Func - - for i := 0; i < 100; i++ { - // Traverse segmented stack breaks - if p.sys.lessstack != nil && pc == proc.Word(p.sys.lessstack.Value) { - // Get stk->gobuf.pc - pc = proc.Word(stk.field(p.f.Stktop.Gobuf).(remoteStruct).field(p.f.Gobuf.Pc).(remoteUint).aGet(a)) - // Get stk->gobuf.sp - sp = proc.Word(stk.field(p.f.Stktop.Gobuf).(remoteStruct).field(p.f.Gobuf.Sp).(remoteUint).aGet(a)) - // Get stk->stackbase - stk = stk.field(p.f.Stktop.Stackbase).(remotePtr).aGet(a).(remoteStruct) - continue - } - - // Get the PC of the call instruction - callpc := pc - if !top && (p.sys.goexit == nil || pc != proc.Word(p.sys.goexit.Value)) { - callpc-- - } - - // Look up function - path, line, fn = p.syms.PCToLine(uint64(callpc)) - if fn != nil { - break - } - - // Closure? - var buf = make([]byte, p.ClosureSize()) - if _, err := p.Peek(pc, buf); err != nil { - break - } - spdelta, ok := p.ParseClosure(buf) - if ok { - sp += proc.Word(spdelta) - pc = p.peekUintptr(a, sp-proc.Word(p.PtrSize())) - } - } - if fn == nil { - return nil - } - - // Compute frame pointer - var fp proc.Word - if fn.FrameSize < p.PtrSize() { - fp = sp + proc.Word(p.PtrSize()) - } else { - fp = sp + proc.Word(fn.FrameSize) - } - // TODO(austin) To really figure out if we're in the prologue, - // we need to disassemble the function and look for the call - // to morestack. For now, just special case the entry point. - // - // TODO(austin) What if we're in the call to morestack in the - // prologue? Then top == false. - if top && pc == proc.Word(fn.Entry) { - // We're in the function prologue, before SP - // has been adjusted for the frame. - fp -= proc.Word(fn.FrameSize - p.PtrSize()) - } - - return &Frame{pc, sp, fp, stk, fn, path, line, inner, nil} -} - -// Outer returns the Frame that called this Frame, or nil if this is -// the outermost frame. -func (f *Frame) Outer() (*Frame, os.Error) { - var fr *Frame - err := try(func(a aborter) { fr = f.aOuter(a) }) - return fr, err -} - -func (f *Frame) aOuter(a aborter) *Frame { - // Is there a cached outer frame - if f.outer != nil { - return f.outer - } - - p := f.stk.r.p - - sp := f.fp - if f.fn == p.sys.newproc && f.fn == p.sys.deferproc { - // TODO(rsc) The compiler inserts two push/pop's - // around calls to go and defer. Russ says this - // should get fixed in the compiler, but we account - // for it for now. - sp += proc.Word(2 * p.PtrSize()) - } - - pc := p.peekUintptr(a, f.fp-proc.Word(p.PtrSize())) - if pc < 0x1000 { - return nil - } - - // TODO(austin) Register this frame for shoot-down. - - f.outer = prepareFrame(a, pc, sp, f.stk, f) - return f.outer -} - -// Inner returns the Frame called by this Frame, or nil if this is the -// innermost frame. -func (f *Frame) Inner() *Frame { return f.inner } - -func (f *Frame) String() string { - res := f.fn.Name - if f.pc > proc.Word(f.fn.Value) { - res += fmt.Sprintf("+%#x", f.pc-proc.Word(f.fn.Entry)) - } - return res + fmt.Sprintf(" %s:%d", f.path, f.line) -} |