1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // DWARF debug information entry parser.
6 // An entry is a sequence of data items of a given format.
7 // The first word in the entry is an index into what DWARF
8 // calls the ``abbreviation table.'' An abbreviation is really
9 // just a type descriptor: it's an array of attribute tag/value format pairs.
18 // a single entry's description: a sequence of attributes
31 // a map from entry format ids to their descriptions
32 type abbrevTable
map[uint32]abbrev
34 // ParseAbbrev returns the abbreviation table that starts at byte off
35 // in the .debug_abbrev section.
36 func (d
*Data
) parseAbbrev(off
uint64, vers
int) (abbrevTable
, error
) {
37 if m
, ok
:= d
.abbrevCache
[off
]; ok
{
42 if off
> uint64(len(data
)) {
47 b
:= makeBuf(d
, unknownFormat
{}, "abbrev", 0, data
)
49 // Error handling is simplified by the buf getters
50 // returning an endless stream of 0s after an error.
51 m
:= make(abbrevTable
)
53 // Table ends with id == 0.
54 id
:= uint32(b
.uint())
59 // Walk over attributes, counting.
61 b1
:= b
// Read from copy of b.
67 if tag
== 0 && fmt
== 0 {
76 // Walk over attributes again, this time writing them down.
79 a
.children
= b
.uint8() != 0
80 a
.field
= make([]afield
, n
)
81 for i
:= range a
.field
{
82 a
.field
[i
].attr
= Attr(b
.uint())
83 a
.field
[i
].fmt
= format(b
.uint())
84 a
.field
[i
].class
= formToClass(a
.field
[i
].fmt
, a
.field
[i
].attr
, vers
, &b
)
94 d
.abbrevCache
[off
] = m
98 // attrIsExprloc indicates attributes that allow exprloc values that
99 // are encoded as block values in DWARF 2 and 3. See DWARF 4, Figure
101 var attrIsExprloc
= map[Attr
]bool{
106 AttrStringLength
: true,
107 AttrLowerBound
: true,
108 AttrReturnAddr
: true,
109 AttrStrideSize
: true,
110 AttrUpperBound
: true,
112 AttrDataMemberLoc
: true,
115 AttrStaticLink
: true,
116 AttrUseLocation
: true,
117 AttrVtableElemLoc
: true,
119 AttrAssociated
: true,
120 AttrDataLocation
: true,
124 // attrPtrClass indicates the *ptr class of attributes that have
125 // encoding formSecOffset in DWARF 4 or formData* in DWARF 2 and 3.
126 var attrPtrClass
= map[Attr
]Class
{
127 AttrLocation
: ClassLocListPtr
,
128 AttrStmtList
: ClassLinePtr
,
129 AttrStringLength
: ClassLocListPtr
,
130 AttrReturnAddr
: ClassLocListPtr
,
131 AttrStartScope
: ClassRangeListPtr
,
132 AttrDataMemberLoc
: ClassLocListPtr
,
133 AttrFrameBase
: ClassLocListPtr
,
134 AttrMacroInfo
: ClassMacPtr
,
135 AttrSegment
: ClassLocListPtr
,
136 AttrStaticLink
: ClassLocListPtr
,
137 AttrUseLocation
: ClassLocListPtr
,
138 AttrVtableElemLoc
: ClassLocListPtr
,
139 AttrRanges
: ClassRangeListPtr
,
142 // formToClass returns the DWARF 4 Class for the given form. If the
143 // DWARF version is less then 4, it will disambiguate some forms
144 // depending on the attribute.
145 func formToClass(form format
, attr Attr
, vers
int, b
*buf
) Class
{
148 b
.error("cannot determine class of unknown attribute form")
154 case formDwarfBlock1
, formDwarfBlock2
, formDwarfBlock4
, formDwarfBlock
:
155 // In DWARF 2 and 3, ClassExprLoc was encoded as a
156 // block. DWARF 4 distinguishes ClassBlock and
157 // ClassExprLoc, but there are no attributes that can
158 // be both, so we also promote ClassBlock values in
159 // DWARF 4 that should be ClassExprLoc in case
160 // producers get this wrong.
161 if attrIsExprloc
[attr
] {
166 case formData1
, formData2
, formData4
, formData8
, formSdata
, formUdata
:
167 // In DWARF 2 and 3, ClassPtr was encoded as a
168 // constant. Unlike ClassExprLoc/ClassBlock, some
169 // DWARF 4 attributes need to distinguish Class*Ptr
170 // from ClassConstant, so we only do this promotion
171 // for versions 2 and 3.
172 if class
, ok
:= attrPtrClass
[attr
]; vers
< 4 && ok
{
177 case formFlag
, formFlagPresent
:
180 case formRefAddr
, formRef1
, formRef2
, formRef4
, formRef8
, formRefUdata
:
181 return ClassReference
184 return ClassReferenceSig
186 case formString
, formStrp
:
190 // DWARF 4 defines four *ptr classes, but doesn't
191 // distinguish them in the encoding. Disambiguate
192 // these classes using the attribute.
193 if class
, ok
:= attrPtrClass
[attr
]; ok
{
202 return ClassReferenceAlt
205 return ClassStringAlt
209 // An entry is a sequence of attribute/value pairs.
211 Offset Offset
// offset of Entry in DWARF info
212 Tag Tag
// tag (kind of Entry)
213 Children
bool // whether Entry is followed by children
217 // A Field is a single attribute/value pair in an Entry.
219 // A value can be one of several "attribute classes" defined by DWARF.
220 // The Go types corresponding to each class are:
222 // DWARF class Go type Class
223 // ----------- ------- -----
224 // address uint64 ClassAddress
225 // block []byte ClassBlock
226 // constant int64 ClassConstant
227 // flag bool ClassFlag
229 // to info dwarf.Offset ClassReference
230 // to type unit uint64 ClassReferenceSig
231 // string string ClassString
232 // exprloc []byte ClassExprLoc
233 // lineptr int64 ClassLinePtr
234 // loclistptr int64 ClassLocListPtr
235 // macptr int64 ClassMacPtr
236 // rangelistptr int64 ClassRangeListPtr
238 // For unrecognized or vendor-defined attributes, Class may be
246 // A Class is the DWARF 4 class of an attribute value.
248 // In general, a given attribute's value may take on one of several
249 // possible classes defined by DWARF, each of which leads to a
250 // slightly different interpretation of the attribute.
252 // DWARF version 4 distinguishes attribute value classes more finely
253 // than previous versions of DWARF. The reader will disambiguate
254 // coarser classes from earlier versions of DWARF into the appropriate
255 // DWARF 4 class. For example, DWARF 2 uses "constant" for constants
256 // as well as all types of section offsets, but the reader will
257 // canonicalize attributes in DWARF 2 files that refer to section
258 // offsets to one of the Class*Ptr classes, even though these classes
259 // were only defined in DWARF 3.
263 // ClassUnknown represents values of unknown DWARF class.
264 ClassUnknown Class
= iota
266 // ClassAddress represents values of type uint64 that are
267 // addresses on the target machine.
270 // ClassBlock represents values of type []byte whose
271 // interpretation depends on the attribute.
274 // ClassConstant represents values of type int64 that are
275 // constants. The interpretation of this constant depends on
279 // ClassExprLoc represents values of type []byte that contain
280 // an encoded DWARF expression or location description.
283 // ClassFlag represents values of type bool.
286 // ClassLinePtr represents values that are an int64 offset
287 // into the "line" section.
290 // ClassLocListPtr represents values that are an int64 offset
291 // into the "loclist" section.
294 // ClassMacPtr represents values that are an int64 offset into
295 // the "mac" section.
298 // ClassMacPtr represents values that are an int64 offset into
299 // the "rangelist" section.
302 // ClassReference represents values that are an Offset offset
303 // of an Entry in the info section (for use with Reader.Seek).
304 // The DWARF specification combines ClassReference and
305 // ClassReferenceSig into class "reference".
308 // ClassReferenceSig represents values that are a uint64 type
309 // signature referencing a type Entry.
312 // ClassString represents values that are strings. If the
313 // compilation unit specifies the AttrUseUTF8 flag (strongly
314 // recommended), the string value will be encoded in UTF-8.
315 // Otherwise, the encoding is unspecified.
318 // ClassReferenceAlt represents values of type int64 that are
319 // an offset into the DWARF "info" section of an alternate
323 // ClassStringAlt represents values of type int64 that are an
324 // offset into the DWARF string section of an alternate object
329 //go:generate stringer -type=Class
331 func (i Class
) GoString() string {
332 return "dwarf." + i
.String()
335 // Val returns the value associated with attribute Attr in Entry,
336 // or nil if there is no such attribute.
338 // A common idiom is to merge the check for nil return with
339 // the check that the value has the expected dynamic type, as in:
340 // v, ok := e.Val(AttrSibling).(int64)
342 func (e
*Entry
) Val(a Attr
) interface{} {
343 if f
:= e
.AttrField(a
); f
!= nil {
349 // AttrField returns the Field associated with attribute Attr in
350 // Entry, or nil if there is no such attribute.
351 func (e
*Entry
) AttrField(a Attr
) *Field
{
352 for i
, f
:= range e
.Field
{
360 // An Offset represents the location of an Entry within the DWARF info.
361 // (See Reader.Seek.)
364 // Entry reads a single entry from buf, decoding
365 // according to the given abbreviation table.
366 func (b
*buf
) entry(atab abbrevTable
, ubase Offset
) *Entry
{
368 id
:= uint32(b
.uint())
374 b
.error("unknown abbreviation table index")
380 Children
: a
.children
,
381 Field
: make([]Field
, len(a
.field
)),
383 for i
:= range e
.Field
{
384 e
.Field
[i
].Attr
= a
.field
[i
].attr
385 e
.Field
[i
].Class
= a
.field
[i
].class
386 fmt
:= a
.field
[i
].fmt
387 if fmt
== formIndirect
{
388 fmt
= format(b
.uint())
393 b
.error("unknown entry attr format 0x" + strconv
.FormatInt(int64(fmt
), 16))
400 case formDwarfBlock1
:
401 val
= b
.bytes(int(b
.uint8()))
402 case formDwarfBlock2
:
403 val
= b
.bytes(int(b
.uint16()))
404 case formDwarfBlock4
:
405 val
= b
.bytes(int(b
.uint32()))
407 val
= b
.bytes(int(b
.uint()))
411 val
= int64(b
.uint8())
413 val
= int64(b
.uint16())
415 val
= int64(b
.uint32())
417 val
= int64(b
.uint64())
421 val
= int64(b
.uint())
427 case formFlagPresent
:
428 // The attribute is implicitly indicated as present, and no value is
429 // encoded in the debugging information entry itself.
432 // reference to other entry
434 vers
:= b
.format
.version()
436 b
.error("unknown version for DW_FORM_ref_addr")
437 } else if vers
== 2 {
438 val
= Offset(b
.addr())
440 is64
, known
:= b
.format
.dwarf64()
442 b
.error("unknown size for DW_FORM_ref_addr")
444 val
= Offset(b
.uint64())
446 val
= Offset(b
.uint32())
450 val
= Offset(b
.uint8()) + ubase
452 val
= Offset(b
.uint16()) + ubase
454 val
= Offset(b
.uint32()) + ubase
456 val
= Offset(b
.uint64()) + ubase
458 val
= Offset(b
.uint()) + ubase
464 var off
uint64 // offset into .debug_str
465 is64
, known
:= b
.format
.dwarf64()
467 b
.error("unknown size for DW_FORM_strp")
471 off
= uint64(b
.uint32())
473 if uint64(int(off
)) != off
{
474 b
.error("DW_FORM_strp offset out of range")
479 b1
:= makeBuf(b
.dwarf
, unknownFormat
{}, "str", 0, b
.dwarf
.str
)
487 // lineptr, loclistptr, macptr, rangelistptr
488 // New in DWARF 4, but clang can generate them with -gdwarf-2.
489 // Section reference, replacing use of formData4 and formData8.
490 case formSecOffset
, formGnuRefAlt
, formGnuStrpAlt
:
491 is64
, known
:= b
.format
.dwarf64()
493 b
.error("unknown size for form 0x" + strconv
.FormatInt(int64(fmt
), 16))
495 val
= int64(b
.uint64())
497 val
= int64(b
.uint32())
503 val
= b
.bytes(int(b
.uint()))
508 // 64-bit type signature.
519 // A Reader allows reading Entry structures from a DWARF ``info'' section.
520 // The Entry structures are arranged in a tree. The Reader's Next function
521 // return successive entries from a pre-order traversal of the tree.
522 // If an entry has children, its Children field will be true, and the children
523 // follow, terminated by an Entry with Tag 0.
529 lastChildren
bool // .Children of last entry returned by Next
530 lastSibling Offset
// .Val(AttrSibling) of last entry returned by Next
533 // Reader returns a new Reader for Data.
534 // The reader is positioned at byte offset 0 in the DWARF ``info'' section.
535 func (d
*Data
) Reader() *Reader
{
541 // AddressSize returns the size in bytes of addresses in the current compilation
543 func (r
*Reader
) AddressSize() int {
544 return r
.d
.unit
[r
.unit
].asize
547 // Seek positions the Reader at offset off in the encoded entry stream.
548 // Offset 0 can be used to denote the first entry.
549 func (r
*Reader
) Seek(off Offset
) {
552 r
.lastChildren
= false
554 if len(d
.unit
) == 0 {
559 r
.b
= makeBuf(r
.d
, u
, "info", u
.off
, u
.data
)
563 i
:= d
.offsetToUnit(off
)
565 r
.err
= errors
.New("offset out of range")
570 r
.b
= makeBuf(r
.d
, u
, "info", off
, u
.data
[off
-u
.off
:])
573 // maybeNextUnit advances to the next unit if this one is finished.
574 func (r
*Reader
) maybeNextUnit() {
575 for len(r
.b
.data
) == 0 && r
.unit
+1 < len(r
.d
.unit
) {
577 u
:= &r
.d
.unit
[r
.unit
]
578 r
.b
= makeBuf(r
.d
, u
, "info", u
.off
, u
.data
)
582 // Next reads the next entry from the encoded entry stream.
583 // It returns nil, nil when it reaches the end of the section.
584 // It returns an error if the current offset is invalid or the data at the
585 // offset cannot be decoded as a valid Entry.
586 func (r
*Reader
) Next() (*Entry
, error
) {
591 if len(r
.b
.data
) == 0 {
594 u
:= &r
.d
.unit
[r
.unit
]
595 e
:= r
.b
.entry(u
.atable
, u
.base
)
601 r
.lastChildren
= e
.Children
603 r
.lastSibling
, _
= e
.Val(AttrSibling
).(Offset
)
606 r
.lastChildren
= false
611 // SkipChildren skips over the child entries associated with
612 // the last Entry returned by Next. If that Entry did not have
613 // children or Next has not been called, SkipChildren is a no-op.
614 func (r
*Reader
) SkipChildren() {
615 if r
.err
!= nil ||
!r
.lastChildren
{
619 // If the last entry had a sibling attribute,
620 // that attribute gives the offset of the next
621 // sibling, so we can avoid decoding the
623 if r
.lastSibling
>= r
.b
.off
{
624 r
.Seek(r
.lastSibling
)
630 if err
!= nil || e
== nil || e
.Tag
== 0 {
639 // clone returns a copy of the reader. This is used by the typeReader
641 func (r
*Reader
) clone() typeReader
{
645 // offset returns the current buffer offset. This is used by the
646 // typeReader interface.
647 func (r
*Reader
) offset() Offset
{
651 // SeekPC returns the Entry for the compilation unit that includes pc,
652 // and positions the reader to read the children of that unit. If pc
653 // is not covered by any unit, SeekPC returns ErrUnknownPC and the
654 // position of the reader is undefined.
656 // Because compilation units can describe multiple regions of the
657 // executable, in the worst case SeekPC must search through all the
658 // ranges in all the compilation units. Each call to SeekPC starts the
659 // search at the compilation unit of the last call, so in general
660 // looking up a series of PCs will be faster if they are sorted. If
661 // the caller wishes to do repeated fast PC lookups, it should build
662 // an appropriate index using the Ranges method.
663 func (r
*Reader
) SeekPC(pc
uint64) (*Entry
, error
) {
665 for i
:= 0; i
< len(r
.d
.unit
); i
++ {
666 if unit
>= len(r
.d
.unit
) {
670 r
.lastChildren
= false
673 r
.b
= makeBuf(r
.d
, u
, "info", u
.off
, u
.data
)
678 ranges
, err
:= r
.d
.Ranges(e
)
682 for _
, pcs
:= range ranges
{
683 if pcs
[0] <= pc
&& pc
< pcs
[1] {
689 return nil, ErrUnknownPC
692 // Ranges returns the PC ranges covered by e, a slice of [low,high) pairs.
693 // Only some entry types, such as TagCompileUnit or TagSubprogram, have PC
694 // ranges; for others, this will return nil with no error.
695 func (d
*Data
) Ranges(e
*Entry
) ([][2]uint64, error
) {
698 low
, lowOK
:= e
.Val(AttrLowpc
).(uint64)
702 highField
:= e
.AttrField(AttrHighpc
)
703 if highField
!= nil {
704 switch highField
.Class
{
706 high
, highOK
= highField
.Val
.(uint64)
708 off
, ok
:= highField
.Val
.(int64)
710 high
= low
+ uint64(off
)
717 ret
= append(ret
, [2]uint64{low
, high
})
720 ranges
, rangesOK
:= e
.Val(AttrRanges
).(int64)
721 if rangesOK
&& d
.ranges
!= nil {
722 // The initial base address is the lowpc attribute
723 // of the enclosing compilation unit.
724 // Although DWARF specifies the lowpc attribute,
725 // comments in gdb/dwarf2read.c say that some versions
726 // of GCC use the entrypc attribute, so we check that too.
728 if e
.Tag
== TagCompileUnit
{
731 i
:= d
.offsetToUnit(e
.Offset
)
733 return nil, errors
.New("no unit for entry")
736 b
:= makeBuf(d
, u
, "info", u
.off
, u
.data
)
737 cu
= b
.entry(u
.atable
, u
.base
)
744 if cuEntry
, cuEntryOK
:= cu
.Val(AttrEntrypc
).(uint64); cuEntryOK
{
746 } else if cuLow
, cuLowOK
:= cu
.Val(AttrLowpc
).(uint64); cuLowOK
{
750 u
:= &d
.unit
[d
.offsetToUnit(e
.Offset
)]
751 buf
:= makeBuf(d
, u
, "ranges", Offset(ranges
), d
.ranges
[ranges
:])
752 for len(buf
.data
) > 0 {
756 if low
== 0 && high
== 0 {
760 if low
== ^uint64(0)>>uint((8-u
.addrsize())*8) {
763 ret
= append(ret
, [2]uint64{base
+ low
, base
+ high
})