xref: /reactos/sdk/lib/rossym/dwarfabbrev.c (revision 190b3da9)
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
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
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*
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*
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