2 * Dwarf info parse and search.
13 DwarfAttrSibling = 0x01,
14 DwarfAttrLocation = 0x02,
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,
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,
88 FormDwarfBlock2 = 0x03,
89 FormDwarfBlock4 = 0x04,
94 FormDwarfBlock = 0x09,
95 FormDwarfBlock1 = 0x0A,
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*);
119 dwarflookupnameinunit(Dwarf *d, ulong unit, char *name, DwarfSym *s)
121 if(dwarfenumunit(d, unit, s) < 0)
124 dwarfnextsym(d, s, 1); /* s is now the CompileUnit */
125 if(dwarfnextsym(d, s, 1) == 1){ /* s is now the first child of the compile unit */
127 if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
129 }while(dwarfnextsym(d, s, 0) == 1);
131 werrstr("symbol '%s' not found", name);
137 dwarflookupsubname(Dwarf *d, DwarfSym *parent, char *name, DwarfSym *s)
140 dwarfnextsym(d, s, 1);
141 if(s->depth == parent->depth+1)
143 if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
145 }while(dwarfnextsym(d, s, 0) == 1);
146 werrstr("symbol '%s' not found", name);
151 dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
153 if(dwarfenumunit(d, unit, s) < 0)
156 dwarfnextsym(d, s, 1); /* s is now the CompileUnit */
157 if(s->attrs.tag == tag)
160 if(dwarfnextsym(d, s, 1) == 1){ /* s is now the first child of the compile unit */
162 if(s->attrs.tag == tag)
164 }while(dwarfnextsym(d, s, 0) == 1);
166 werrstr("symbol with tag 0x%lux not found", tag);
171 dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s)
173 if(dwarfenumunit(d, unit, s) < 0)
175 s->b.p = d->info.data + unit + off;
176 if(dwarfnextsym(d, s, 1) != 1)
182 dwarflookupfn(Dwarf *d, ulong unit, ulong pc, DwarfSym *s)
184 if(dwarfenumunit(d, unit, s) < 0)
187 if(dwarfnextsym(d, s, 1) != 1)
189 /* s is now the CompileUnit */
191 if(dwarfnextsym(d, s, 1) == 1){ /* s is now the first child of the compile unit */
193 if(s->attrs.tag != TagSubprogram)
195 if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
197 }while(dwarfnextsym(d, s, 0) == 1);
199 werrstr("fn containing pc 0x%lux not found", pc);
204 dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
209 if(unit >= d->info.len){
210 werrstr("dwarf unit address 0x%lux >= 0x%lux out of range", unit, d->info.len);
213 memset(s, 0, sizeof *s);
214 memset(&s->b, 0, sizeof s->b);
216 s->b.p = d->info.data + unit;
217 s->b.ep = d->info.data + d->info.len;
218 len = dwarfget4(&s->b);
219 s->nextunit = unit + 4 + len;
221 if(s->b.ep - s->b.p < len){
223 werrstr("bad dwarf unit header at unit 0x%lux", unit);
226 s->b.ep = s->b.p+len;
227 if((i=dwarfget2(&s->b)) != 2)
229 aoff = dwarfget4(&s->b);
230 s->b.addrsize = dwarfget1(&s->b);
232 d->addrsize = s->b.addrsize;
243 dwarfenum(Dwarf *d, DwarfSym *s)
245 if(dwarfenumunit(d, 0, s) < 0)
252 _dwarfnextsym(Dwarf *d, DwarfSym *s)
260 if(s->b.p >= s->b.ep){
261 if(s->allunits && s->nextunit < d->info.len){
262 if(dwarfenumunit(d, s->nextunit, s) < 0)
270 s->uoff = s->b.p - (d->info.data+s->unit);
271 num = dwarfget128(&s->b);
280 a = dwarfgetabbrev(d, s->aoff, num);
282 fprint(2, "getabbrev %ud: %r\n", num);
285 if(parseattrs(&s->b, s->unit, a, &s->attrs) < 0)
291 dwarfnextsym(Dwarf *d, DwarfSym *s, int recurse)
298 return _dwarfnextsym(d, s);
301 if(s->attrs.have.sibling){
302 sib = s->attrs.sibling;
303 if(sib < d->info.len && d->info.data+sib >= s->b.p)
304 s->b.p = d->info.data+sib;
305 s->attrs.haskids = 0;
309 r = _dwarfnextsym(d, s);
312 }while(s->depth != depth);
318 typedef struct Parse Parse;
326 #define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x)
328 static Parse plist[] = { /* Font Tab 4 */
329 DwarfAttrAbstractOrigin, OFFSET(abstractorigin), TReference,
330 DwarfAttrAccessibility, OFFSET(accessibility), TConstant,
331 DwarfAttrAddrClass, OFFSET(addrclass), TConstant,
332 DwarfAttrArtificial, OFFSET(isartificial), TFlag,
333 DwarfAttrBaseTypes, OFFSET(basetypes), TReference,
334 DwarfAttrBitOffset, OFFSET(bitoffset), TConstant,
335 DwarfAttrBitSize, OFFSET(bitsize), TConstant,
336 DwarfAttrByteSize, OFFSET(bytesize), TConstant,
337 DwarfAttrCalling, OFFSET(calling), TConstant,
338 DwarfAttrCommonRef, OFFSET(commonref), TReference,
339 DwarfAttrCompDir, OFFSET(compdir), TString,
340 DwarfAttrConstValue, OFFSET(constvalue), TString|TConstant|TBlock,
341 DwarfAttrContainingType, OFFSET(containingtype), TReference,
342 DwarfAttrCount, OFFSET(count), TConstant|TReference,
343 DwarfAttrDataMemberLoc, OFFSET(datamemberloc), TBlock|TConstant|TReference,
344 DwarfAttrDeclColumn, OFFSET(declcolumn), TConstant,
345 DwarfAttrDeclFile, OFFSET(declfile), TConstant,
346 DwarfAttrDeclLine, OFFSET(declline), TConstant,
347 DwarfAttrDeclaration, OFFSET(isdeclaration), TFlag,
348 DwarfAttrDefaultValue, OFFSET(defaultvalue), TReference,
349 DwarfAttrDiscr, OFFSET(discr), TReference,
350 DwarfAttrDiscrList, OFFSET(discrlist), TBlock,
351 DwarfAttrDiscrValue, OFFSET(discrvalue), TConstant,
352 DwarfAttrEncoding, OFFSET(encoding), TConstant,
353 DwarfAttrExternal, OFFSET(isexternal), TFlag,
354 DwarfAttrFrameBase, OFFSET(framebase), TBlock|TConstant,
355 DwarfAttrFriend, OFFSET(friend), TReference,
356 DwarfAttrHighpc, OFFSET(highpc), TAddress,
357 DwarfAttrIdentifierCase, OFFSET(identifiercase), TConstant,
358 DwarfAttrImport, OFFSET(import), TReference,
359 DwarfAttrInline, OFFSET(inlined), TConstant,
360 DwarfAttrIsOptional, OFFSET(isoptional), TFlag,
361 DwarfAttrLanguage, OFFSET(language), TConstant,
362 DwarfAttrLocation, OFFSET(location), TBlock|TConstant,
363 DwarfAttrLowerBound, OFFSET(lowerbound), TConstant|TReference,
364 DwarfAttrLowpc, OFFSET(lowpc), TAddress,
365 DwarfAttrMacroInfo, OFFSET(macroinfo), TConstant,
366 DwarfAttrName, OFFSET(name), TString,
367 DwarfAttrNamelistItem, OFFSET(namelistitem), TBlock,
368 DwarfAttrOrdering, OFFSET(ordering), TConstant,
369 DwarfAttrPriority, OFFSET(priority), TReference,
370 DwarfAttrProducer, OFFSET(producer), TString,
371 DwarfAttrPrototyped, OFFSET(isprototyped), TFlag,
372 DwarfAttrRanges, OFFSET(ranges), TReference,
373 DwarfAttrReturnAddr, OFFSET(returnaddr), TBlock|TConstant,
374 DwarfAttrSegment, OFFSET(segment), TBlock|TConstant,
375 DwarfAttrSibling, OFFSET(sibling), TReference,
376 DwarfAttrSpecification, OFFSET(specification), TReference,
377 DwarfAttrStartScope, OFFSET(startscope), TConstant,
378 DwarfAttrStaticLink, OFFSET(staticlink), TBlock|TConstant,
379 DwarfAttrStmtList, OFFSET(stmtlist), TConstant,
380 DwarfAttrStrideSize, OFFSET(stridesize), TConstant,
381 DwarfAttrStringLength, OFFSET(stringlength), TBlock|TConstant,
382 DwarfAttrType, OFFSET(type), TReference,
383 DwarfAttrUpperBound, OFFSET(upperbound), TConstant|TReference,
384 DwarfAttrUseLocation, OFFSET(uselocation), TBlock|TConstant,
385 DwarfAttrVarParam, OFFSET(isvarparam), TFlag,
386 DwarfAttrVirtuality, OFFSET(virtuality), TConstant,
387 DwarfAttrVisibility, OFFSET(visibility), TConstant,
388 DwarfAttrVtableElemLoc, OFFSET(vtableelemloc), TBlock|TReference,
391 static Parse ptab[DwarfAttrMax];
394 parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
400 /* initialize ptab first time through for quick access */
401 if(ptab[DwarfAttrName].name != DwarfAttrName)
402 for(i=0; i<nelem(plist); i++)
403 ptab[plist[i].name] = plist[i];
405 memset(attrs, 0, sizeof *attrs);
407 attrs->haskids = a->haskids;
409 for(i=0; i<a->nattr; i++){
412 if(n < 0 || n >= nelem(ptab) || ptab[n].name==0){
414 fprint(2, "dwarf parse attrs: unexpected attribute name 0x%ux\n", n);
417 v = (char*)attrs + ptab[n].off;
419 if(f == FormIndirect)
421 if((ptab[n].type&(TConstant|TReference|TAddress))
422 && getulong(b, f, unit, v, &got) >= 0)
424 else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
426 else if((ptab[n].type&TString) && getstring(b, f, v) >= 0)
428 else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0)
431 if(skipform(b, f) < 0){
433 fprint(2, "dwarf parse attrs: cannot skip form %d\n", f);
437 if(got == TBlock && (ptab[n].type&TConstant))
438 got = constblock(b->d, v, v);
439 *((uchar*)attrs+ptab[n].haveoff) = got;
445 getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type)
457 *u = dwarfgetaddr(b);
462 /* absolute ref in .debug_info */
464 *u = dwarfgetaddr(b);
498 if(uv != *u && ++nbad == 1)
499 fprint(2, "dwarf: truncating 64-bit attribute constants\n");
502 *u = dwarfget128s(b);
513 getuchar(DwarfBuf *b, int form, uchar *u)
526 getstring(DwarfBuf *b, int form, char **s)
536 *s = dwarfgetstring(b);
541 if(u >= b->d->str.len){
543 fprint(2, "dwarf: bad string pointer 0x%lux in attribute\n", u);
544 /* don't return error - maybe can proceed */
547 *s = b->d->str.data + u;
554 getblock(DwarfBuf *b, int form, DwarfBlock *bl)
564 case FormDwarfBlock1:
567 case FormDwarfBlock2:
570 case FormDwarfBlock4:
573 bl->data = dwarfgetnref(b, n);
582 constblock(Dwarf *d, DwarfBlock *bl, ulong *pval)
586 memset(&b, 0, sizeof b);
588 b.ep = bl->data+bl->len;
591 switch(dwarfget1(&b)){
593 *pval = dwarfgetaddr(&b);
596 *pval = dwarfget1(&b);
599 *pval = (schar)dwarfget1(&b);
602 *pval = dwarfget2(&b);
605 *pval = (s16int)dwarfget2(&b);
608 *pval = dwarfget4(&b);
611 *pval = (s32int)dwarfget4(&b);
614 *pval = (u64int)dwarfget8(&b);
617 *pval = (s64int)dwarfget8(&b);
620 *pval = dwarfget128(&b);
623 *pval = dwarfget128s(&b);
626 *pval = dwarfget128(&b);
635 skipform(DwarfBuf *b, int form)
640 if(getulong(b, form, 0, &val.c, &type) < 0
641 && getuchar(b, form, (uchar*)&val) < 0
642 && getstring(b, form, &val.s) < 0
643 && getblock(b, form, &val.b) < 0)