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