plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

dwarfabbrev.c (2629B)


      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 <u.h>
     10 #include <libc.h>
     11 #include <bio.h>
     12 #include "elf.h"
     13 #include "dwarf.h"
     14 
     15 static int parseabbrevs(Dwarf*, ulong, DwarfAbbrev*, DwarfAttr*, int*, int*);
     16 DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
     17 
     18 static int
     19 loadabbrevs(Dwarf *d, ulong off, DwarfAbbrev **aa)
     20 {
     21 	int nattr, nabbrev;
     22 	DwarfAbbrev *abbrev;
     23 	DwarfAttr *attr;
     24 
     25 	if(d->acache.off == off && d->acache.na){
     26 		*aa = d->acache.a;
     27 		return d->acache.na;
     28 	}
     29 
     30 	/* two passes - once to count, then allocate, then a second to copy */
     31 	if(parseabbrevs(d, off, nil, nil, &nabbrev, &nattr) < 0)
     32 		return -1;
     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\n", 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 		haskids = dwarfget1(&b);
     79 		for(i=0;; i++){
     80 			name = dwarfget128(&b);
     81 			form = dwarfget128(&b);
     82 			if(name == 0 && form == 0)
     83 				break;
     84 			if(attr){
     85 				attr[i].name = name;
     86 				attr[i].form = form;
     87 			}
     88 		}
     89 		if(abbrev){
     90 			abbrev->num = num;
     91 			abbrev->tag = tag;
     92 			abbrev->haskids = haskids;
     93 			abbrev->attr = attr;
     94 			abbrev->nattr = i;
     95 			abbrev++;
     96 			attr += i;
     97 		}
     98 		nabbrev++;
     99 		nattr += i;
    100 	}
    101 	if(pnabbrev)
    102 		*pnabbrev = nabbrev;
    103 	if(pnattr)
    104 		*pnattr = nattr;
    105 	return 0;
    106 }
    107 
    108 static DwarfAbbrev*
    109 findabbrev(DwarfAbbrev *a, int na, ulong num)
    110 {
    111 	int i;
    112 
    113 	for(i=0; i<na; i++)
    114 		if(a[i].num == num)
    115 			return &a[i];
    116 	werrstr("abbrev not found");
    117 	return nil;
    118 }
    119 
    120 DwarfAbbrev*
    121 dwarfgetabbrev(Dwarf *d, ulong off, ulong num)
    122 {
    123 	DwarfAbbrev *a;
    124 	int na;
    125 
    126 	if((na = loadabbrevs(d, off, &a)) < 0){
    127 		werrstr("loadabbrevs: %r");
    128 		return nil;
    129 	}
    130 	return findabbrev(a, na, num);
    131 }