2 * Dwarf info parse and search.
8 #include <reactos/rossym.h>
9 #include "rossympriv.h"
20 DwarfAttrSibling
= 0x01,
21 DwarfAttrLocation
= 0x02,
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,
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,
95 FormDwarfBlock2
= 0x03,
96 FormDwarfBlock4
= 0x04,
101 FormDwarfBlock
= 0x09,
102 FormDwarfBlock1
= 0x0A,
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
*);
126 dwarflookupnameinunit(Dwarf
*d
, ulong unit
, char *name
, DwarfSym
*s
)
128 if(dwarfenumunit(d
, unit
, s
) < 0)
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)
135 werrstr("symbol '%s' not found", name
);
141 dwarflookupsubname(Dwarf
*d
, DwarfSym
*parent
, char *name
, DwarfSym
*s
)
144 while(dwarfnextsymat(d
, s
, parent
->depth
+1))
145 if(s
->attrs
.name
&& strcmp(s
->attrs
.name
, name
) == 0)
147 werrstr("symbol '%s' not found", name
);
152 dwarflookuptag(Dwarf
*d
, ulong unit
, ulong tag
, DwarfSym
*s
)
154 if(dwarfenumunit(d
, unit
, s
) < 0) {
158 dwarfnextsymat(d
, s
, 0); /* s is now the CompileUnit */
159 if(s
->attrs
.tag
== tag
) {
162 while(dwarfnextsymat(d
, s
, 1) == 1)
163 if(s
->attrs
.tag
== tag
) {
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(dwarfnextsymat(d
, s
, 0) != 1)
182 dwarflookupfn(Dwarf
*d
, ulong unit
, ulong pc
, DwarfSym
*s
)
184 if(dwarfenumunit(d
, unit
, s
) < 0)
187 if(dwarfnextsymat(d
, s
, 0) != 1)
189 /* s is now the CompileUnit */
191 while(dwarfnextsymat(d
, s
, 1) == 1){
192 if(s
->attrs
.tag
!= TagSubprogram
)
194 if(s
->attrs
.lowpc
<= pc
&& pc
< s
->attrs
.highpc
)
197 werrstr("fn containing pc 0x%lux not found", pc
);
202 dwarfenumunit(Dwarf
*d
, ulong unit
, DwarfSym
*s
)
207 if(unit
>= d
->info
.len
){
208 werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit
, d
->info
.len
);
211 memset(s
, 0, sizeof *s
);
212 memset(&s
->b
, 0, sizeof s
->b
);
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
;
220 if(s
->b
.ep
- s
->b
.p
< len
){
222 werrstr("bad dwarf unit header at unit 0x%lux", unit
);
225 s
->b
.ep
= s
->b
.p
+len
;
226 if((i
=dwarfget2(&s
->b
)) != 2)
228 aoff
= dwarfget4(&s
->b
);
229 s
->b
.addrsize
= dwarfget1(&s
->b
);
231 d
->addrsize
= s
->b
.addrsize
;
242 dwarfenum(Dwarf
*d
, DwarfSym
*s
)
244 if(dwarfenumunit(d
, 0, s
) < 0)
251 dwarfnextsym(Dwarf
*d
, DwarfSym
*s
)
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) {
270 s
->uoff
= s
->b
.p
- (d
->info
.data
+s
->unit
);
271 num
= dwarfget128(&s
->b
);
281 a
= dwarfgetabbrev(d
, s
->aoff
, num
);
283 werrstr("getabbrev %ud %ud for %ud,%ud: %r\n", s
->aoff
, num
, s
->unit
, s
->uoff
);
286 if(parseattrs(&s
->b
, s
->unit
, a
, &s
->attrs
) < 0) {
293 dwarfnextsymat(Dwarf
*d
, DwarfSym
*s
, int depth
)
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;
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
316 if((r
= dwarfnextsym(d
, &t
)) != 1) {
320 /* went too far - nothing to see */
324 if(t
.depth
== depth
) {
330 typedef struct Parse Parse
;
338 #define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x)
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
},
405 static Parse ptab
[DwarfAttrMax
];
408 parseattrs(DwarfBuf
*b
, ulong unit
, DwarfAbbrev
*a
, DwarfAttrs
*attrs
)
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
];
419 memset(attrs
, 0, sizeof *attrs
);
421 attrs
->haskids
= a
->haskids
;
423 for(i
=0; i
<a
->nattr
; i
++){
426 if(n
< 0 || n
>= DwarfAttrMax
|| ptab
[n
].name
==0){
428 werrstr("dwarf parse attrs: unexpected attribute name 0x%x", n
);
429 continue; //return -1;
431 v
= (char*)attrs
+ ptab
[n
].off
;
433 if(f
== FormIndirect
)
435 if((ptab
[n
].type
&(TConstant
|TReference
|TAddress
))
436 && getulong(b
, f
, unit
, v
, &got
) >= 0)
438 else if((ptab
[n
].type
&TFlag
) && getuchar(b
, f
, v
) >= 0)
440 else if((ptab
[n
].type
&TString
) && getstring(b
, f
, v
) >= 0)
442 else if((ptab
[n
].type
&TBlock
) && getblock(b
, f
, v
) >= 0)
445 if(skipform(b
, f
) < 0){
447 werrstr("dwarf parse attrs: cannot skip form %d", f
);
451 if(got
== TBlock
&& (ptab
[n
].type
&TConstant
))
452 got
= constblock(b
->d
, v
, v
);
453 *((uchar
*)attrs
+ptab
[n
].haveoff
) = got
;
459 getulong(DwarfBuf
*b
, int form
, ulong unit
, ulong
*u
, int *type
)
471 *u
= dwarfgetaddr(b
);
476 /* absolute ref in .debug_info */
478 *u
= dwarfgetaddr(b
);
512 if(uv
!= *u
&& ++nbad
== 1)
513 werrstr("dwarf: truncating 64-bit attribute constants");
516 *u
= dwarfget128s(b
);
527 getuchar(DwarfBuf
*b
, int form
, uchar
*u
)
540 getstring(DwarfBuf
*b
, int form
, char **s
)
550 *s
= dwarfgetstring(b
);
555 if(u
>= b
->d
->str
.len
){
557 werrstr("dwarf: bad string pointer 0x%lux in attribute", u
);
558 /* don't return error - maybe can proceed */
561 *s
= (char*)b
->d
->str
.data
+ u
;
568 getblock(DwarfBuf
*b
, int form
, DwarfBlock
*bl
)
578 case FormDwarfBlock1
:
581 case FormDwarfBlock2
:
584 case FormDwarfBlock4
:
587 bl
->data
= dwarfgetnref(b
, n
);
596 constblock(Dwarf
*d
, DwarfBlock
*bl
, ulong
*pval
)
600 memset(&b
, 0, sizeof b
);
602 b
.ep
= bl
->data
+bl
->len
;
605 switch(dwarfget1(&b
)){
607 *pval
= dwarfgetaddr(&b
);
610 *pval
= dwarfget1(&b
);
613 *pval
= (schar
)dwarfget1(&b
);
616 *pval
= dwarfget2(&b
);
619 *pval
= (s16int
)dwarfget2(&b
);
622 *pval
= dwarfget4(&b
);
625 *pval
= (s32int
)dwarfget4(&b
);
628 *pval
= (u64int
)dwarfget8(&b
);
631 *pval
= (s64int
)dwarfget8(&b
);
634 *pval
= dwarfget128(&b
);
637 *pval
= dwarfget128s(&b
);
640 *pval
= dwarfget128(&b
);
649 skipform(DwarfBuf
*b
, int form
)
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)