2011-05-16 13:12:07 +00:00
|
|
|
/*
|
|
|
|
* Dwarf abbreviation parsing code.
|
|
|
|
*
|
|
|
|
* The convention here is that calling dwarfgetabbrevs relinquishes
|
2021-06-11 12:29:21 +00:00
|
|
|
* access to any abbrevs returned previously. Will have to add
|
2011-05-16 13:12:07 +00:00
|
|
|
* explicit reference counting if this turns out not to be acceptable.
|
|
|
|
*/
|
|
|
|
|
2011-08-14 18:12:05 +00:00
|
|
|
#include <precomp.h>
|
2011-05-16 13:12:07 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
2011-08-14 21:17:14 +00:00
|
|
|
#include <debug.h>
|
2011-05-16 13:12:07 +00:00
|
|
|
|
|
|
|
static int parseabbrevs(Dwarf*, ulong, DwarfAbbrev*, DwarfAttr*, int*, int*);
|
|
|
|
DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
|
|
|
|
|
|
|
|
static int
|
|
|
|
loadabbrevs(Dwarf *d, ulong off, DwarfAbbrev **aa)
|
|
|
|
{
|
2011-06-01 20:36:40 +00:00
|
|
|
int nattr, nabbrev;
|
|
|
|
DwarfAbbrev *abbrev;
|
|
|
|
DwarfAttr *attr;
|
|
|
|
|
|
|
|
if(d->acache.off == off && d->acache.na){
|
|
|
|
*aa = d->acache.a;
|
|
|
|
return d->acache.na;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* two passes - once to count, then allocate, then a second to copy */
|
|
|
|
if(parseabbrevs(d, off, nil, nil, &nabbrev, &nattr) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
abbrev = malloc(nabbrev*sizeof(DwarfAbbrev) + nattr*sizeof(DwarfAttr));
|
|
|
|
attr = (DwarfAttr*)(abbrev+nabbrev);
|
|
|
|
|
|
|
|
if(parseabbrevs(d, off, abbrev, attr, nil, nil) < 0){
|
|
|
|
free(abbrev);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(d->acache.a);
|
|
|
|
d->acache.a = abbrev;
|
|
|
|
d->acache.na = nabbrev;
|
|
|
|
d->acache.off = off;
|
|
|
|
|
|
|
|
*aa = abbrev;
|
|
|
|
return nabbrev;
|
2011-05-16 13:12:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parseabbrevs(Dwarf *d, ulong off, DwarfAbbrev *abbrev, DwarfAttr *attr, int *pnabbrev, int *pnattr)
|
|
|
|
{
|
2011-06-01 20:36:40 +00:00
|
|
|
int i, nabbrev, nattr, haskids;
|
|
|
|
ulong num, tag, name, form;
|
|
|
|
DwarfBuf b;
|
|
|
|
|
|
|
|
if(off >= d->abbrev.len){
|
|
|
|
werrstr("bad abbrev section offset 0x%lux >= 0x%lux", off, d->abbrev.len);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&b, 0, sizeof b);
|
|
|
|
b.p = d->abbrev.data + off;
|
|
|
|
b.ep = d->abbrev.data + d->abbrev.len;
|
|
|
|
|
|
|
|
nabbrev = 0;
|
|
|
|
nattr = 0;
|
|
|
|
for(;;){
|
|
|
|
if(b.p == nil){
|
|
|
|
werrstr("malformed abbrev data");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
num = dwarfget128(&b);
|
|
|
|
if(num == 0)
|
|
|
|
break;
|
|
|
|
tag = dwarfget128(&b);
|
2011-07-08 11:16:26 +00:00
|
|
|
werrstr("abbrev: num %d tag %x @ %x", num, tag, b.p - d->abbrev.data);
|
2011-06-01 20:36:40 +00:00
|
|
|
haskids = dwarfget1(&b);
|
|
|
|
for(i=0;; i++){
|
|
|
|
name = dwarfget128(&b);
|
|
|
|
form = dwarfget128(&b);
|
|
|
|
assert(form < 0x3000);
|
|
|
|
if(name == 0 && form == 0)
|
|
|
|
break;
|
|
|
|
if(attr){
|
|
|
|
attr[i].name = name;
|
|
|
|
attr[i].form = form;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(abbrev){
|
|
|
|
abbrev->num = num;
|
|
|
|
abbrev->tag = tag;
|
|
|
|
abbrev->haskids = haskids;
|
|
|
|
abbrev->attr = attr;
|
|
|
|
abbrev->nattr = i;
|
|
|
|
abbrev++;
|
|
|
|
attr += i;
|
|
|
|
}
|
|
|
|
nabbrev++;
|
|
|
|
nattr += i;
|
|
|
|
}
|
|
|
|
if(pnabbrev)
|
|
|
|
*pnabbrev = nabbrev;
|
|
|
|
if(pnattr)
|
|
|
|
*pnattr = nattr;
|
|
|
|
return 0;
|
2011-05-16 13:12:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static DwarfAbbrev*
|
|
|
|
findabbrev(DwarfAbbrev *a, int na, ulong num)
|
|
|
|
{
|
2011-06-01 20:36:40 +00:00
|
|
|
int i;
|
|
|
|
|
2011-07-08 11:16:26 +00:00
|
|
|
for(i=0; i<na; i++) {
|
|
|
|
if(a[i].num == num) {
|
2011-06-01 20:36:40 +00:00
|
|
|
return &a[i];
|
2011-07-08 11:16:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
werrstr("abbrev not found (%x)", na);
|
2011-06-01 20:36:40 +00:00
|
|
|
return nil;
|
2011-05-16 13:12:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DwarfAbbrev*
|
|
|
|
dwarfgetabbrev(Dwarf *d, ulong off, ulong num)
|
|
|
|
{
|
2011-06-01 20:36:40 +00:00
|
|
|
DwarfAbbrev *a;
|
|
|
|
int na;
|
2011-07-08 11:16:26 +00:00
|
|
|
werrstr("want num %d\n", num);
|
2011-06-01 20:36:40 +00:00
|
|
|
if((na = loadabbrevs(d, off, &a)) < 0){
|
|
|
|
werrstr("loadabbrevs: %r");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
return findabbrev(a, na, num);
|
2011-05-16 13:12:07 +00:00
|
|
|
}
|
|
|
|
|