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