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

static int
_dwarfnametounit(Dwarf *d, char *name, DwarfBlock *bl, DwarfSym *s)
{
	int vers;
	ulong len, unit, off;
	uchar *next;
	char *str;
	DwarfBuf b;

	b.d = d;
	b.p = bl->data;
	b.ep = b.p + bl->len;

	while(b.p < b.ep){
		len = dwarfget4(&b);
		if(len > b.ep-b.p){
			werrstr("bad length in dwarf name header");
			return -1;
		}
		next = b.p + len;
		vers = dwarfget2(&b);
		if(vers != 1 && vers != 2){
			werrstr("bad version %d in dwarf name header", vers);
			return -1;
		}
		unit = dwarfget4(&b);
		dwarfget4(&b);	/* unit length */
		while(b.p < next){
			off = dwarfget4(&b);
			if(off == 0)
				break;
			str = dwarfgetstring(&b);
			if(strcmp(str, name) == 0){
				if(dwarfenumunit(d, unit, s) < 0)
					return -1;
				if(unit + off >= s->b.ep - d->info.data){
					werrstr("bad offset in name entry");
					return -1;
				}
				s->b.p = d->info.data + unit + off;
				if(dwarfnextsym(d, s) < 0)
					return -1;
				if(s->attrs.name==nil || strcmp(s->attrs.name, name)!=0){
					werrstr("unexpected name %#q in lookup for %#q", s->attrs.name, name);
					return -1;
				}
				return 0;
			}
		}
		b.p = next;
	}
	werrstr("unknown name '%s'", name);
	return -1;
}

int
dwarflookupname(Dwarf *d, char *name, DwarfSym *sym)
{
	return _dwarfnametounit(d, name, &d->pubnames, sym);
}

/*

int
dwarflookuptype(Dwarf *d, char *name, DwarfSym *sym)
{
	return _dwarfnametounit(d, name, &d->pubtypes, sym);
}

 */
