// 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:])
		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:]
		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:]
		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()
}
