// 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/elf";
	"debug/gosym";
	"debug/proc";
	"exp/eval";
	"fmt";
	"log";
	"os";
	"reflect";
)

// A FormatError indicates a failure to process information in or
// about a remote process, such as unexpected or missing information
// in the object file or runtime structures.
type FormatError string

func (e FormatError) String() string	{ return string(e) }

// An UnknownArchitecture occurs when trying to load an object file
// that indicates an architecture not supported by the debugger.
type UnknownArchitecture elf.Machine

func (e UnknownArchitecture) String() string {
	return "unknown architecture: " + elf.Machine(e).String()
}

// A ProcessNotStopped error occurs when attempting to read or write
// memory or registers of a process that is not stopped.
type ProcessNotStopped struct{}

func (e ProcessNotStopped) String() string	{ return "process not stopped" }

// An UnknownGoroutine error is an internal error representing an
// unrecognized G structure pointer.
type UnknownGoroutine struct {
	OSThread	proc.Thread;
	Goroutine	proc.Word;
}

func (e UnknownGoroutine) String() string {
	return fmt.Sprintf("internal error: unknown goroutine (G %#x)", e.Goroutine)
}

// A NoCurrentGoroutine error occurs when no goroutine is currently
// selected in a process (or when there are no goroutines in a
// process).
type NoCurrentGoroutine struct{}

func (e NoCurrentGoroutine) String() string	{ return "no current goroutine" }

// A Process represents a remote attached process.
type Process struct {
	Arch;
	proc	proc.Process;

	// The symbol table of this process
	syms	*gosym.Table;

	// A possibly-stopped OS thread, or nil
	threadCache	proc.Thread;

	// Types parsed from the remote process
	types	map[proc.Word]*remoteType;

	// Types and values from the remote runtime package
	runtime	runtimeValues;

	// Runtime field indexes
	f	runtimeIndexes;

	// Globals from the sys package (or from no package)
	sys	struct {
		lessstack, goexit, newproc, deferproc, newprocreadylocked	*gosym.Func;
		allg								remotePtr;
		g0								remoteStruct;
	};

	// Event queue
	posted	[]Event;
	pending	[]Event;
	event	Event;

	// Event hooks
	breakpointHooks		map[proc.Word]*breakpointHook;
	goroutineCreateHook	*goroutineCreateHook;
	goroutineExitHook	*goroutineExitHook;

	// Current goroutine, or nil if there are no goroutines
	curGoroutine	*Goroutine;

	// Goroutines by the address of their G structure
	goroutines	map[proc.Word]*Goroutine;
}

/*
 * Process creation
 */

// NewProcess constructs a new remote process around a traced
// process, an architecture, and a symbol table.
func NewProcess(tproc proc.Process, arch Arch, syms *gosym.Table) (*Process, os.Error) {
	p := &Process{
		Arch: arch,
		proc: tproc,
		syms: syms,
		types: make(map[proc.Word]*remoteType),
		breakpointHooks: make(map[proc.Word]*breakpointHook),
		goroutineCreateHook: new(goroutineCreateHook),
		goroutineExitHook: new(goroutineExitHook),
		goroutines: make(map[proc.Word]*Goroutine),
	};

	// Fill in remote runtime
	p.bootstrap();

	switch {
	case p.sys.allg.addr().base == 0:
		return nil, FormatError("failed to find runtime symbol 'allg'")
	case p.sys.g0.addr().base == 0:
		return nil, FormatError("failed to find runtime symbol 'g0'")
	case p.sys.newprocreadylocked == nil:
		return nil, FormatError("failed to find runtime symbol 'newprocreadylocked'")
	case p.sys.goexit == nil:
		return nil, FormatError("failed to find runtime symbol 'sys.goexit'")
	}

	// Get current goroutines
	p.goroutines[p.sys.g0.addr().base] = &Goroutine{p.sys.g0, nil, false};
	err := try(func(a aborter) {
		g := p.sys.allg.aGet(a);
		for g != nil {
			gs := g.(remoteStruct);
			fmt.Printf("*** Found goroutine at %#x\n", gs.addr().base);
			p.goroutines[gs.addr().base] = &Goroutine{gs, nil, false};
			g = gs.field(p.f.G.Alllink).(remotePtr).aGet(a);
		}
	});
	if err != nil {
		return nil, err
	}

	// Create internal breakpoints to catch new and exited goroutines
	p.OnBreakpoint(proc.Word(p.sys.newprocreadylocked.Entry)).(*breakpointHook).addHandler(readylockedBP, true);
	p.OnBreakpoint(proc.Word(p.sys.goexit.Entry)).(*breakpointHook).addHandler(goexitBP, true);

	// Select current frames
	for _, g := range p.goroutines {
		g.resetFrame()
	}

	p.selectSomeGoroutine();

	return p, nil;
}

