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

// Runtime symbol table parsing.
// See http://golang.org/s/go12symtab for an overview.

package runtime
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "arch_GOARCH.h"
#include "malloc.h"
#include "funcdata.h"

typedef struct Ftab Ftab;
struct Ftab
{
	uintptr	entry;
	uintptr	funcoff;
};

extern byte pclntab[];

static Ftab *ftab;
static uintptr nftab;
static uint32 *filetab;
static uint32 nfiletab;

static String end = { (uint8*)"end", 3 };

void
runtime·symtabinit(void)
{
	int32 i, j;
	Func *f1, *f2;
	
	// See golang.org/s/go12symtab for header: 0xfffffffb,
	// two zero bytes, a byte giving the PC quantum,
	// and a byte giving the pointer width in bytes.
	if(*(uint32*)pclntab != 0xfffffffb || pclntab[4] != 0 || pclntab[5] != 0 || pclntab[6] != PCQuantum || pclntab[7] != sizeof(void*)) {
		runtime·printf("runtime: function symbol table header: %x %x\n", *(uint32*)pclntab, *(uint32*)(pclntab+4));
		runtime·throw("invalid function symbol table\n");
	}

	nftab = *(uintptr*)(pclntab+8);
	ftab = (Ftab*)(pclntab+8+sizeof(void*));
	for(i=0; i<nftab; i++) {
		// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
		if(ftab[i].entry > ftab[i+1].entry) {
			f1 = (Func*)(pclntab + ftab[i].funcoff);
			f2 = (Func*)(pclntab + ftab[i+1].funcoff);
			runtime·printf("function symbol table not sorted by program counter: %p %s > %p %s", ftab[i].entry, runtime·funcname(f1), ftab[i+1].entry, i+1 == nftab ? "end" : runtime·funcname(f2));
			for(j=0; j<=i; j++)
				runtime·printf("\t%p %s\n", ftab[j].entry, runtime·funcname((Func*)(pclntab + ftab[j].funcoff)));
			runtime·throw("invalid runtime symbol table");
		}
	}
	
	filetab = (uint32*)(pclntab + *(uint32*)&ftab[nftab].funcoff);
	nfiletab = filetab[0];
}

static uint32
readvarint(byte **pp)
{
	byte *p;
	uint32 v;
	int32 shift;
	
	v = 0;
	p = *pp;
	for(shift = 0;; shift += 7) {
		v |= (*p & 0x7F) << shift;
		if(!(*p++ & 0x80))
			break;
	}
	*pp = p;
	return v;
}

void*
runtime·funcdata(Func *f, int32 i)
{
	byte *p;

	if(i < 0 || i >= f->nfuncdata)
		return nil;
	p = (byte*)&f->nfuncdata + 4 + f->npcdata*4;
	if(sizeof(void*) == 8 && ((uintptr)p & 4)) {
		if(((uintptr)f & 4))
			runtime·printf("misaligned func %p\n", f);
		p += 4;
	}
	return ((void**)p)[i];
}

static bool
step(byte **pp, uintptr *pc, int32 *value, bool first)
{
	uint32 uvdelta, pcdelta;
	int32 vdelta;

	uvdelta = readvarint(pp);
	if(uvdelta == 0 && !first)
		return 0;
	if(uvdelta&1)
		uvdelta = ~(uvdelta>>1);
	else
		uvdelta >>= 1;
	vdelta = (int32)uvdelta;
	pcdelta = readvarint(pp) * PCQuantum;
	*value += vdelta;
	*pc += pcdelta;
	return 1;
}

// Return associated data value for targetpc in func f.
// (Source file is f->src.)
static int32
pcvalue(Func *f, int32 off, uintptr targetpc, bool strict)
{
	byte *p;
	uintptr pc;
	int32 value;

	enum {
		debug = 0
	};

	// The table is a delta-encoded sequence of (value, pc) pairs.
	// Each pair states the given value is in effect up to pc.
	// The value deltas are signed, zig-zag encoded.
	// The pc deltas are unsigned.
	// The starting value is -1, the starting pc is the function entry.
	// The table ends at a value delta of 0 except in the first pair.
	if(off == 0)
		return -1;
	p = pclntab + off;
	pc = f->entry;
	value = -1;

	if(debug && !runtime·panicking)
		runtime·printf("pcvalue start f=%s [%p] pc=%p targetpc=%p value=%d tab=%p\n",
			runtime·funcname(f), f, pc, targetpc, value, p);
	
	while(step(&p, &pc, &value, pc == f->entry)) {
		if(debug)
			runtime·printf("\tvalue=%d until pc=%p\n", value, pc);
		if(targetpc < pc)
			return value;
	}
	
	// If there was a table, it should have covered all program counters.
	// If not, something is wrong.
	if(runtime·panicking || !strict)
		return -1;
	runtime·printf("runtime: invalid pc-encoded table f=%s pc=%p targetpc=%p tab=%p\n",
		runtime·funcname(f), pc, targetpc, p);
	p = (byte*)f + off;
	pc = f->entry;
	value = -1;
	
	while(step(&p, &pc, &value, pc == f->entry))
		runtime·printf("\tvalue=%d until pc=%p\n", value, pc);
	
	runtime·throw("invalid runtime symbol table");
	return -1;
}

