debug/dwarf: formStrp uses a 64-bit value for 64-bit DWARF
[official-gcc.git] / libgo / go / debug / dwarf / entry.go
blob6be0700b7ef11452e58f69e3eec81ad56407efa6
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.
11 package dwarf
13 import (
14 "errors"
15 "strconv"
18 // a single entry's description: a sequence of attributes
19 type abbrev struct {
20 tag Tag
21 children bool
22 field []afield
25 type afield struct {
26 attr Attr
27 fmt format
28 class Class
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 {
38 return m, nil
41 data := d.abbrev
42 if off > uint64(len(data)) {
43 data = nil
44 } else {
45 data = data[off:]
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)
52 for {
53 // Table ends with id == 0.
54 id := uint32(b.uint())
55 if id == 0 {
56 break
59 // Walk over attributes, counting.
60 n := 0
61 b1 := b // Read from copy of b.
62 b1.uint()
63 b1.uint8()
64 for {
65 tag := b1.uint()
66 fmt := b1.uint()
67 if tag == 0 && fmt == 0 {
68 break
70 n++
72 if b1.err != nil {
73 return nil, b1.err
76 // Walk over attributes again, this time writing them down.
77 var a abbrev
78 a.tag = Tag(b.uint())
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)
86 b.uint()
87 b.uint()
89 m[id] = a
91 if b.err != nil {
92 return nil, b.err
94 d.abbrevCache[off] = m
95 return m, nil
98 // attrIsExprloc indicates attributes that allow exprloc values that
99 // are encoded as block values in DWARF 2 and 3. See DWARF 4, Figure
100 // 20.
101 var attrIsExprloc = map[Attr]bool{
102 AttrLocation: true,
103 AttrByteSize: true,
104 AttrBitOffset: true,
105 AttrBitSize: true,
106 AttrStringLength: true,
107 AttrLowerBound: true,
108 AttrReturnAddr: true,
109 AttrStrideSize: true,
110 AttrUpperBound: true,
111 AttrCount: true,
112 AttrDataMemberLoc: true,
113 AttrFrameBase: true,
114 AttrSegment: true,
115 AttrStaticLink: true,
116 AttrUseLocation: true,
117 AttrVtableElemLoc: true,
118 AttrAllocated: true,
119 AttrAssociated: true,
120 AttrDataLocation: true,
121 AttrStride: 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 {
146 switch form {
147 default:
148 b.error("cannot determine class of unknown attribute form")
149 return 0
151 case formAddr:
152 return ClassAddress
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] {
162 return ClassExprLoc
164 return ClassBlock
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 {
173 return class
175 return ClassConstant
177 case formFlag, formFlagPresent:
178 return ClassFlag
180 case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata:
181 return ClassReference
183 case formRefSig8:
184 return ClassReferenceSig
186 case formString, formStrp:
187 return ClassString
189 case formSecOffset:
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 {
194 return class
196 return ClassUnknown
198 case formExprloc:
199 return ClassExprLoc
201 case formGnuRefAlt:
202 return ClassReferenceAlt
204 case formGnuStrpAlt:
205 return ClassStringAlt
209 // An entry is a sequence of attribute/value pairs.
210 type Entry struct {
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
214 Field []Field
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
228 // reference
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
239 // ClassUnknown.
240 type Field struct {
241 Attr Attr
242 Val interface{}
243 Class Class
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.
260 type Class int
262 const (
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.
268 ClassAddress
270 // ClassBlock represents values of type []byte whose
271 // interpretation depends on the attribute.
272 ClassBlock
274 // ClassConstant represents values of type int64 that are
275 // constants. The interpretation of this constant depends on
276 // the attribute.
277 ClassConstant
279 // ClassExprLoc represents values of type []byte that contain
280 // an encoded DWARF expression or location description.
281 ClassExprLoc
283 // ClassFlag represents values of type bool.
284 ClassFlag
286 // ClassLinePtr represents values that are an int64 offset
287 // into the "line" section.
288 ClassLinePtr
290 // ClassLocListPtr represents values that are an int64 offset
291 // into the "loclist" section.
292 ClassLocListPtr
294 // ClassMacPtr represents values that are an int64 offset into
295 // the "mac" section.
296 ClassMacPtr
298 // ClassMacPtr represents values that are an int64 offset into
299 // the "rangelist" section.
300 ClassRangeListPtr
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".
306 ClassReference
308 // ClassReferenceSig represents values that are a uint64 type
309 // signature referencing a type Entry.
310 ClassReferenceSig
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.
316 ClassString
318 // ClassReferenceAlt represents values of type int64 that are
319 // an offset into the DWARF "info" section of an alternate
320 // object file.
321 ClassReferenceAlt
323 // ClassStringAlt represents values of type int64 that are an
324 // offset into the DWARF string section of an alternate object
325 // file.
326 ClassStringAlt
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 {
344 return f.Val
346 return 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 {
353 if f.Attr == a {
354 return &e.Field[i]
357 return nil
360 // An Offset represents the location of an Entry within the DWARF info.
361 // (See Reader.Seek.)
362 type Offset uint32
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 {
367 off := b.off
368 id := uint32(b.uint())
369 if id == 0 {
370 return &Entry{}
372 a, ok := atab[id]
373 if !ok {
374 b.error("unknown abbreviation table index")
375 return nil
377 e := &Entry{
378 Offset: off,
379 Tag: a.tag,
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())
390 var val interface{}
391 switch fmt {
392 default:
393 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
395 // address
396 case formAddr:
397 val = b.addr()
399 // block
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()))
406 case formDwarfBlock:
407 val = b.bytes(int(b.uint()))
409 // constant
410 case formData1:
411 val = int64(b.uint8())
412 case formData2:
413 val = int64(b.uint16())
414 case formData4:
415 val = int64(b.uint32())
416 case formData8:
417 val = int64(b.uint64())
418 case formSdata:
419 val = int64(b.int())
420 case formUdata:
421 val = int64(b.uint())
423 // flag
424 case formFlag:
425 val = b.uint8() == 1
426 // New in DWARF 4.
427 case formFlagPresent:
428 // The attribute is implicitly indicated as present, and no value is
429 // encoded in the debugging information entry itself.
430 val = true
432 // reference to other entry
433 case formRefAddr:
434 vers := b.format.version()
435 if vers == 0 {
436 b.error("unknown version for DW_FORM_ref_addr")
437 } else if vers == 2 {
438 val = Offset(b.addr())
439 } else {
440 is64, known := b.format.dwarf64()
441 if !known {
442 b.error("unknown size for DW_FORM_ref_addr")
443 } else if is64 {
444 val = Offset(b.uint64())
445 } else {
446 val = Offset(b.uint32())
449 case formRef1:
450 val = Offset(b.uint8()) + ubase
451 case formRef2:
452 val = Offset(b.uint16()) + ubase
453 case formRef4:
454 val = Offset(b.uint32()) + ubase
455 case formRef8:
456 val = Offset(b.uint64()) + ubase
457 case formRefUdata:
458 val = Offset(b.uint()) + ubase
460 // string
461 case formString:
462 val = b.string()
463 case formStrp:
464 var off uint64 // offset into .debug_str
465 is64, known := b.format.dwarf64()
466 if !known {
467 b.error("unknown size for DW_FORM_strp")
468 } else if is64 {
469 off = b.uint64()
470 } else {
471 off = uint64(b.uint32())
473 if uint64(int(off)) != off {
474 b.error("DW_FORM_strp offset out of range")
476 if b.err != nil {
477 return nil
479 b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str)
480 b1.skip(int(off))
481 val = b1.string()
482 if b1.err != nil {
483 b.err = b1.err
484 return nil
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()
492 if !known {
493 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
494 } else if is64 {
495 val = int64(b.uint64())
496 } else {
497 val = int64(b.uint32())
500 // exprloc
501 // New in DWARF 4.
502 case formExprloc:
503 val = b.bytes(int(b.uint()))
505 // reference
506 // New in DWARF 4.
507 case formRefSig8:
508 // 64-bit type signature.
509 val = b.uint64()
511 e.Field[i].Val = val
513 if b.err != nil {
514 return nil
516 return e
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.
524 type Reader struct {
525 b buf
526 d *Data
527 err error
528 unit int
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 {
536 r := &Reader{d: d}
537 r.Seek(0)
538 return r
541 // AddressSize returns the size in bytes of addresses in the current compilation
542 // unit.
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) {
550 d := r.d
551 r.err = nil
552 r.lastChildren = false
553 if off == 0 {
554 if len(d.unit) == 0 {
555 return
557 u := &d.unit[0]
558 r.unit = 0
559 r.b = makeBuf(r.d, u, "info", u.off, u.data)
560 return
563 i := d.offsetToUnit(off)
564 if i == -1 {
565 r.err = errors.New("offset out of range")
566 return
568 u := &d.unit[i]
569 r.unit = i
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) {
576 r.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) {
587 if r.err != nil {
588 return nil, r.err
590 r.maybeNextUnit()
591 if len(r.b.data) == 0 {
592 return nil, nil
594 u := &r.d.unit[r.unit]
595 e := r.b.entry(u.atable, u.base)
596 if r.b.err != nil {
597 r.err = r.b.err
598 return nil, r.err
600 if e != nil {
601 r.lastChildren = e.Children
602 if r.lastChildren {
603 r.lastSibling, _ = e.Val(AttrSibling).(Offset)
605 } else {
606 r.lastChildren = false
608 return e, nil
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 {
616 return
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
622 // child subtrees.
623 if r.lastSibling >= r.b.off {
624 r.Seek(r.lastSibling)
625 return
628 for {
629 e, err := r.Next()
630 if err != nil || e == nil || e.Tag == 0 {
631 break
633 if e.Children {
634 r.SkipChildren()
639 // clone returns a copy of the reader. This is used by the typeReader
640 // interface.
641 func (r *Reader) clone() typeReader {
642 return r.d.Reader()
645 // offset returns the current buffer offset. This is used by the
646 // typeReader interface.
647 func (r *Reader) offset() Offset {
648 return r.b.off
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) {
664 unit := r.unit
665 for i := 0; i < len(r.d.unit); i++ {
666 if unit >= len(r.d.unit) {
667 unit = 0
669 r.err = nil
670 r.lastChildren = false
671 r.unit = unit
672 u := &r.d.unit[unit]
673 r.b = makeBuf(r.d, u, "info", u.off, u.data)
674 e, err := r.Next()
675 if err != nil {
676 return nil, err
678 ranges, err := r.d.Ranges(e)
679 if err != nil {
680 return nil, err
682 for _, pcs := range ranges {
683 if pcs[0] <= pc && pc < pcs[1] {
684 return e, nil
687 unit++
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) {
696 var ret [][2]uint64
698 low, lowOK := e.Val(AttrLowpc).(uint64)
700 var high uint64
701 var highOK bool
702 highField := e.AttrField(AttrHighpc)
703 if highField != nil {
704 switch highField.Class {
705 case ClassAddress:
706 high, highOK = highField.Val.(uint64)
707 case ClassConstant:
708 off, ok := highField.Val.(int64)
709 if ok {
710 high = low + uint64(off)
711 highOK = true
716 if lowOK && highOK {
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.
727 var cu *Entry
728 if e.Tag == TagCompileUnit {
729 cu = e
730 } else {
731 i := d.offsetToUnit(e.Offset)
732 if i == -1 {
733 return nil, errors.New("no unit for entry")
735 u := &d.unit[i]
736 b := makeBuf(d, u, "info", u.off, u.data)
737 cu = b.entry(u.atable, u.base)
738 if b.err != nil {
739 return nil, b.err
743 var base uint64
744 if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK {
745 base = cuEntry
746 } else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK {
747 base = cuLow
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 {
753 low = buf.addr()
754 high = buf.addr()
756 if low == 0 && high == 0 {
757 break
760 if low == ^uint64(0)>>uint((8-u.addrsize())*8) {
761 base = high
762 } else {
763 ret = append(ret, [2]uint64{base + low, base + high})
768 return ret, nil