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 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)
128 werrstr("symbol '%s' not found", name);
134 dwarflookupsubname(Dwarf *d, DwarfSym *parent, char *name, DwarfSym *s)
137 while(dwarfnextsymat(d, s, parent->depth+1))
138 if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
140 werrstr("symbol '%s' not found", name);
145 dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
147 if(dwarfenumunit(d, unit, s) < 0)
150 dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */
151 if(s->attrs.tag == tag)
153 while(dwarfnextsymat(d, s, 1) == 1)
154 if(s->attrs.tag == tag)
156 werrstr("symbol with tag 0x%lux not found", tag);
161 dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s)
163 if(dwarfenumunit(d, unit, s) < 0)
165 s->b.p = d->info.data + unit + off;
166 if(dwarfnextsymat(d, s, 0) != 1)
172 dwarflookupfn(Dwarf *d, ulong unit, ulong pc, DwarfSym *s)
174 if(dwarfenumunit(d, unit, s) < 0)
177 if(dwarfnextsymat(d, s, 0) != 1)
179 /* s is now the CompileUnit */
181 while(dwarfnextsymat(d, s, 1) == 1){
182 if(s->attrs.tag != TagSubprogram)
184 if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
187 werrstr("fn containing pc 0x%lux not found", pc);
192 dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
197 if(unit >= d->info.len){
198 werrstr("dwarf unit address 0x%lux >= 0x%lux out of range", unit, d->info.len);
201 memset(s, 0, sizeof *s);
202 memset(&s->b, 0, sizeof s->b);
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;
209 if(s->b.ep - s->b.p < len){
211 werrstr("bad dwarf unit header at unit 0x%lux", unit);
214 s->b.ep = s->b.p+len;
215 if((i=dwarfget2(&s->b)) != 2)
217 aoff = dwarfget4(&s->b);
218 s->b.addrsize = dwarfget1(&s->b);
220 d->addrsize = s->b.addrsize;
231 dwarfenum(Dwarf *d, DwarfSym *s)
233 if(dwarfenumunit(d, 0, s) < 0)
240 dwarfnextsym(Dwarf *d, DwarfSym *s)
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)
258 s->uoff = s->b.p - (d->info.data+s->unit);
259 num = dwarfget128(&s->b);
268 a = dwarfgetabbrev(d, s->aoff, num);
270 fprint(2, "getabbrev %ud %ud for %ud,%ud: %r\n", s->aoff, num, s->unit, s->uoff);
274 if(parseattrs(&s->b, s->unit, a, &s->attrs) < 0)
280 dwarfnextsymat(Dwarf *d, DwarfSym *s, int depth)
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;
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
303 if((r = dwarfnextsym(d, &t)) != 1)
306 /* went too far - nothing to see */
315 typedef struct Parse Parse;
323 #define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x)
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,
388 static Parse ptab[DwarfAttrMax];
391 parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
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];
402 memset(attrs, 0, sizeof *attrs);
404 attrs->haskids = a->haskids;
406 for(i=0; i<a->nattr; i++){
409 if(n < 0 || n >= nelem(ptab) || ptab[n].name==0){
411 fprint(2, "dwarf parse attrs: unexpected attribute name 0x%ux\n", n);
414 v = (char*)attrs + ptab[n].off;
416 if(f == FormIndirect)
418 if((ptab[n].type&(TConstant|TReference|TAddress))
419 && getulong(b, f, unit, v, &got) >= 0)
421 else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
423 else if((ptab[n].type&TString) && getstring(b, f, v) >= 0)
425 else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0)
428 if(skipform(b, f) < 0){
430 fprint(2, "dwarf parse attrs: cannot skip form %d\n", f);
434 if(got == TBlock && (ptab[n].type&TConstant))
435 got = constblock(b->d, v, v);
436 *((uchar*)attrs+ptab[n].haveoff) = got;
442 getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type)
454 *u = dwarfgetaddr(b);
459 /* absolute ref in .debug_info */
461 *u = dwarfgetaddr(b);
495 if(uv != *u && ++nbad == 1)
496 fprint(2, "dwarf: truncating 64-bit attribute constants\n");
499 *u = dwarfget128s(b);
510 getuchar(DwarfBuf *b, int form, uchar *u)
523 getstring(DwarfBuf *b, int form, char **s)
533 *s = dwarfgetstring(b);
538 if(u >= b->d->str.len){
540 fprint(2, "dwarf: bad string pointer 0x%lux in attribute\n", u);
541 /* don't return error - maybe can proceed */
544 *s = (char*)b->d->str.data + u;
551 getblock(DwarfBuf *b, int form, DwarfBlock *bl)
561 case FormDwarfBlock1:
564 case FormDwarfBlock2:
567 case FormDwarfBlock4:
570 bl->data = dwarfgetnref(b, n);
579 constblock(Dwarf *d, DwarfBlock *bl, ulong *pval)
583 memset(&b, 0, sizeof b);
585 b.ep = bl->data+bl->len;
588 switch(dwarfget1(&b)){
590 *pval = dwarfgetaddr(&b);
593 *pval = dwarfget1(&b);
596 *pval = (schar)dwarfget1(&b);
599 *pval = dwarfget2(&b);
602 *pval = (s16int)dwarfget2(&b);
605 *pval = dwarfget4(&b);
608 *pval = (s32int)dwarfget4(&b);
611 *pval = (u64int)dwarfget8(&b);
614 *pval = (s64int)dwarfget8(&b);
617 *pval = dwarfget128(&b);
620 *pval = dwarfget128s(&b);
623 *pval = dwarfget128(&b);
632 skipform(DwarfBuf *b, int form)
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)