func elfGoSyms(f *elf.File) (*gosym.Table, os.Error) {
	text := f.Section(".text");
	symtab := f.Section(".gosymtab");
	pclntab := f.Section(".gopclntab");
	if text == nil || symtab == nil || pclntab == nil {
		return nil, nil
	}

	symdat, err := symtab.Data();
	if err != nil {
		return nil, err
	}
	pclndat, err := pclntab.Data();
	if err != nil {
		return nil, err
	}

	pcln := gosym.NewLineTable(pclndat, text.Addr);
	tab, err := gosym.NewTable(symdat, pcln);
	if err != nil {
		return nil, err
	}

	return tab, nil;
}

// NewProcessElf constructs a new remote process around a traced
// process and the process' ELF object.
func NewProcessElf(tproc proc.Process, f *elf.File) (*Process, os.Error) {
	syms, err := elfGoSyms(f);
	if err != nil {
		return nil, err
	}
	if syms == nil {
		return nil, FormatError("Failed to find symbol table")
	}
	var arch Arch;
	switch f.Machine {
	case elf.EM_X86_64:
		arch = Amd64
	default:
		return nil, UnknownArchitecture(f.Machine)
	}
	return NewProcess(tproc, arch, syms);
}

// bootstrap constructs the runtime structure of a remote process.
func (p *Process) bootstrap() {
	// Manually construct runtime types
	p.runtime.String = newManualType(eval.TypeOfNative(rt1String{}), p.Arch);
	p.runtime.Slice = newManualType(eval.TypeOfNative(rt1Slice{}), p.Arch);
	p.runtime.Eface = newManualType(eval.TypeOfNative(rt1Eface{}), p.Arch);

	p.runtime.Type = newManualType(eval.TypeOfNative(rt1Type{}), p.Arch);
	p.runtime.CommonType = newManualType(eval.TypeOfNative(rt1CommonType{}), p.Arch);
	p.runtime.UncommonType = newManualType(eval.TypeOfNative(rt1UncommonType{}), p.Arch);
	p.runtime.StructField = newManualType(eval.TypeOfNative(rt1StructField{}), p.Arch);
	p.runtime.StructType = newManualType(eval.TypeOfNative(rt1StructType{}), p.Arch);
	p.runtime.PtrType = newManualType(eval.TypeOfNative(rt1PtrType{}), p.Arch);
	p.runtime.ArrayType = newManualType(eval.TypeOfNative(rt1ArrayType{}), p.Arch);
	p.runtime.SliceType = newManualType(eval.TypeOfNative(rt1SliceType{}), p.Arch);

	p.runtime.Stktop = newManualType(eval.TypeOfNative(rt1Stktop{}), p.Arch);
	p.runtime.Gobuf = newManualType(eval.TypeOfNative(rt1Gobuf{}), p.Arch);
	p.runtime.G = newManualType(eval.TypeOfNative(rt1G{}), p.Arch);

	// Get addresses of type.*runtime.XType for discrimination.
	rtv := reflect.Indirect(reflect.NewValue(&p.runtime)).(*reflect.StructValue);
	rtvt := rtv.Type().(*reflect.StructType);
	for i := 0; i < rtv.NumField(); i++ {
		n := rtvt.Field(i).Name;
		if n[0] != 'P' || n[1] < 'A' || n[1] > 'Z' {
			continue
		}
		sym := p.syms.LookupSym("type.*runtime." + n[1:len(n)]);
		if sym == nil {
			continue
		}
		rtv.Field(i).(*reflect.Uint64Value).Set(sym.Value);
	}

	// Get runtime field indexes
	fillRuntimeIndexes(&p.runtime, &p.f);

	// Fill G status
	p.runtime.runtimeGStatus = rt1GStatus;

	// Get globals
	p.sys.lessstack = p.syms.LookupFunc("sys.lessstack");
	p.sys.goexit = p.syms.LookupFunc("goexit");
	p.sys.newproc = p.syms.LookupFunc("sys.newproc");
	p.sys.deferproc = p.syms.LookupFunc("sys.deferproc");
	p.sys.newprocreadylocked = p.syms.LookupFunc("newprocreadylocked");
	if allg := p.syms.LookupSym("allg"); allg != nil {
		p.sys.allg = remotePtr{remote{proc.Word(allg.Value), p}, p.runtime.G}
	}
	if g0 := p.syms.LookupSym("g0"); g0 != nil {
		p.sys.g0 = p.runtime.G.mk(remote{proc.Word(g0.Value), p}).(remoteStruct)
	}
}

