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