static String unknown = { (uint8*)"?", 1 };

int8*
runtime·funcname(Func *f)
{
	if(f == nil || f->nameoff == 0)
		return nil;
	return (int8*)(pclntab + f->nameoff);
}

static int32
funcline(Func *f, uintptr targetpc, String *file, bool strict)
{
	int32 line;
	int32 fileno;

	*file = unknown;
	fileno = pcvalue(f, f->pcfile, targetpc, strict);
	line = pcvalue(f, f->pcln, targetpc, strict);
	if(fileno == -1 || line == -1 || fileno >= nfiletab) {
		// runtime·printf("looking for %p in %S got file=%d line=%d\n", targetpc, *f->name, fileno, line);
		return 0;
	}
	*file = runtime·gostringnocopy(pclntab + filetab[fileno]);
	return line;
}

int32
runtime·funcline(Func *f, uintptr targetpc, String *file)
{
	return funcline(f, targetpc, file, true);
}

int32
runtime·funcspdelta(Func *f, uintptr targetpc)
{
	int32 x;
	
	x = pcvalue(f, f->pcsp, targetpc, true);
	if(x&(sizeof(void*)-1))
		runtime·printf("invalid spdelta %d %d\n", f->pcsp, x);
	return x;
}

int32
runtime·pcdatavalue(Func *f, int32 table, uintptr targetpc)
{
	if(table < 0 || table >= f->npcdata)
		return -1;
	return pcvalue(f, (&f->nfuncdata)[1+table], targetpc, true);
}

int32
runtime·funcarglen(Func *f, uintptr targetpc)
{
	if(targetpc == f->entry)
		return 0;
	return runtime·pcdatavalue(f, PCDATA_ArgSize, targetpc-PCQuantum);
}

func funcline_go(f *Func, targetpc uintptr) (retfile String, retline int) {
	// Pass strict=false here, because anyone can call this function,
	// and they might just be wrong about targetpc belonging to f.
	retline = funcline(f, targetpc, &retfile, false);
}

func funcname_go(f *Func) (ret String) {
	ret = runtime·gostringnocopy((uint8*)runtime·funcname(f));
}

func funcentry_go(f *Func) (ret uintptr) {
	ret = f->entry;
}

Func*
runtime·findfunc(uintptr addr)
{
	Ftab *f;
	int32 nf, n;

	if(nftab == 0)
		return nil;
	if(addr < ftab[0].entry || addr >= ftab[nftab].entry)
		return nil;

	// binary search to find func with entry <= addr.
	f = ftab;
	nf = nftab;
	while(nf > 0) {
		n = nf/2;
		if(f[n].entry <= addr && addr < f[n+1].entry)
			return (Func*)(pclntab + f[n].funcoff);
		else if(addr < f[n].entry)
			nf = n;
		else {
			f += n+1;
			nf -= n+1;
		}
	}

	// can't get here -- we already checked above
	// that the address was in the table bounds.
	// this can only happen if the table isn't sorted
	// by address or if the binary search above is buggy.
	runtime·prints("findfunc unreachable\n");
	return nil;
}

func FuncForPC(pc uintptr) (ret *Func) {
	ret = runtime·findfunc(pc);
}

static bool
hasprefix(String s, int8 *p)
{
	int32 i;

	for(i=0; i<s.len; i++) {
		if(p[i] == 0)
			return 1;
		if(p[i] != s.str[i])
			return 0;
	}
	return p[i] == 0;
}

static bool
contains(String s, int8 *p)
{
	int32 i;

	if(p[0] == 0)
		return 1;
	for(i=0; i<s.len; i++) {
		if(s.str[i] != p[0])
			continue;
		if(hasprefix((String){s.str + i, s.len - i}, p))
			return 1;
	}
	return 0;
}

bool
runtime·showframe(Func *f, G *gp)
{
	static int32 traceback = -1;
	String name;

	if(m->throwing > 0 && gp != nil && (gp == m->curg || gp == m->caughtsig))
		return 1;
	if(traceback < 0)
		traceback = runtime·gotraceback(nil);
	name = runtime·gostringnocopy((uint8*)runtime·funcname(f));

	// Special case: always show runtime.panic frame, so that we can
	// see where a panic started in the middle of a stack trace.
	// See golang.org/issue/5832.
	if(name.len == 7+1+5 && hasprefix(name, "runtime.panic"))
		return 1;

	return traceback > 1 || f != nil && contains(name, ".") && !hasprefix(name, "runtime.");
}
