xref: /reactos/sdk/lib/rossym/dwarfinfo.c (revision 98e8827a)
1 /*
2  * Dwarf info parse and search.
3  */
4 
5 #define NTOSAPI
6 #include <ntifs.h>
7 #include <ndk/ntndk.h>
8 #include <reactos/rossym.h>
9 #include "rossympriv.h"
10 #include <ntimage.h>
11 
12 #define NDEBUG
13 #include <debug.h>
14 
15 #include "dwarf.h"
16 #include <windef.h>
17 
18 enum
19 {
20 	DwarfAttrSibling = 0x01,
21 	DwarfAttrLocation = 0x02,
22 	DwarfAttrName = 0x03,
23 	DwarfAttrOrdering = 0x09,
24 	DwarfAttrByteSize = 0x0B,
25 	DwarfAttrBitOffset = 0x0C,
26 	DwarfAttrBitSize = 0x0D,
27 	DwarfAttrStmtList = 0x10,
28 	DwarfAttrLowpc = 0x11,
29 	DwarfAttrHighpc = 0x12,
30 	DwarfAttrLanguage = 0x13,
31 	DwarfAttrDiscr = 0x15,
32 	DwarfAttrDiscrValue = 0x16,
33 	DwarfAttrVisibility = 0x17,
34 	DwarfAttrImport = 0x18,
35 	DwarfAttrStringLength = 0x19,
36 	DwarfAttrCommonRef = 0x1A,
37 	DwarfAttrCompDir = 0x1B,
38 	DwarfAttrConstValue = 0x1C,
39 	DwarfAttrContainingType = 0x1D,
40 	DwarfAttrDefaultValue = 0x1E,
41 	DwarfAttrInline = 0x20,
42 	DwarfAttrIsOptional = 0x21,
43 	DwarfAttrLowerBound = 0x22,
44 	DwarfAttrProducer = 0x25,
45 	DwarfAttrPrototyped = 0x27,
46 	DwarfAttrReturnAddr = 0x2A,
47 	DwarfAttrStartScope = 0x2C,
48 	DwarfAttrStrideSize = 0x2E,
49 	DwarfAttrUpperBound = 0x2F,
50 	DwarfAttrAbstractOrigin = 0x31,
51 	DwarfAttrAccessibility = 0x32,
52 	DwarfAttrAddrClass = 0x33,
53 	DwarfAttrArtificial = 0x34,
54 	DwarfAttrBaseTypes = 0x35,
55 	DwarfAttrCalling = 0x36,
56 	DwarfAttrCount = 0x37,
57 	DwarfAttrDataMemberLoc = 0x38,
58 	DwarfAttrDeclColumn = 0x39,
59 	DwarfAttrDeclFile = 0x3A,
60 	DwarfAttrDeclLine = 0x3B,
61 	DwarfAttrDeclaration = 0x3C,
62 	DwarfAttrDiscrList = 0x3D,
63 	DwarfAttrEncoding = 0x3E,
64 	DwarfAttrExternal = 0x3F,
65 	DwarfAttrFrameBase = 0x40,
66 	DwarfAttrFriend = 0x41,
67 	DwarfAttrIdentifierCase = 0x42,
68 	DwarfAttrMacroInfo = 0x43,
69 	DwarfAttrNamelistItem = 0x44,
70 	DwarfAttrPriority = 0x45,
71 	DwarfAttrSegment = 0x46,
72 	DwarfAttrSpecification = 0x47,
73 	DwarfAttrStaticLink = 0x48,
74 	DwarfAttrType = 0x49,
75 	DwarfAttrUseLocation = 0x4A,
76 	DwarfAttrVarParam = 0x4B,
77 	DwarfAttrVirtuality = 0x4C,
78 	DwarfAttrVtableElemLoc = 0x4D,
79 	DwarfAttrAllocated = 0x4E,
80 	DwarfAttrAssociated = 0x4F,
81 	DwarfAttrDataLocation = 0x50,
82 	DwarfAttrStride = 0x51,
83 	DwarfAttrEntrypc = 0x52,
84 	DwarfAttrUseUTF8 = 0x53,
85 	DwarfAttrExtension = 0x54,
86 	DwarfAttrRanges = 0x55,
87 	DwarfAttrTrampoline = 0x56,
88 	DwarfAttrCallColumn = 0x57,
89 	DwarfAttrCallFile = 0x58,
90 	DwarfAttrCallLine = 0x59,
91 	DwarfAttrDescription = 0x5A,
92 	DwarfAttrMax,
93 
94 	FormAddr = 0x01,
95 	FormDwarfBlock2 = 0x03,
96 	FormDwarfBlock4 = 0x04,
97 	FormData2 = 0x05,
98 	FormData4 = 0x06,
99 	FormData8 = 0x07,
100 	FormString = 0x08,
101 	FormDwarfBlock = 0x09,
102 	FormDwarfBlock1 = 0x0A,
103 	FormData1 = 0x0B,
104 	FormFlag = 0x0C,
105 	FormSdata = 0x0D,
106 	FormStrp = 0x0E,
107 	FormUdata = 0x0F,
108 	FormRefAddr = 0x10,
109 	FormRef1 = 0x11,
110 	FormRef2 = 0x12,
111 	FormRef4 = 0x13,
112 	FormRef8 = 0x14,
113 	FormRefUdata = 0x15,
114 	FormIndirect = 0x16
115 };
116 
117 static int parseattrs(DwarfBuf*, ulong, DwarfAbbrev*, DwarfAttrs*);
118 static int getulong(DwarfBuf*, int, ulong, ulong*, int*);
119 static int getuchar(DwarfBuf*, int, uchar*);
120 static int getstring(DwarfBuf*, int, char**);
121 static int getblock(DwarfBuf*, int, DwarfBlock*);
122 static int skipform(DwarfBuf*, int);
123 static int constblock(Dwarf*, DwarfBlock*, ulong*);
124 
125 int
126 dwarflookupnameinunit(Dwarf *d, ulong unit, char *name, DwarfSym *s)
127 {
128 	if(dwarfenumunit(d, unit, s) < 0)
129 		return -1;
130 
131 	dwarfnextsymat(d, s, 0);	/* s is now the CompileUnit */
132 	while(dwarfnextsymat(d, s, 1) == 1)
133 		if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
134 			return 0;
135 	werrstr("symbol '%s' not found", name);
136 	return -1;
137 }
138 
139 
140 int
141 dwarflookupsubname(Dwarf *d, DwarfSym *parent, char *name, DwarfSym *s)
142 {
143 	*s = *parent;
144 	while(dwarfnextsymat(d, s, parent->depth+1))
145 		if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
146 			return 0;
147 	werrstr("symbol '%s' not found", name);
148 	return -1;
149 }
150 
151 int
152 dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
153 {
154 	if(dwarfenumunit(d, unit, s) < 0) {
155 		return -1;
156 	}
157 
158 	dwarfnextsymat(d, s, 0);	/* s is now the CompileUnit */
159 	if(s->attrs.tag == tag) {
160 		return 0;
161 	}
162 	while(dwarfnextsymat(d, s, 1) == 1)
163 		if(s->attrs.tag == tag) {
164 			return 0;
165 		}
166 	werrstr("symbol with tag 0x%lux not found", tag);
167 	return -1;
168 }
169 
170 int
171 dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s)
172 {
173 	if(dwarfenumunit(d, unit, s) < 0)
174 		return -1;
175 	s->b.p = d->info.data + unit + off;
176 	if(dwarfnextsymat(d, s, 0) != 1)
177 		return -1;
178 	return 0;
179 }
180 
181 int
182 dwarflookupfn(Dwarf *d, ulong unit, ulong pc, DwarfSym *s)
183 {
184 	if(dwarfenumunit(d, unit, s) < 0)
185 		return -1;
186 
187 	if(dwarfnextsymat(d, s, 0) != 1)
188 		return -1;
189 	/* s is now the CompileUnit */
190 
191 	while(dwarfnextsymat(d, s, 1) == 1){
192 		if(s->attrs.tag != TagSubprogram)
193 			continue;
194 		if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
195 			return 0;
196 	}
197 	werrstr("fn containing pc 0x%lux not found", pc);
198 	return -1;
199 }
200 
201 int
202 dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
203 {
204 	int i;
205 	ulong aoff, len;
206 
207 	if(unit >= d->info.len){
208 		werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit, d->info.len);
209 		return -1;
210 	}
211 	memset(s, 0, sizeof *s);
212 	memset(&s->b, 0, sizeof s->b);
213 
214 	s->b.d = d;
215 	s->b.p = d->info.data + unit;
216 	s->b.ep = d->info.data + d->info.len;
217 	len = dwarfget4(&s->b);
218 	s->nextunit = unit + 4 + len;
219 
220 	if(s->b.ep - s->b.p < len){
221 	badheader:
222 		werrstr("bad dwarf unit header at unit 0x%lux", unit);
223 		return -1;
224 	}
225 	s->b.ep = s->b.p+len;
226 	if((i=dwarfget2(&s->b)) != 2)
227 		goto badheader;
228 	aoff = dwarfget4(&s->b);
229 	s->b.addrsize = dwarfget1(&s->b);
230 	if(d->addrsize == 0)
231 		d->addrsize = s->b.addrsize;
232 	if(s->b.p == nil)
233 		goto badheader;
234 
235 	s->aoff = aoff;
236 	s->unit = unit;
237 	s->depth = 0;
238 	return 0;
239 }
240 
241 int
242 dwarfenum(Dwarf *d, DwarfSym *s)
243 {
244 	if(dwarfenumunit(d, 0, s) < 0)
245 		return -1;
246 	s->allunits = 1;
247 	return 0;
248 }
249 
250 int
251 dwarfnextsym(Dwarf *d, DwarfSym *s)
252 {
253 	ulong num;
254 	DwarfAbbrev *a;
255 
256 	if(s->attrs.haskids)
257 		s->depth++;
258 top:
259 	if(s->b.p >= s->b.ep){
260 		if(s->allunits && s->nextunit < d->info.len){
261 			if(dwarfenumunit(d, s->nextunit, s) < 0) {
262 				return -1;
263 			}
264 			s->allunits = 1;
265 			goto top;
266 		}
267 		return 0;
268 	}
269 
270 	s->uoff = s->b.p - (d->info.data+s->unit);
271 	num = dwarfget128(&s->b);
272 	if(num == 0){
273 		if(s->depth == 0) {
274 			return 0;
275 		}
276 		if(s->depth > 0)
277 			s->depth--;
278 		goto top;
279 	}
280 
281 	a = dwarfgetabbrev(d, s->aoff, num);
282 	if(a == nil){
283 		werrstr("getabbrev %ud %ud for %ud,%ud: %r\n", s->aoff, num, s->unit, s->uoff);
284 		return -1;
285 	}
286 	if(parseattrs(&s->b, s->unit, a, &s->attrs) < 0) {
287 		return -1;
288 	}
289 	return 1;
290 }
291 
292 int
293 dwarfnextsymat(Dwarf *d, DwarfSym *s, int depth)
294 {
295 	int r;
296 	DwarfSym t;
297 	uint sib;
298 
299 	if(s->depth == depth && s->attrs.have.sibling){
300 		sib = s->attrs.sibling;
301 		if(sib < d->info.len && d->info.data+sib >= s->b.p)
302 			s->b.p = d->info.data+sib;
303 		s->attrs.haskids = 0;
304 	}
305 
306 	/*
307 	 * The funny game with t and s make sure that
308 	 * if we get to the end of a run of a particular
309 	 * depth, we leave s so that a call to nextsymat with depth-1
310 	 * will actually produce the desired guy.  We could change
311 	 * the interface to dwarfnextsym instead, but I'm scared
312 	 * to touch it.
313 	 */
314 	t = *s;
315 	for(;;){
316 		if((r = dwarfnextsym(d, &t)) != 1) {
317 			return r;
318 		}
319 		if(t.depth < depth){
320 			/* went too far - nothing to see */
321 			return 0;
322 		}
323 		*s = t;
324 		if(t.depth == depth) {
325 			return 1;
326 		}
327 	}
328 }
329 
330 typedef struct Parse Parse;
331 struct Parse {
332 	int name;
333 	int off;
334 	int haveoff;
335 	int type;
336 };
337 
338 #define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x)
339 
340 static Parse plist[] = {	/* Font Tab 4 */
341 	{ DwarfAttrAbstractOrigin,	OFFSET(abstractorigin),		TReference },
342 	{ DwarfAttrAccessibility,	OFFSET(accessibility),		TConstant },
343 	{ DwarfAttrAddrClass, 		OFFSET(addrclass), 			TConstant },
344 	{ DwarfAttrArtificial,		OFFSET(isartificial), 		TFlag },
345 	{ DwarfAttrBaseTypes,		OFFSET(basetypes),			TReference },
346 	{ DwarfAttrBitOffset,		OFFSET(bitoffset),			TConstant },
347 	{ DwarfAttrBitSize,		OFFSET(bitsize),			TConstant },
348 	{ DwarfAttrByteSize,		OFFSET(bytesize),			TConstant },
349 	{ DwarfAttrCalling,		OFFSET(calling),			TConstant },
350 	{ DwarfAttrCommonRef,		OFFSET(commonref),			TReference },
351 	{ DwarfAttrCompDir,		OFFSET(compdir),			TString },
352 	{ DwarfAttrConstValue,		OFFSET(constvalue),			TString|TConstant|TBlock },
353 	{ DwarfAttrContainingType,	OFFSET(containingtype),		TReference },
354 	{ DwarfAttrCount,			OFFSET(count),				TConstant|TReference },
355 	{ DwarfAttrDataMemberLoc,	OFFSET(datamemberloc),		TBlock|TConstant|TReference },
356 	{ DwarfAttrDeclColumn,		OFFSET(declcolumn),			TConstant },
357 	{ DwarfAttrDeclFile,		OFFSET(declfile),			TConstant },
358 	{ DwarfAttrDeclLine,		OFFSET(declline),			TConstant },
359 	{ DwarfAttrDeclaration,	OFFSET(isdeclaration),		TFlag },
360 	{ DwarfAttrDefaultValue,	OFFSET(defaultvalue),		TReference },
361 	{ DwarfAttrDiscr,			OFFSET(discr),				TReference },
362 	{ DwarfAttrDiscrList,		OFFSET(discrlist),			TBlock },
363 	{ DwarfAttrDiscrValue,		OFFSET(discrvalue),			TConstant },
364 	{ DwarfAttrEncoding,		OFFSET(encoding),			TConstant },
365 	{ DwarfAttrExternal,		OFFSET(isexternal),			TFlag },
366 	{ DwarfAttrFrameBase,		OFFSET(framebase),			TBlock|TConstant },
367 	{ DwarfAttrFriend,			OFFSET(friend),				TReference },
368 	{ DwarfAttrHighpc,			OFFSET(highpc),				TAddress },
369 	{ DwarfAttrEntrypc,         OFFSET(entrypc),            TAddress },
370 	{ DwarfAttrIdentifierCase,	OFFSET(identifiercase),		TConstant },
371 	{ DwarfAttrImport,			OFFSET(import),				TReference },
372 	{ DwarfAttrInline,			OFFSET(inlined),			TConstant },
373 	{ DwarfAttrIsOptional,		OFFSET(isoptional),			TFlag },
374 	{ DwarfAttrLanguage,		OFFSET(language),			TConstant },
375 	{ DwarfAttrLocation,		OFFSET(location),			TBlock|TConstant },
376 	{ DwarfAttrLowerBound,		OFFSET(lowerbound),			TConstant|TReference },
377 	{ DwarfAttrLowpc,			OFFSET(lowpc),				TAddress },
378 	{ DwarfAttrMacroInfo,		OFFSET(macroinfo),			TConstant },
379 	{ DwarfAttrName,			OFFSET(name),				TString },
380 	{ DwarfAttrNamelistItem,	OFFSET(namelistitem),		TBlock },
381 	{ DwarfAttrOrdering, 		OFFSET(ordering),			TConstant },
382 	{ DwarfAttrPriority,		OFFSET(priority),			TReference },
383 	{ DwarfAttrProducer,		OFFSET(producer),			TString },
384 	{ DwarfAttrPrototyped,		OFFSET(isprototyped),		TFlag },
385 	{ DwarfAttrRanges,			OFFSET(ranges),				TReference },
386 	{ DwarfAttrReturnAddr,		OFFSET(returnaddr),			TBlock|TConstant },
387 	{ DwarfAttrSegment,		OFFSET(segment),			TBlock|TConstant },
388 	{ DwarfAttrSibling,		OFFSET(sibling),			TReference },
389 	{ DwarfAttrSpecification,	OFFSET(specification),		TReference },
390 	{ DwarfAttrStartScope,		OFFSET(startscope),			TConstant },
391 	{ DwarfAttrStaticLink,		OFFSET(staticlink),			TBlock|TConstant },
392 	{ DwarfAttrStmtList,		OFFSET(stmtlist),			TConstant },
393 	{ DwarfAttrStrideSize,		OFFSET(stridesize),			TConstant },
394 	{ DwarfAttrStringLength,	OFFSET(stringlength),		TBlock|TConstant },
395 	{ DwarfAttrType,			OFFSET(type),				TReference },
396 	{ DwarfAttrUpperBound,		OFFSET(upperbound),			TConstant|TReference },
397 	{ DwarfAttrUseLocation,	OFFSET(uselocation),		TBlock|TConstant },
398 	{ DwarfAttrVarParam,		OFFSET(isvarparam),			TFlag },
399 	{ DwarfAttrVirtuality,		OFFSET(virtuality),			TConstant },
400 	{ DwarfAttrVisibility,		OFFSET(visibility),			TConstant },
401 	{ DwarfAttrVtableElemLoc,	OFFSET(vtableelemloc),		TBlock|TReference },
402 	{ }
403 };
404 
405 static Parse ptab[DwarfAttrMax];
406 
407 static int
408 parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
409 {
410 	int i, f, n, got;
411 	static int nbad;
412 	void *v;
413 
414 	/* initialize ptab first time through for quick access */
415 	if(ptab[DwarfAttrName].name != DwarfAttrName)
416 		for(i=0; plist[i].name; i++)
417 			ptab[plist[i].name] = plist[i];
418 
419 	memset(attrs, 0, sizeof *attrs);
420 	attrs->tag = a->tag;
421 	attrs->haskids = a->haskids;
422 
423 	for(i=0; i<a->nattr; i++){
424 		n = a->attr[i].name;
425 		f = a->attr[i].form;
426 		if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0){
427 			if(++nbad == 1)
428 				werrstr("dwarf parse attrs: unexpected attribute name 0x%x", n);
429 			continue; //return -1;
430 		}
431 		v = (char*)attrs + ptab[n].off;
432 		got = 0;
433 		if(f == FormIndirect)
434 			f = dwarfget128(b);
435 		if((ptab[n].type&(TConstant|TReference|TAddress))
436 		&& getulong(b, f, unit, v, &got) >= 0)
437 			;
438 		else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
439 			got = TFlag;
440 		else if((ptab[n].type&TString) && getstring(b, f, v) >= 0)
441 			got = TString;
442 		else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0)
443 			got = TBlock;
444 		else{
445 			if(skipform(b, f) < 0){
446 				if(++nbad == 1)
447 					werrstr("dwarf parse attrs: cannot skip form %d", f);
448 				return -1;
449 			}
450 		}
451 		if(got == TBlock && (ptab[n].type&TConstant))
452 			got = constblock(b->d, v, v);
453 		*((uchar*)attrs+ptab[n].haveoff) = got;
454 	}
455 	return 0;
456 }
457 
458 static int
459 getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type)
460 {
461 	static int nbad;
462 	uvlong uv;
463 
464 	switch(form){
465 	default:
466 		return -1;
467 
468 	/* addresses */
469 	case FormAddr:
470 		*type = TAddress;
471 		*u = dwarfgetaddr(b);
472 		return 0;
473 
474 	/* references */
475 	case FormRefAddr:
476 		/* absolute ref in .debug_info */
477 		*type = TReference;
478 		*u = dwarfgetaddr(b);
479 		return 0;
480 	case FormRef1:
481 		*u = dwarfget1(b);
482 		goto relativeref;
483 	case FormRef2:
484 		*u = dwarfget2(b);
485 		goto relativeref;
486 	case FormRef4:
487 		*u = dwarfget4(b);
488 		goto relativeref;
489 	case FormRef8:
490 		*u = dwarfget8(b);
491 		goto relativeref;
492 	case FormRefUdata:
493 		*u = dwarfget128(b);
494 	relativeref:
495 		*u += unit;
496 		*type = TReference;
497 		return 0;
498 
499 	/* constants */
500 	case FormData1:
501 		*u = dwarfget1(b);
502 		goto constant;
503 	case FormData2:
504 		*u = dwarfget2(b);
505 		goto constant;
506 	case FormData4:
507 		*u = dwarfget4(b);
508 		goto constant;
509 	case FormData8:
510 		uv = dwarfget8(b);
511 		*u = uv;
512 		if(uv != *u && ++nbad == 1)
513 			werrstr("dwarf: truncating 64-bit attribute constants");
514 		goto constant;
515 	case FormSdata:
516 		*u = dwarfget128s(b);
517 		goto constant;
518 	case FormUdata:
519 		*u = dwarfget128(b);
520 	constant:
521 		*type = TConstant;
522 		return 0;
523 	}
524 }
525 
526 static int
527 getuchar(DwarfBuf *b, int form, uchar *u)
528 {
529 	switch(form){
530 	default:
531 		return -1;
532 
533 	case FormFlag:
534 		*u = dwarfget1(b);
535 		return 0;
536 	}
537 }
538 
539 static int
540 getstring(DwarfBuf *b, int form, char **s)
541 {
542 	static int nbad;
543 	ulong u;
544 
545 	switch(form){
546 	default:
547 		return -1;
548 
549 	case FormString:
550 		*s = dwarfgetstring(b);
551 		return 0;
552 
553 	case FormStrp:
554 		u = dwarfget4(b);
555 		if(u >= b->d->str.len){
556 			if(++nbad == 1)
557 				werrstr("dwarf: bad string pointer 0x%lux in attribute", u);
558 			/* don't return error - maybe can proceed */
559 			*s = nil;
560 		}else
561 			*s = (char*)b->d->str.data + u;
562 		return 0;
563 
564 	}
565 }
566 
567 static int
568 getblock(DwarfBuf *b, int form, DwarfBlock *bl)
569 {
570 	ulong n;
571 
572 	switch(form){
573 	default:
574 		return -1;
575 	case FormDwarfBlock:
576 		n = dwarfget128(b);
577 		goto copyn;
578 	case FormDwarfBlock1:
579 		n = dwarfget1(b);
580 		goto copyn;
581 	case FormDwarfBlock2:
582 		n = dwarfget2(b);
583 		goto copyn;
584 	case FormDwarfBlock4:
585 		n = dwarfget4(b);
586 	copyn:
587 		bl->data = dwarfgetnref(b, n);
588 		bl->len = n;
589 		if(bl->data == nil)
590 			return -1;
591 		return 0;
592 	}
593 }
594 
595 static int
596 constblock(Dwarf *d, DwarfBlock *bl, ulong *pval)
597 {
598 	DwarfBuf b;
599 
600 	memset(&b, 0, sizeof b);
601 	b.p = bl->data;
602 	b.ep = bl->data+bl->len;
603 	b.d = d;
604 
605 	switch(dwarfget1(&b)){
606 	case OpAddr:
607 		*pval = dwarfgetaddr(&b);
608 		return TConstant;
609 	case OpConst1u:
610 		*pval = dwarfget1(&b);
611 		return TConstant;
612 	case OpConst1s:
613 		*pval = (schar)dwarfget1(&b);
614 		return TConstant;
615 	case OpConst2u:
616 		*pval = dwarfget2(&b);
617 		return TConstant;
618 	case OpConst2s:
619 		*pval = (s16int)dwarfget2(&b);
620 		return TConstant;
621 	case OpConst4u:
622 		*pval = dwarfget4(&b);
623 		return TConstant;
624 	case OpConst4s:
625 		*pval = (s32int)dwarfget4(&b);
626 		return TConstant;
627 	case OpConst8u:
628 		*pval = (u64int)dwarfget8(&b);
629 		return TConstant;
630 	case OpConst8s:
631 		*pval = (s64int)dwarfget8(&b);
632 		return TConstant;
633 	case OpConstu:
634 		*pval = dwarfget128(&b);
635 		return TConstant;
636 	case OpConsts:
637 		*pval = dwarfget128s(&b);
638 		return TConstant;
639 	case OpPlusUconst:
640 		*pval = dwarfget128(&b);
641 		return TConstant;
642 	default:
643 		return TBlock;
644 	}
645 }
646 
647 /* last resort */
648 static int
649 skipform(DwarfBuf *b, int form)
650 {
651 	int type;
652 	DwarfVal val;
653 
654 	if(getulong(b, form, 0, &val.c, &type) < 0
655 	&& getuchar(b, form, (uchar*)&val) < 0
656 	&& getstring(b, form, &val.s) < 0
657 	&& getblock(b, form, &val.b) < 0)
658 		return -1;
659 	return 0;
660 }
661 
662