1 /* 2 * Dwarf abbreviation parsing code. 3 * 4 * The convention here is that calling dwarfgetabbrevs relinquishes 5 * access to any abbrevs returned previously. Will have to add 6 * explicit reference counting if this turns out not to be acceptable. 7 */ 8 9 #include <precomp.h> 10 11 #define NDEBUG 12 #include <debug.h> 13 14 static int parseabbrevs(Dwarf*, ulong, DwarfAbbrev*, DwarfAttr*, int*, int*); 15 DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong); 16 17 static int 18 loadabbrevs(Dwarf *d, ulong off, DwarfAbbrev **aa) 19 { 20 int nattr, nabbrev; 21 DwarfAbbrev *abbrev; 22 DwarfAttr *attr; 23 24 if(d->acache.off == off && d->acache.na){ 25 *aa = d->acache.a; 26 return d->acache.na; 27 } 28 29 /* two passes - once to count, then allocate, then a second to copy */ 30 if(parseabbrevs(d, off, nil, nil, &nabbrev, &nattr) < 0) { 31 return -1; 32 } 33 34 abbrev = malloc(nabbrev*sizeof(DwarfAbbrev) + nattr*sizeof(DwarfAttr)); 35 attr = (DwarfAttr*)(abbrev+nabbrev); 36 37 if(parseabbrevs(d, off, abbrev, attr, nil, nil) < 0){ 38 free(abbrev); 39 return -1; 40 } 41 42 free(d->acache.a); 43 d->acache.a = abbrev; 44 d->acache.na = nabbrev; 45 d->acache.off = off; 46 47 *aa = abbrev; 48 return nabbrev; 49 } 50 51 static int 52 parseabbrevs(Dwarf *d, ulong off, DwarfAbbrev *abbrev, DwarfAttr *attr, int *pnabbrev, int *pnattr) 53 { 54 int i, nabbrev, nattr, haskids; 55 ulong num, tag, name, form; 56 DwarfBuf b; 57 58 if(off >= d->abbrev.len){ 59 werrstr("bad abbrev section offset 0x%lux >= 0x%lux", off, d->abbrev.len); 60 return -1; 61 } 62 63 memset(&b, 0, sizeof b); 64 b.p = d->abbrev.data + off; 65 b.ep = d->abbrev.data + d->abbrev.len; 66 67 nabbrev = 0; 68 nattr = 0; 69 for(;;){ 70 if(b.p == nil){ 71 werrstr("malformed abbrev data"); 72 return -1; 73 } 74 num = dwarfget128(&b); 75 if(num == 0) 76 break; 77 tag = dwarfget128(&b); 78 werrstr("abbrev: num %d tag %x @ %x", num, tag, b.p - d->abbrev.data); 79 haskids = dwarfget1(&b); 80 for(i=0;; i++){ 81 name = dwarfget128(&b); 82 form = dwarfget128(&b); 83 assert(form < 0x3000); 84 if(name == 0 && form == 0) 85 break; 86 if(attr){ 87 attr[i].name = name; 88 attr[i].form = form; 89 } 90 } 91 if(abbrev){ 92 abbrev->num = num; 93 abbrev->tag = tag; 94 abbrev->haskids = haskids; 95 abbrev->attr = attr; 96 abbrev->nattr = i; 97 abbrev++; 98 attr += i; 99 } 100 nabbrev++; 101 nattr += i; 102 } 103 if(pnabbrev) 104 *pnabbrev = nabbrev; 105 if(pnattr) 106 *pnattr = nattr; 107 return 0; 108 } 109 110 static DwarfAbbrev* 111 findabbrev(DwarfAbbrev *a, int na, ulong num) 112 { 113 int i; 114 115 for(i=0; i<na; i++) { 116 if(a[i].num == num) { 117 return &a[i]; 118 } 119 } 120 werrstr("abbrev not found (%x)", na); 121 return nil; 122 } 123 124 DwarfAbbrev* 125 dwarfgetabbrev(Dwarf *d, ulong off, ulong num) 126 { 127 DwarfAbbrev *a; 128 int na; 129 werrstr("want num %d\n", num); 130 if((na = loadabbrevs(d, off, &a)) < 0){ 131 werrstr("loadabbrevs: %r"); 132 return nil; 133 } 134 return findabbrev(a, na, num); 135 } 136 137