// 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/internal/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
	p             *Process     // The parent process of 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{p: p, 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")
	var pctab, funcnametab region
	havePCtab := r.HasField("pctab")
	if havePCtab {
		// In 1.16, pclntable was split up into pctab and funcnametab.
		pctab = r.Field("pctab")
		funcnametab = r.Field("funcnametab")
	}
	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)
		var min, max core.Address
		var funcoff int64
		if ft.HasField("entryoff") {
			min = m.textAddr(ft.Field("entryoff").Uint32())
			max = m.textAddr(ftab.SliceIndex(i + 1).Field("entryoff").Uint32())
			funcoff = int64(ft.Field("funcoff").Uint32())
		} else {
			// Prior to 1.18, functab.entry directly referenced the
			// entries.
			min = core.Address(ft.Field("entry").Uintptr())
			max = core.Address(ftab.SliceIndex(i + 1).Field("entry").Uintptr())
			// funcoff changed type, but had the same meaning.
			funcoff = int64(ft.Field("funcoff").Uintptr())
		}
		fr := pcln.SliceIndex(funcoff).Cast("runtime._func")
		var f *Func
		if havePCtab {
			f = m.readFunc(fr, pctab, funcnametab)
		} else {
			f = m.readFunc(fr, pcln, 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, pctab region, funcnametab region) *Func {
	f := &Func{module: m, r: r}
	if r.HasField("entryoff") {
		f.entry = m.textAddr(r.Field("entryoff").Uint32())
	} else {
		// Prior to 1.18, _func.entry directly referenced the entries.
		f.entry = core.Address(r.Field("entry").Uintptr())
	}
	f.name = r.p.proc.ReadCString(funcnametab.SliceIndex(int64(r.Field("nameoff").Int32())).a)
	pcsp := r.Field("pcsp")
	var pcspIdx int64
	if pcsp.typ.Kind == KindUint {
		// In 1.16, pcsp changed to be a uint32 from an int32.
		pcspIdx = int64(pcsp.Uint32())
	} else {
		pcspIdx = int64(pcsp.Int32())
	}
	f.frameSize.read(r.p.proc, pctab.SliceIndex(pcspIdx).a)

	// Parse pcdata and funcdata, which are laid out beyond the end of the _func.
	// In 1.16, npcdata changed to be a uint32 from an int32.
	npcdata := r.Field("npcdata")
	var n uint32
	if npcdata.typ.Kind == KindUint {
		// In 1.16, pcsp changed to be a uint32 from an int32.
		n = npcdata.Uint32()
	} else {
		n = uint32(npcdata.Int32())
	}
	nfd := r.Field("nfuncdata")
	a := nfd.a.Add(nfd.typ.Size)

	for i := uint32(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())

	if nfd.typ.Size == 1 { // go 1.12 and beyond, this is a uint8
		n = uint32(nfd.Uint8())
	} else { // go 1.11 and earlier, this is an int32
		n = uint32(nfd.Int32())
	}
	for i := uint32(0); i < n; i++ {
		if m.r.HasField("gofunc") {
			// Since 1.18, funcdata contains offsets from go.func.*.
			off := r.p.proc.ReadUint32(a)
			if off == ^uint32(0) {
				// No entry.
				f.funcdata = append(f.funcdata, 0)
			} else {
				f.funcdata = append(f.funcdata, core.Address(m.r.Field("gofunc").Uintptr()+uint64(off)))
			}
			a = a.Add(4)
		} else {
			// Prior to 1.18, funcdata contains pointers directly
			// to the data.
			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, pctab.SliceIndex(int64(f.pcdata[stackmap])).a)
	} else {
		f.stackMap.setEmpty()
	}

	return f
}

// textAddr returns the address of a text offset.
//
// Equivalent to runtime.moduledata.textAddr.
func (m *module) textAddr(off32 uint32) core.Address {
	off := uint64(off32)
	res := m.r.Field("text").Uintptr() + off

	textsectmap := m.r.Field("textsectmap")
	length := textsectmap.SliceLen()
	if length > 1 {
		for i := int64(0); i < length; i++ {
			sect := textsectmap.SliceIndex(i)

			vaddr := sect.Field("vaddr").Uintptr()
			end := sect.Field("end").Uintptr()
			baseaddr := sect.Field("baseaddr").Uintptr()

			if off >= vaddr && off < end || (i == length-1 && off == end) {
				res = baseaddr + off - vaddr
			}
		}
	}

	return core.Address(res)
}

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, error) {
	for _, e := range t.entries {
		if off < e.bytes {
			return e.val, nil
		}
		off -= e.bytes
	}
	return 0, fmt.Errorf("can't find pctab entry for offset %#x", off)
}

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