// Copyright 2017 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 gocore

import (
	"fmt"
	"sort"

	"golang.org/x/debug/core"
)

type module struct {
	r             region       // inferior region holding a runtime.moduledata
	types, etypes core.Address // range that holds all the runtime._type data in this module
}

func (p *Process) readModules() {
	// Note: the cast is necessary for cores generated by Go 1.9, where
	// runtime.moduledata is just an unsafe.Pointer.
	ms := p.rtGlobals["modulesSlice"].Cast("*[]*runtime.moduledata").Deref()
	n := ms.SliceLen()
	for i := int64(0); i < n; i++ {
		md := ms.SliceIndex(i).Deref()
		p.modules = append(p.modules, p.readModule(md))
	}
	p.funcTab.sort()
}

func (p *Process) readModule(r region) *module {
	m := &module{r: r}
	m.types = core.Address(r.Field("types").Uintptr())
	m.etypes = core.Address(r.Field("etypes").Uintptr())

	// Read the pc->function table
	pcln := r.Field("pclntable")
	ftab := r.Field("ftab")
	n := ftab.SliceLen() - 1 // last slot is a dummy, just holds entry
	for i := int64(0); i < n; i++ {
		ft := ftab.SliceIndex(i)
		min := core.Address(ft.Field("entry").Uintptr())
		max := core.Address(ftab.SliceIndex(i + 1).Field("entry").Uintptr())
		fr := pcln.SliceIndex(int64(ft.Field("funcoff").Uintptr())).Cast("runtime._func")
		f := m.readFunc(fr, pcln)
		if f.entry != min {
			panic(fmt.Errorf("entry %x and min %x don't match for %s", f.entry, min, f.name))
		}
		p.funcTab.add(min, max, f)
	}

	return m
}

// readFunc parses a runtime._func and returns a *Func.
// r must have type runtime._func.
// pcln must have type []byte and represent the module's pcln table region.
func (m *module) readFunc(r region, pcln region) *Func {
	f := &Func{module: m, r: r}
	f.entry = core.Address(r.Field("entry").Uintptr())
	f.name = r.p.proc.ReadCString(pcln.SliceIndex(int64(r.Field("nameoff").Int32())).a)
	f.frameSize.read(r.p.proc, pcln.SliceIndex(int64(r.Field("pcsp").Int32())).a)

	// Parse pcdata and funcdata, which are laid out beyond the end of the _func.
	a := r.a.Add(int64(r.p.findType("runtime._func").Size))
	n := r.Field("npcdata").Int32()
	for i := int32(0); i < n; i++ {
		f.pcdata = append(f.pcdata, r.p.proc.ReadInt32(a))
		a = a.Add(4)
	}
	a = a.Align(r.p.proc.PtrSize())
	n = r.Field("nfuncdata").Int32()
	for i := int32(0); i < n; i++ {
		f.funcdata = append(f.funcdata, r.p.proc.ReadPtr(a))
		a = a.Add(r.p.proc.PtrSize())
	}

	// Read pcln tables we need.
	if stackmap := int(r.p.rtConstants["_PCDATA_StackMapIndex"]); stackmap < len(f.pcdata) {
		f.stackMap.read(r.p.proc, pcln.SliceIndex(int64(f.pcdata[stackmap])).a)
	} else {
		f.stackMap.setEmpty()
	}

	return f
}

type funcTabEntry struct {
	min, max core.Address
	f        *Func
}

type funcTab struct {
	entries []funcTabEntry
}

// add records that PCs in the range [min,max) map to function f.
func (t *funcTab) add(min, max core.Address, f *Func) {
	t.entries = append(t.entries, funcTabEntry{min: min, max: max, f: f})
}

// sort must be called after all the adds, but before any find.
func (t *funcTab) sort() {
	sort.Slice(t.entries, func(i, j int) bool {
		return t.entries[i].min < t.entries[j].min
	})
}

// Finds a Func for the given address.  Sort must have been called already.
func (t *funcTab) find(pc core.Address) *Func {
	n := sort.Search(len(t.entries), func(i int) bool {
		return t.entries[i].max > pc
	})
	if n == len(t.entries) || pc < t.entries[n].min || pc >= t.entries[n].max {
		return nil
	}
	return t.entries[n].f
}

// a pcTab maps from an offset in a function to an int64.
type pcTab struct {
	entries []pcTabEntry
}

type pcTabEntry struct {
	bytes int64 // # of bytes this entry covers
	val   int64 // value over that range of bytes
}

// read parses a pctab from the core file at address data.
func (t *pcTab) read(core *core.Process, data core.Address) {
	var pcQuantum int64
	switch core.Arch() {
	case "386", "amd64", "amd64p32":
		pcQuantum = 1
	case "s390x":
		pcQuantum = 2
	case "arm", "arm64", "mips", "mipsle", "mips64", "mips64le", "ppc64", "ppc64le":
		pcQuantum = 4
	default:
		panic("unknown architecture " + core.Arch())
	}
	val := int64(-1)
	first := true
	for {
		// Advance value.
		v, n := readVarint(core, data)
		if v == 0 && !first {
			return
		}
		data = data.Add(n)
		if v&1 != 0 {
			val += ^(v >> 1)
		} else {
			val += v >> 1
		}

		// Advance pc.
		v, n = readVarint(core, data)
		data = data.Add(n)
		t.entries = append(t.entries, pcTabEntry{bytes: v * pcQuantum, val: val})
		first = false
	}
}

func (t *pcTab) setEmpty() {
	t.entries = []pcTabEntry{{bytes: 1<<63 - 1, val: -1}}
}

func (t *pcTab) find(off int64) int64 {
	for _, e := range t.entries {
		if off < e.bytes {
			return e.val
		}
		off -= e.bytes
	}
	panic("can't find pctab entry")
}

// readVarint reads a varint from the core file.
// val is the value, n is the number of bytes consumed.
func readVarint(core *core.Process, a core.Address) (val, n int64) {
	for {
		b := core.ReadUint8(a)
		val |= int64(b&0x7f) << uint(n*7)
		n++
		a++
		if b&0x80 == 0 {
			return
		}
	}
}