func (p *Process) selectSomeGoroutine() {
	// Once we have friendly goroutine ID's, there might be a more
	// reasonable behavior for this.
	p.curGoroutine = nil;
	for _, g := range p.goroutines {
		if !g.isG0() && g.frame != nil {
			p.curGoroutine = g;
			return;
		}
	}
}

/*
 * Process memory
 */

func (p *Process) someStoppedOSThread() proc.Thread {
	if p.threadCache != nil {
		if _, err := p.threadCache.Stopped(); err == nil {
			return p.threadCache
		}
	}

	for _, t := range p.proc.Threads() {
		if _, err := t.Stopped(); err == nil {
			p.threadCache = t;
			return t;
		}
	}
	return nil;
}

func (p *Process) Peek(addr proc.Word, out []byte) (int, os.Error) {
	thr := p.someStoppedOSThread();
	if thr == nil {
		return 0, ProcessNotStopped{}
	}
	return thr.Peek(addr, out);
}

func (p *Process) Poke(addr proc.Word, b []byte) (int, os.Error) {
	thr := p.someStoppedOSThread();
	if thr == nil {
		return 0, ProcessNotStopped{}
	}
	return thr.Poke(addr, b);
}

func (p *Process) peekUintptr(a aborter, addr proc.Word) proc.Word {
	return proc.Word(mkUintptr(remote{addr, p}).(remoteUint).aGet(a))
}

/*
 * Events
 */

// OnBreakpoint returns the hook that is run when the program reaches
// the given program counter.
func (p *Process) OnBreakpoint(pc proc.Word) EventHook {
	if bp, ok := p.breakpointHooks[pc]; ok {
		return bp
	}
	// The breakpoint will register itself when a handler is added
	return &breakpointHook{commonHook{nil, 0}, p, pc};
}

// OnGoroutineCreate returns the hook that is run when a goroutine is created.
func (p *Process) OnGoroutineCreate() EventHook {
	return p.goroutineCreateHook
}

// OnGoroutineExit returns the hook that is run when a goroutine exits.
func (p *Process) OnGoroutineExit() EventHook	{ return p.goroutineExitHook }

// osThreadToGoroutine looks up the goroutine running on an OS thread.
func (p *Process) osThreadToGoroutine(t proc.Thread) (*Goroutine, os.Error) {
	regs, err := t.Regs();
	if err != nil {
		return nil, err
	}
	g := p.G(regs);
	gt, ok := p.goroutines[g];
	if !ok {
		return nil, UnknownGoroutine{t, g}
	}
	return gt, nil;
}

// causesToEvents translates the stop causes of the underlying process
// into an event queue.
func (p *Process) causesToEvents() ([]Event, os.Error) {
	// Count causes we're interested in
	nev := 0;
	for _, t := range p.proc.Threads() {
		if c, err := t.Stopped(); err == nil {
			switch c := c.(type) {
			case proc.Breakpoint:
				nev++
			case proc.Signal:
				// TODO(austin)
				//nev++;
			}
		}
	}

	// Translate causes to events
	events := make([]Event, nev);
	i := 0;
	for _, t := range p.proc.Threads() {
		if c, err := t.Stopped(); err == nil {
			switch c := c.(type) {
			case proc.Breakpoint:
				gt, err := p.osThreadToGoroutine(t);
				if err != nil {
					return nil, err
				}
				events[i] = &Breakpoint{commonEvent{p, gt}, t, proc.Word(c)};
				i++;
			case proc.Signal:
				// TODO(austin)
			}
		}
	}

	return events, nil;
}

