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