plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

dwarfinfo.c (15367B)


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