/*
 * Dwarf pc to source line conversion.
 * 
 * Maybe should do the reverse here, but what should the interface look like?
 * One possibility is to use the Plan 9 line2addr interface:
 *
 *	long line2addr(ulong line, ulong basepc)
 *
 * which returns the smallest pc > basepc with line number line (ignoring file name).
 *
 * The encoding may be small, but it sure isn't simple!
 */

#include <u.h>
#include <libc.h>
#include <bio.h>
#include "elf.h"
#include "dwarf.h"

#define trace 0

enum
{
	Isstmt = 1<<0,
	BasicDwarfBlock = 1<<1,
	EndSequence = 1<<2,
	PrologueEnd = 1<<3,
	EpilogueBegin = 1<<4,
};

typedef struct State State;
struct State
{
	ulong addr;
	ulong file;
	ulong line;
	ulong column;
	ulong flags;
	ulong isa;
};

int
dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, ulong *line, ulong *mtime, ulong *length)
{
	uchar *prog, *opcount, *end;
	ulong off, unit, len, vers, x, start;
	int i, first, op, a, l, quantum, isstmt, linebase, linerange, opcodebase, nf;
	char *files, *dirs, *s;
	DwarfBuf b;
	DwarfSym sym;
	State emit, cur, reset;
	uchar **f, **newf;

	f = nil;

	if(dwarfaddrtounit(d, pc, &unit) < 0
	|| dwarflookuptag(d, unit, TagCompileUnit, &sym) < 0)
		return -1;

	if(!sym.attrs.have.stmtlist){
		werrstr("no line mapping information for 0x%lux", pc);
		return -1;
	}
	off = sym.attrs.stmtlist;
	if(off >= d->line.len){
		fprint(2, "bad stmtlist\n");
		goto bad;
	}

	if(trace) fprint(2, "unit 0x%lux stmtlist 0x%lux\n", unit, sym.attrs.stmtlist);

	memset(&b, 0, sizeof b);
	b.d = d;
	b.p = d->line.data + off;
	b.ep = b.p + d->line.len;
	b.addrsize = sym.b.addrsize;	/* should i get this from somewhere else? */

	len = dwarfget4(&b);
	if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
		fprint(2, "bad len\n");
		goto bad;
	}

	b.ep = b.p+len;
	vers = dwarfget2(&b);
	if(vers != 2){
		werrstr("bad dwarf version 0x%lux", vers);
		return -1;
	}

	len = dwarfget4(&b);
	if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
		fprint(2, "another bad len\n");
		goto bad;
	}
	prog = b.p+len;

	quantum = dwarfget1(&b);
	isstmt = dwarfget1(&b);
	linebase = (schar)dwarfget1(&b);
	linerange = (schar)dwarfget1(&b);
	opcodebase = dwarfget1(&b);

	opcount = b.p-1;
	dwarfgetnref(&b, opcodebase-1);
	if(b.p == nil){
		fprint(2, "bad opcode chart\n");
		goto bad;
	}

	/* just skip the files and dirs for now; we'll come back */
	dirs = (char*)b.p;
	while(b.p!=nil && *b.p!=0)
		dwarfgetstring(&b);
	dwarfget1(&b);

	files = (char*)b.p;
	while(b.p!=nil && *b.p!=0){
		dwarfgetstring(&b);
		dwarfget128(&b);
		dwarfget128(&b);
		dwarfget128(&b);
	}
	dwarfget1(&b);

	/* move on to the program */
	if(b.p == nil || b.p > prog){
		fprint(2, "bad header\n");
		goto bad;
	}
	b.p = prog;

	reset.addr = 0;
	reset.file = 1;
	reset.line = 1;
	reset.column = 0;
	reset.flags = isstmt ? Isstmt : 0;
	reset.isa = 0;

	cur = reset;
	emit = reset;
	nf = 0;
	start = 0;
	if(trace) fprint(2, "program @ %lud ... %.*H opbase = %d\n", b.p - d->line.data, b.ep-b.p, b.p, opcodebase);
	first = 1;
	while(b.p != nil){
		op = dwarfget1(&b);
		if(trace) fprint(2, "\tline %lud, addr 0x%lux, op %d %.10H", cur.line, cur.addr, op, b.p);
		if(op >= opcodebase){
			a = (op - opcodebase) / linerange;
			l = (op - opcodebase) % linerange + linebase;
			cur.line += l;
			cur.addr += a * quantum;
			if(trace) fprint(2, " +%d,%d\n", a, l);
		emit:
			if(first){
				if(cur.addr > pc){
					werrstr("found wrong line mapping 0x%lux for pc 0x%lux", cur.addr, pc);
					goto out;
				}
				first = 0;
				start = cur.addr;
			}
			if(cur.addr > pc)
				break;
			if(b.p == nil){
				werrstr("buffer underflow in line mapping");
				goto out;
			}
			emit = cur;
			if(emit.flags & EndSequence){
				werrstr("found wrong line mapping 0x%lux-0x%lux for pc 0x%lux", start, cur.addr, pc);
				goto out;
			}
			cur.flags &= ~(BasicDwarfBlock|PrologueEnd|EpilogueBegin);
		}else{
			switch(op){
			case 0:	/* extended op code */
				if(trace) fprint(2, " ext");
				len = dwarfget128(&b);
				end = b.p+len;
				if(b.p == nil || end > b.ep || end < b.p || len < 1)
					goto bad;
				switch(dwarfget1(&b)){
				case 1:	/* end sequence */
					if(trace) fprint(2, " end\n");
					cur.flags |= EndSequence;
					goto emit;
				case 2:	/* set address */
					cur.addr = dwarfgetaddr(&b);
					if(trace) fprint(2, " set pc 0x%lux\n", cur.addr);
					break;
				case 3:	/* define file */
					newf = realloc(f, (nf+1)*sizeof(f[0]));
					if(newf == nil)
						goto out;
					f[nf++] = b.p;
					s = dwarfgetstring(&b);
					dwarfget128(&b);
					dwarfget128(&b);
					dwarfget128(&b);
					if(trace) fprint(2, " def file %s\n", s);
					break;
				}
				if(b.p == nil || b.p > end)
					goto bad;
				b.p = end;
				break;
			case 1:	/* emit */
				if(trace) fprint(2, " emit\n");
				goto emit;
			case 2:	/* advance pc */
				a = dwarfget128(&b);
				if(trace) fprint(2, " advance pc + %lud\n", a*quantum);
				cur.addr += a * quantum;
				break;
			case 3:	/* advance line */
				l = dwarfget128s(&b);
				if(trace) fprint(2, " advance line + %ld\n", l);
				cur.line += l;
				break;
			case 4:	/* set file */
				if(trace) fprint(2, " set file\n");
				cur.file = dwarfget128s(&b);
				break;
			case 5:	/* set column */
				if(trace) fprint(2, " set column\n");
				cur.column = dwarfget128(&b);
				break;
			case 6:	/* negate stmt */
				if(trace) fprint(2, " negate stmt\n");
				cur.flags ^= Isstmt;
				break;
			case 7:	/* set basic block */
				if(trace) fprint(2, " set basic block\n");
				cur.flags |= BasicDwarfBlock;
				break;
			case 8:	/* const add pc */
				a = (255 - opcodebase) / linerange * quantum;
				if(trace) fprint(2, " const add pc + %d\n", a);
				cur.addr += a;
				break;
			case 9:	/* fixed advance pc */
				a = dwarfget2(&b);
				if(trace) fprint(2, " fixed advance pc + %d\n", a);
				cur.addr += a;
				break;
			case 10:	/* set prologue end */
				if(trace) fprint(2, " set prologue end\n");
				cur.flags |= PrologueEnd;
				break;
			case 11:	/* set epilogue begin */
				if(trace) fprint(2, " set epilogue begin\n");
				cur.flags |= EpilogueBegin;
				break;
			case 12:	/* set isa */
				if(trace) fprint(2, " set isa\n");
				cur.isa = dwarfget128(&b);
				break;
			default:	/* something new - skip it */
				if(trace) fprint(2, " unknown %d\n", opcount[op]);
				for(i=0; i<opcount[op]; i++)
					dwarfget128(&b);
				break;
			}
		}
	}
	if(b.p == nil)
		goto bad;

	/* finally!  the data we seek is in "emit" */

	if(emit.file == 0){
		werrstr("invalid file index in mapping data");
		goto out;
	}
	if(line)
		*line = emit.line;

	/* skip over first emit.file-2 guys */
	b.p = (uchar*)files;
	for(i=emit.file-1; i > 0 && b.p!=nil && *b.p!=0; i--){
		dwarfgetstring(&b);
		dwarfget128(&b);
		dwarfget128(&b);
		dwarfget128(&b);
	}
	if(b.p == nil){
		werrstr("problem parsing file data second time (cannot happen)");
		goto bad;
	}
	if(*b.p == 0){
		if(i >= nf){
			werrstr("bad file index in mapping data");
			goto bad;
		}
		b.p = f[i];
	}
	s = dwarfgetstring(&b);
	if(file)
		*file = s;
	i = dwarfget128(&b);		/* directory */
	x = dwarfget128(&b);
	if(mtime)
		*mtime = x;
	x = dwarfget128(&b);
	if(length)
		*length = x;

	/* fetch dir name */
	if(cdir)
		*cdir = sym.attrs.compdir;

	if(dir){
		if(i == 0)
			*dir = nil;
		else{
			b.p = (uchar*)dirs;
			for(i--; i>0 && b.p!=nil && *b.p!=0; i--)
				dwarfgetstring(&b);
			if(b.p==nil || *b.p==0){
				werrstr("bad directory reference in line mapping");
				goto out;		/* can only happen with bad dir index */
			}
			*dir = dwarfgetstring(&b);
		}
	}

	/* free at last, free at last */
	free(f);
	return 0;

bad:
	werrstr("corrupted line mapping for 0x%lux", pc);
out:
	free(f);
	return -1;
}