// postEvent appends an event to the posted queue.  These events will
// be processed before any currently pending events.
func (p *Process) postEvent(ev Event) {
	n := len(p.posted);
	m := n * 2;
	if m == 0 {
		m = 4
	}
	posted := make([]Event, n+1, m);
	for i, p := range p.posted {
		posted[i] = p
	}
	posted[n] = ev;
	p.posted = posted;
}

// processEvents processes events in the event queue until no events
// remain, a handler returns EAStop, or a handler returns an error.
// It returns either EAStop or EAContinue and possibly an error.
func (p *Process) processEvents() (EventAction, os.Error) {
	var ev Event;
	for len(p.posted) > 0 {
		ev, p.posted = p.posted[0], p.posted[1:len(p.posted)];
		action, err := p.processEvent(ev);
		if action == EAStop {
			return action, err
		}
	}

	for len(p.pending) > 0 {
		ev, p.pending = p.pending[0], p.pending[1:len(p.pending)];
		action, err := p.processEvent(ev);
		if action == EAStop {
			return action, err
		}
	}

	return EAContinue, nil;
}

// processEvent processes a single event, without manipulating the
// event queues.  It returns either EAStop or EAContinue and possibly
// an error.
func (p *Process) processEvent(ev Event) (EventAction, os.Error) {
	p.event = ev;

	var action EventAction;
	var err os.Error;
	switch ev := p.event.(type) {
	case *Breakpoint:
		hook, ok := p.breakpointHooks[ev.pc];
		if !ok {
			break
		}
		p.curGoroutine = ev.Goroutine();
		action, err = hook.handle(ev);

	case *GoroutineCreate:
		p.curGoroutine = ev.Goroutine();
		action, err = p.goroutineCreateHook.handle(ev);

	case *GoroutineExit:
		action, err = p.goroutineExitHook.handle(ev)

	default:
		log.Crashf("Unknown event type %T in queue", p.event)
	}

	if err != nil {
		return EAStop, err
	} else if action == EAStop {
		return EAStop, nil
	}
	return EAContinue, nil;
}

// Event returns the last event that caused the process to stop.  This
// may return nil if the process has never been stopped by an event.
//
// TODO(austin) Return nil if the user calls p.Stop()?
func (p *Process) Event() Event	{ return p.event }

/*
 * Process control
 */

// TODO(austin) Cont, WaitStop, and Stop.  Need to figure out how
// event handling works with these.  Originally I did it only in
// WaitStop, but if you Cont and there are pending events, then you
// have to not actually continue and wait until a WaitStop to process
// them, even if the event handlers will tell you to continue.  We
// could handle them in both Cont and WaitStop to avoid this problem,
// but it's still weird if an event happens after the Cont and before
// the WaitStop that the handlers say to continue from.  Or we could
// handle them on a separate thread.  Then obviously you get weird
// asynchronous things, like prints while the user it typing a command,
// but that's not necessarily a bad thing.

// ContWait resumes process execution and waits for an event to occur
// that stops the process.
func (p *Process) ContWait() os.Error {
	for {
		a, err := p.processEvents();
		if err != nil {
			return err
		} else if a == EAStop {
			break
		}
		err = p.proc.Continue();
		if err != nil {
			return err
		}
		err = p.proc.WaitStop();
		if err != nil {
			return err
		}
		for _, g := range p.goroutines {
			g.resetFrame()
		}
		p.pending, err = p.causesToEvents();
		if err != nil {
			return err
		}
	}
	return nil;
}

// Out selects the caller frame of the current frame.
func (p *Process) Out() os.Error {
	if p.curGoroutine == nil {
		return NoCurrentGoroutine{}
	}
	return p.curGoroutine.Out();
}

// In selects the frame called by the current frame.
func (p *Process) In() os.Error {
	if p.curGoroutine == nil {
		return NoCurrentGoroutine{}
	}
	return p.curGoroutine.In();
}
