// 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);
}
