[CONUTILS] Make the headers C++ compatible.
[reactos.git] / sdk / lib / rossym_new / dwarfabbrev.c
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