diff options
Diffstat (limited to 'src/libmach/dwarfaranges.c')
| -rw-r--r-- | src/libmach/dwarfaranges.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/libmach/dwarfaranges.c b/src/libmach/dwarfaranges.c new file mode 100644 index 00000000..21299588 --- /dev/null +++ b/src/libmach/dwarfaranges.c @@ -0,0 +1,63 @@ +/* + * 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; +} + |
