| /* | 
 |  * Dwarf address ranges parsing code. | 
 |  */ | 
 |  | 
 | #include <u.h> | 
 | #include <libc.h> | 
 | #include <bio.h> | 
 | #include "elf.h" | 
 | #include "dwarf.h" | 
 |  | 
 | int | 
 | dwarfaddrtounit(Dwarf *d, ulong addr, ulong *unit) | 
 | { | 
 | 	DwarfBuf b; | 
 | 	int segsize, i; | 
 | 	ulong len, id, off, base, size; | 
 | 	uchar *start, *end; | 
 |  | 
 | 	memset(&b, 0, sizeof b); | 
 | 	b.d = d; | 
 | 	b.p = d->aranges.data; | 
 | 	b.ep = b.p + d->aranges.len; | 
 |  | 
 | 	while(b.p < b.ep){ | 
 | 		start = b.p; | 
 | 		len = dwarfget4(&b); | 
 | 		if((id = dwarfget2(&b)) != 2){ | 
 | 			if(b.p == nil){ | 
 | 			underflow: | 
 | 				werrstr("buffer underflow reading address ranges header"); | 
 | 			}else | 
 | 				werrstr("bad dwarf version 0x%lux in address ranges header", id); | 
 | 			return -1; | 
 | 		} | 
 | 		off = dwarfget4(&b); | 
 | 		b.addrsize = dwarfget1(&b); | 
 | 		if(d->addrsize == 0) | 
 | 			d->addrsize = b.addrsize; | 
 | 		segsize = dwarfget1(&b); | 
 | 		USED(segsize);	/* what am i supposed to do with this? */ | 
 | 		if(b.p == nil) | 
 | 			goto underflow; | 
 | 		if((i = (b.p-start) % (2*b.addrsize)) != 0) | 
 | 			b.p += 2*b.addrsize - i; | 
 | 		end = start+4+len; | 
 | 		while(b.p!=nil && b.p<end){ | 
 | 			base = dwarfgetaddr(&b); | 
 | 			size = dwarfgetaddr(&b); | 
 | 			if(b.p == nil) | 
 | 				goto underflow; | 
 | 			if(base <= addr && addr < base+size){ | 
 | 				*unit = off; | 
 | 				return 0; | 
 | 			} | 
 | 		} | 
 | 		if(b.p == nil) | 
 | 			goto underflow; | 
 | 		b.p = end; | 
 | 	} | 
 | 	werrstr("address 0x%lux is not listed in dwarf debugging symbols", addr); | 
 | 	return -1; | 
 | } | 
 |  |