| #include <u.h> |
| #include <libc.h> |
| #include <bio.h> |
| #include "elf.h" |
| #include "dwarf.h" |
| |
| static int |
| readblock(int fd, DwarfBlock *b, ulong off, ulong len) |
| { |
| b->data = malloc(len); |
| if(b->data == nil) |
| return -1; |
| if(seek(fd, off, 0) < 0 || readn(fd, b->data, len) != len){ |
| free(b->data); |
| b->data = nil; |
| return -1; |
| } |
| b->len = len; |
| return 0; |
| } |
| |
| static int |
| findsection(Elf *elf, char *name, ulong *off, ulong *len) |
| { |
| ElfSect *s; |
| |
| if((s = elfsection(elf, name)) == nil) |
| return -1; |
| *off = s->offset; |
| *len = s->size; |
| return s - elf->sect; |
| } |
| |
| static int |
| loadsection(Elf *elf, char *name, DwarfBlock *b) |
| { |
| ulong off, len; |
| |
| if(findsection(elf, name, &off, &len) < 0) |
| return -1; |
| return readblock(elf->fd, b, off, len); |
| } |
| |
| Dwarf* |
| dwarfopen(Elf *elf) |
| { |
| Dwarf *d; |
| |
| if(elf == nil){ |
| werrstr("nil elf passed to dwarfopen"); |
| return nil; |
| } |
| |
| d = mallocz(sizeof(Dwarf), 1); |
| if(d == nil) |
| return nil; |
| |
| d->elf = elf; |
| if(loadsection(elf, ".debug_abbrev", &d->abbrev) < 0 |
| || loadsection(elf, ".debug_aranges", &d->aranges) < 0 |
| || loadsection(elf, ".debug_line", &d->line) < 0 |
| || loadsection(elf, ".debug_pubnames", &d->pubnames) < 0 |
| || loadsection(elf, ".debug_info", &d->info) < 0) |
| goto err; |
| loadsection(elf, ".debug_frame", &d->frame); |
| loadsection(elf, ".debug_ranges", &d->ranges); |
| loadsection(elf, ".debug_str", &d->str); |
| |
| /* make this a table once there are more */ |
| switch(d->elf->hdr.machine){ |
| case ElfMach386: |
| d->reg = dwarf386regs; |
| d->nreg = dwarf386nregs; |
| break; |
| default: |
| werrstr("unsupported machine"); |
| goto err; |
| } |
| |
| return d; |
| |
| err: |
| free(d->abbrev.data); |
| free(d->aranges.data); |
| free(d->frame.data); |
| free(d->line.data); |
| free(d->pubnames.data); |
| free(d->ranges.data); |
| free(d->str.data); |
| free(d->info.data); |
| free(d); |
| return nil; |
| } |
| |
| void |
| dwarfclose(Dwarf *d) |
| { |
| free(d->abbrev.data); |
| free(d->aranges.data); |
| free(d->frame.data); |
| free(d->line.data); |
| free(d->pubnames.data); |
| free(d->ranges.data); |
| free(d->str.data); |
| free(d->info.data); |
| free(d); |
| } |