rsc | a84cbb2 | 2004-04-19 19:29:25 +0000 | [diff] [blame] | 1 | #include <u.h> |
| 2 | #include <libc.h> |
| 3 | #include <bio.h> |
| 4 | #include "elf.h" |
| 5 | #include "dwarf.h" |
| 6 | |
| 7 | static int |
| 8 | readblock(int fd, DwarfBlock *b, ulong off, ulong len) |
| 9 | { |
| 10 | b->data = malloc(len); |
| 11 | if(b->data == nil) |
| 12 | return -1; |
| 13 | if(seek(fd, off, 0) < 0 || readn(fd, b->data, len) != len){ |
| 14 | free(b->data); |
| 15 | b->data = nil; |
| 16 | return -1; |
| 17 | } |
| 18 | b->len = len; |
| 19 | return 0; |
| 20 | } |
| 21 | |
| 22 | static int |
| 23 | findsection(Elf *elf, char *name, ulong *off, ulong *len) |
| 24 | { |
| 25 | ElfSect *s; |
| 26 | |
| 27 | if((s = elfsection(elf, name)) == nil) |
| 28 | return -1; |
| 29 | *off = s->offset; |
| 30 | *len = s->size; |
| 31 | return s - elf->sect; |
| 32 | } |
| 33 | |
| 34 | static int |
| 35 | loadsection(Elf *elf, char *name, DwarfBlock *b) |
| 36 | { |
| 37 | ulong off, len; |
| 38 | |
| 39 | if(findsection(elf, name, &off, &len) < 0) |
| 40 | return -1; |
| 41 | return readblock(elf->fd, b, off, len); |
| 42 | } |
| 43 | |
| 44 | Dwarf* |
| 45 | dwarfopen(Elf *elf) |
| 46 | { |
| 47 | Dwarf *d; |
| 48 | |
| 49 | if(elf == nil){ |
| 50 | werrstr("nil elf passed to dwarfopen"); |
| 51 | return nil; |
| 52 | } |
| 53 | |
| 54 | d = mallocz(sizeof(Dwarf), 1); |
| 55 | if(d == nil) |
| 56 | return nil; |
| 57 | |
| 58 | d->elf = elf; |
| 59 | if(loadsection(elf, ".debug_abbrev", &d->abbrev) < 0 |
| 60 | || loadsection(elf, ".debug_aranges", &d->aranges) < 0 |
rsc | a84cbb2 | 2004-04-19 19:29:25 +0000 | [diff] [blame] | 61 | || loadsection(elf, ".debug_line", &d->line) < 0 |
| 62 | || loadsection(elf, ".debug_pubnames", &d->pubnames) < 0 |
rsc | a84cbb2 | 2004-04-19 19:29:25 +0000 | [diff] [blame] | 63 | || loadsection(elf, ".debug_info", &d->info) < 0) |
| 64 | goto err; |
rsc | ebd3954 | 2004-04-20 05:43:05 +0000 | [diff] [blame] | 65 | loadsection(elf, ".debug_frame", &d->frame); |
| 66 | loadsection(elf, ".debug_ranges", &d->ranges); |
| 67 | loadsection(elf, ".debug_str", &d->str); |
rsc | a84cbb2 | 2004-04-19 19:29:25 +0000 | [diff] [blame] | 68 | |
| 69 | /* make this a table once there are more */ |
| 70 | switch(d->elf->hdr.machine){ |
| 71 | case ElfMach386: |
| 72 | d->reg = dwarf386regs; |
| 73 | d->nreg = dwarf386nregs; |
| 74 | break; |
| 75 | default: |
| 76 | werrstr("unsupported machine"); |
| 77 | goto err; |
| 78 | } |
| 79 | |
| 80 | return d; |
| 81 | |
| 82 | err: |
| 83 | free(d->abbrev.data); |
| 84 | free(d->aranges.data); |
| 85 | free(d->frame.data); |
| 86 | free(d->line.data); |
| 87 | free(d->pubnames.data); |
| 88 | free(d->ranges.data); |
| 89 | free(d->str.data); |
| 90 | free(d->info.data); |
| 91 | free(d); |
| 92 | return nil; |
| 93 | } |
| 94 | |
| 95 | void |
| 96 | dwarfclose(Dwarf *d) |
| 97 | { |
| 98 | free(d->abbrev.data); |
| 99 | free(d->aranges.data); |
| 100 | free(d->frame.data); |
| 101 | free(d->line.data); |
| 102 | free(d->pubnames.data); |
| 103 | free(d->ranges.data); |
| 104 | free(d->str.data); |
| 105 | free(d->info.data); |
| 106 | free(d); |
| 107 | } |