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.
4 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.
10 11 package dwarf
12 13 import (
14 "encoding/binary"
15 "errors"
16 "fmt"
17 "strconv"
18 )
19 20 // a single entry's description: a sequence of attributes
21 type abbrev struct {
22 tag Tag
23 children bool
24 field []afield
25 }
26 27 type afield struct {
28 attr Attr
29 fmt format
30 class Class
31 val int64 // for formImplicitConst
32 }
33 34 // a map from entry format ids to their descriptions
35 type abbrevTable map[uint32]abbrev
36 37 // parseAbbrev returns the abbreviation table that starts at byte off
38 // in the .debug_abbrev section.
39 func (d *Data) parseAbbrev(off uint64, vers int) (abbrevTable, error) {
40 if m, ok := d.abbrevCache[off]; ok {
41 return m, nil
42 }
43 44 data := d.abbrev
45 if off > uint64(len(data)) {
46 data = nil
47 } else {
48 data = data[off:]
49 }
50 b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
51 52 // Error handling is simplified by the buf getters
53 // returning an endless stream of 0s after an error.
54 m := make(abbrevTable)
55 for {
56 // Table ends with id == 0.
57 id := uint32(b.uint())
58 if id == 0 {
59 break
60 }
61 62 // Walk over attributes, counting.
63 n := 0
64 b1 := b // Read from copy of b.
65 b1.uint()
66 b1.uint8()
67 for {
68 tag := b1.uint()
69 fmt := b1.uint()
70 if tag == 0 && fmt == 0 {
71 break
72 }
73 if format(fmt) == formImplicitConst {
74 b1.int()
75 }
76 n++
77 }
78 if b1.err != nil {
79 return nil, b1.err
80 }
81 82 // Walk over attributes again, this time writing them down.
83 var a abbrev
84 a.tag = Tag(b.uint())
85 a.children = b.uint8() != 0
86 a.field = []afield{:n}
87 for i := range a.field {
88 a.field[i].attr = Attr(b.uint())
89 a.field[i].fmt = format(b.uint())
90 a.field[i].class = formToClass(a.field[i].fmt, a.field[i].attr, vers, &b)
91 if a.field[i].fmt == formImplicitConst {
92 a.field[i].val = b.int()
93 }
94 }
95 b.uint()
96 b.uint()
97 98 m[id] = a
99 }
100 if b.err != nil {
101 return nil, b.err
102 }
103 d.abbrevCache[off] = m
104 return m, nil
105 }
106 107 // attrIsExprloc indicates attributes that allow exprloc values that
108 // are encoded as block values in DWARF 2 and 3. See DWARF 4, Figure
109 // 20.
110 var attrIsExprloc = map[Attr]bool{
111 AttrLocation: true,
112 AttrByteSize: true,
113 AttrBitOffset: true,
114 AttrBitSize: true,
115 AttrStringLength: true,
116 AttrLowerBound: true,
117 AttrReturnAddr: true,
118 AttrStrideSize: true,
119 AttrUpperBound: true,
120 AttrCount: true,
121 AttrDataMemberLoc: true,
122 AttrFrameBase: true,
123 AttrSegment: true,
124 AttrStaticLink: true,
125 AttrUseLocation: true,
126 AttrVtableElemLoc: true,
127 AttrAllocated: true,
128 AttrAssociated: true,
129 AttrDataLocation: true,
130 AttrStride: true,
131 }
132 133 // attrPtrClass indicates the *ptr class of attributes that have
134 // encoding formSecOffset in DWARF 4 or formData* in DWARF 2 and 3.
135 var attrPtrClass = map[Attr]Class{
136 AttrLocation: ClassLocListPtr,
137 AttrStmtList: ClassLinePtr,
138 AttrStringLength: ClassLocListPtr,
139 AttrReturnAddr: ClassLocListPtr,
140 AttrStartScope: ClassRangeListPtr,
141 AttrDataMemberLoc: ClassLocListPtr,
142 AttrFrameBase: ClassLocListPtr,
143 AttrMacroInfo: ClassMacPtr,
144 AttrSegment: ClassLocListPtr,
145 AttrStaticLink: ClassLocListPtr,
146 AttrUseLocation: ClassLocListPtr,
147 AttrVtableElemLoc: ClassLocListPtr,
148 AttrRanges: ClassRangeListPtr,
149 // The following are new in DWARF 5.
150 AttrStrOffsetsBase: ClassStrOffsetsPtr,
151 AttrAddrBase: ClassAddrPtr,
152 AttrRnglistsBase: ClassRngListsPtr,
153 AttrLoclistsBase: ClassLocListPtr,
154 }
155 156 // formToClass returns the DWARF 4 Class for the given form. If the
157 // DWARF version is less then 4, it will disambiguate some forms
158 // depending on the attribute.
159 func formToClass(form format, attr Attr, vers int, b *buf) Class {
160 switch form {
161 default:
162 b.error("cannot determine class of unknown attribute form")
163 return 0
164 165 case formIndirect:
166 return ClassUnknown
167 168 case formAddr, formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
169 return ClassAddress
170 171 case formDwarfBlock1, formDwarfBlock2, formDwarfBlock4, formDwarfBlock:
172 // In DWARF 2 and 3, ClassExprLoc was encoded as a
173 // block. DWARF 4 distinguishes ClassBlock and
174 // ClassExprLoc, but there are no attributes that can
175 // be both, so we also promote ClassBlock values in
176 // DWARF 4 that should be ClassExprLoc in case
177 // producers get this wrong.
178 if attrIsExprloc[attr] {
179 return ClassExprLoc
180 }
181 return ClassBlock
182 183 case formData1, formData2, formData4, formData8, formSdata, formUdata, formData16, formImplicitConst:
184 // In DWARF 2 and 3, ClassPtr was encoded as a
185 // constant. Unlike ClassExprLoc/ClassBlock, some
186 // DWARF 4 attributes need to distinguish Class*Ptr
187 // from ClassConstant, so we only do this promotion
188 // for versions 2 and 3.
189 if class, ok := attrPtrClass[attr]; vers < 4 && ok {
190 return class
191 }
192 return ClassConstant
193 194 case formFlag, formFlagPresent:
195 return ClassFlag
196 197 case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata, formRefSup4, formRefSup8:
198 return ClassReference
199 200 case formRefSig8:
201 return ClassReferenceSig
202 203 case formString, formStrp, formStrx, formStrpSup, formLineStrp, formStrx1, formStrx2, formStrx3, formStrx4:
204 return ClassString
205 206 case formSecOffset:
207 // DWARF 4 defines four *ptr classes, but doesn't
208 // distinguish them in the encoding. Disambiguate
209 // these classes using the attribute.
210 if class, ok := attrPtrClass[attr]; ok {
211 return class
212 }
213 return ClassUnknown
214 215 case formExprloc:
216 return ClassExprLoc
217 218 case formGnuRefAlt:
219 return ClassReferenceAlt
220 221 case formGnuStrpAlt:
222 return ClassStringAlt
223 224 case formLoclistx:
225 return ClassLocList
226 227 case formRnglistx:
228 return ClassRngList
229 }
230 }
231 232 // An entry is a sequence of attribute/value pairs.
233 type Entry struct {
234 Offset Offset // offset of Entry in DWARF info
235 Tag Tag // tag (kind of Entry)
236 Children bool // whether Entry is followed by children
237 Field []Field
238 }
239 240 // A Field is a single attribute/value pair in an [Entry].
241 //
242 // A value can be one of several "attribute classes" defined by DWARF.
243 // The Go types corresponding to each class are:
244 //
245 // DWARF class Go type Class
246 // ----------- ------- -----
247 // address uint64 ClassAddress
248 // block []byte ClassBlock
249 // constant int64 ClassConstant
250 // flag bool ClassFlag
251 // reference
252 // to info dwarf.Offset ClassReference
253 // to type unit uint64 ClassReferenceSig
254 // string string ClassString
255 // exprloc []byte ClassExprLoc
256 // lineptr int64 ClassLinePtr
257 // loclistptr int64 ClassLocListPtr
258 // macptr int64 ClassMacPtr
259 // rangelistptr int64 ClassRangeListPtr
260 //
261 // For unrecognized or vendor-defined attributes, [Class] may be
262 // [ClassUnknown].
263 type Field struct {
264 Attr Attr
265 Val any
266 Class Class
267 }
268 269 // A Class is the DWARF 4 class of an attribute value.
270 //
271 // In general, a given attribute's value may take on one of several
272 // possible classes defined by DWARF, each of which leads to a
273 // slightly different interpretation of the attribute.
274 //
275 // DWARF version 4 distinguishes attribute value classes more finely
276 // than previous versions of DWARF. The reader will disambiguate
277 // coarser classes from earlier versions of DWARF into the appropriate
278 // DWARF 4 class. For example, DWARF 2 uses "constant" for constants
279 // as well as all types of section offsets, but the reader will
280 // canonicalize attributes in DWARF 2 files that refer to section
281 // offsets to one of the Class*Ptr classes, even though these classes
282 // were only defined in DWARF 3.
283 type Class int
284 285 const (
286 // ClassUnknown represents values of unknown DWARF class.
287 ClassUnknown Class = iota
288 289 // ClassAddress represents values of type uint64 that are
290 // addresses on the target machine.
291 ClassAddress
292 293 // ClassBlock represents values of type []byte whose
294 // interpretation depends on the attribute.
295 ClassBlock
296 297 // ClassConstant represents values of type int64 that are
298 // constants. The interpretation of this constant depends on
299 // the attribute.
300 ClassConstant
301 302 // ClassExprLoc represents values of type []byte that contain
303 // an encoded DWARF expression or location description.
304 ClassExprLoc
305 306 // ClassFlag represents values of type bool.
307 ClassFlag
308 309 // ClassLinePtr represents values that are an int64 offset
310 // into the "line" section.
311 ClassLinePtr
312 313 // ClassLocListPtr represents values that are an int64 offset
314 // into the "loclist" section.
315 ClassLocListPtr
316 317 // ClassMacPtr represents values that are an int64 offset into
318 // the "mac" section.
319 ClassMacPtr
320 321 // ClassRangeListPtr represents values that are an int64 offset into
322 // the "rangelist" section.
323 ClassRangeListPtr
324 325 // ClassReference represents values that are an Offset offset
326 // of an Entry in the info section (for use with Reader.Seek).
327 // The DWARF specification combines ClassReference and
328 // ClassReferenceSig into class "reference".
329 ClassReference
330 331 // ClassReferenceSig represents values that are a uint64 type
332 // signature referencing a type Entry.
333 ClassReferenceSig
334 335 // ClassString represents values that are strings. If the
336 // compilation unit specifies the AttrUseUTF8 flag (strongly
337 // recommended), the string value will be encoded in UTF-8.
338 // Otherwise, the encoding is unspecified.
339 ClassString
340 341 // ClassReferenceAlt represents values of type int64 that are
342 // an offset into the DWARF "info" section of an alternate
343 // object file.
344 ClassReferenceAlt
345 346 // ClassStringAlt represents values of type int64 that are an
347 // offset into the DWARF string section of an alternate object
348 // file.
349 ClassStringAlt
350 351 // ClassAddrPtr represents values that are an int64 offset
352 // into the "addr" section.
353 ClassAddrPtr
354 355 // ClassLocList represents values that are an int64 offset
356 // into the "loclists" section.
357 ClassLocList
358 359 // ClassRngList represents values that are a uint64 offset
360 // from the base of the "rnglists" section.
361 ClassRngList
362 363 // ClassRngListsPtr represents values that are an int64 offset
364 // into the "rnglists" section. These are used as the base for
365 // ClassRngList values.
366 ClassRngListsPtr
367 368 // ClassStrOffsetsPtr represents values that are an int64
369 // offset into the "str_offsets" section.
370 ClassStrOffsetsPtr
371 )
372 373 //go:generate stringer -type=Class
374 375 func (i Class) GoString() string {
376 return "dwarf." + i.String()
377 }
378 379 // Val returns the value associated with attribute [Attr] in [Entry],
380 // or nil if there is no such attribute.
381 //
382 // A common idiom is to merge the check for nil return with
383 // the check that the value has the expected dynamic type, as in:
384 //
385 // v, ok := e.Val(AttrSibling).(int64)
386 func (e *Entry) Val(a Attr) any {
387 if f := e.AttrField(a); f != nil {
388 return f.Val
389 }
390 return nil
391 }
392 393 // AttrField returns the [Field] associated with attribute [Attr] in
394 // [Entry], or nil if there is no such attribute.
395 func (e *Entry) AttrField(a Attr) *Field {
396 for i, f := range e.Field {
397 if f.Attr == a {
398 return &e.Field[i]
399 }
400 }
401 return nil
402 }
403 404 // An Offset represents the location of an [Entry] within the DWARF info.
405 // (See [Reader.Seek].)
406 type Offset uint32
407 408 // Entry reads a single entry from buf, decoding
409 // according to the given abbreviation table.
410 func (b *buf) entry(cu *Entry, u *unit) *Entry {
411 atab, ubase, vers := u.atable, u.base, u.vers
412 off := b.off
413 id := uint32(b.uint())
414 if id == 0 {
415 return &Entry{}
416 }
417 a, ok := atab[id]
418 if !ok {
419 b.error("unknown abbreviation table index")
420 return nil
421 }
422 e := &Entry{
423 Offset: off,
424 Tag: a.tag,
425 Children: a.children,
426 Field: []Field{:len(a.field)},
427 }
428 429 resolveStrx := func(strBase, off uint64) string {
430 off += strBase
431 if uint64(int(off)) != off {
432 b.error("DW_FORM_strx offset out of range")
433 }
434 435 b1 := makeBuf(b.dwarf, b.format, "str_offsets", 0, b.dwarf.strOffsets)
436 b1.skip(int(off))
437 is64, _ := b.format.dwarf64()
438 if is64 {
439 off = b1.uint64()
440 } else {
441 off = uint64(b1.uint32())
442 }
443 if b1.err != nil {
444 b.err = b1.err
445 return ""
446 }
447 if uint64(int(off)) != off {
448 b.error("DW_FORM_strx indirect offset out of range")
449 }
450 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
451 b1.skip(int(off))
452 val := b1.string()
453 if b1.err != nil {
454 b.err = b1.err
455 }
456 return val
457 }
458 459 resolveRnglistx := func(rnglistsBase, off uint64) uint64 {
460 is64, _ := b.format.dwarf64()
461 if is64 {
462 off *= 8
463 } else {
464 off *= 4
465 }
466 off += rnglistsBase
467 if uint64(int(off)) != off {
468 b.error("DW_FORM_rnglistx offset out of range")
469 }
470 471 b1 := makeBuf(b.dwarf, b.format, "rnglists", 0, b.dwarf.rngLists)
472 b1.skip(int(off))
473 if is64 {
474 off = b1.uint64()
475 } else {
476 off = uint64(b1.uint32())
477 }
478 if b1.err != nil {
479 b.err = b1.err
480 return 0
481 }
482 if uint64(int(off)) != off {
483 b.error("DW_FORM_rnglistx indirect offset out of range")
484 }
485 return rnglistsBase + off
486 }
487 488 for i := range e.Field {
489 e.Field[i].Attr = a.field[i].attr
490 e.Field[i].Class = a.field[i].class
491 fmt := a.field[i].fmt
492 if fmt == formIndirect {
493 fmt = format(b.uint())
494 e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b)
495 }
496 var val any
497 switch fmt {
498 default:
499 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
500 501 // address
502 case formAddr:
503 val = b.addr()
504 case formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
505 var off uint64
506 switch fmt {
507 case formAddrx:
508 off = b.uint()
509 case formAddrx1:
510 off = uint64(b.uint8())
511 case formAddrx2:
512 off = uint64(b.uint16())
513 case formAddrx3:
514 off = uint64(b.uint24())
515 case formAddrx4:
516 off = uint64(b.uint32())
517 }
518 if b.dwarf.addr == nil {
519 b.error("DW_FORM_addrx with no .debug_addr section")
520 }
521 if b.err != nil {
522 return nil
523 }
524 525 addrBase := int64(u.addrBase())
526 var err error
527 val, err = b.dwarf.debugAddr(b.format, uint64(addrBase), off)
528 if err != nil {
529 if b.err == nil {
530 b.err = err
531 }
532 return nil
533 }
534 535 // block
536 case formDwarfBlock1:
537 val = b.bytes(int(b.uint8()))
538 case formDwarfBlock2:
539 val = b.bytes(int(b.uint16()))
540 case formDwarfBlock4:
541 val = b.bytes(int(b.uint32()))
542 case formDwarfBlock:
543 val = b.bytes(int(b.uint()))
544 545 // constant
546 case formData1:
547 val = int64(b.uint8())
548 case formData2:
549 val = int64(b.uint16())
550 case formData4:
551 val = int64(b.uint32())
552 case formData8:
553 val = int64(b.uint64())
554 case formData16:
555 val = b.bytes(16)
556 case formSdata:
557 val = int64(b.int())
558 case formUdata:
559 val = int64(b.uint())
560 case formImplicitConst:
561 val = a.field[i].val
562 563 // flag
564 case formFlag:
565 val = b.uint8() == 1
566 // New in DWARF 4.
567 case formFlagPresent:
568 // The attribute is implicitly indicated as present, and no value is
569 // encoded in the debugging information entry itself.
570 val = true
571 572 // reference to other entry
573 case formRefAddr:
574 vers := b.format.version()
575 if vers == 0 {
576 b.error("unknown version for DW_FORM_ref_addr")
577 } else if vers == 2 {
578 val = Offset(b.addr())
579 } else {
580 is64, known := b.format.dwarf64()
581 if !known {
582 b.error("unknown size for DW_FORM_ref_addr")
583 } else if is64 {
584 val = Offset(b.uint64())
585 } else {
586 val = Offset(b.uint32())
587 }
588 }
589 case formRef1:
590 val = Offset(b.uint8()) + ubase
591 case formRef2:
592 val = Offset(b.uint16()) + ubase
593 case formRef4:
594 val = Offset(b.uint32()) + ubase
595 case formRef8:
596 val = Offset(b.uint64()) + ubase
597 case formRefUdata:
598 val = Offset(b.uint()) + ubase
599 600 // string
601 case formString:
602 val = b.string()
603 case formStrp, formLineStrp:
604 var off uint64 // offset into .debug_str
605 is64, known := b.format.dwarf64()
606 if !known {
607 b.error("unknown size for DW_FORM_strp/line_strp")
608 } else if is64 {
609 off = b.uint64()
610 } else {
611 off = uint64(b.uint32())
612 }
613 if uint64(int(off)) != off {
614 b.error("DW_FORM_strp/line_strp offset out of range")
615 }
616 if b.err != nil {
617 return nil
618 }
619 var b1 buf
620 if fmt == formStrp {
621 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
622 } else {
623 if len(b.dwarf.lineStr) == 0 {
624 b.error("DW_FORM_line_strp with no .debug_line_str section")
625 return nil
626 }
627 b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr)
628 }
629 b1.skip(int(off))
630 val = b1.string()
631 if b1.err != nil {
632 b.err = b1.err
633 return nil
634 }
635 case formStrx, formStrx1, formStrx2, formStrx3, formStrx4:
636 var off uint64
637 switch fmt {
638 case formStrx:
639 off = b.uint()
640 case formStrx1:
641 off = uint64(b.uint8())
642 case formStrx2:
643 off = uint64(b.uint16())
644 case formStrx3:
645 off = uint64(b.uint24())
646 case formStrx4:
647 off = uint64(b.uint32())
648 }
649 if len(b.dwarf.strOffsets) == 0 {
650 b.error("DW_FORM_strx with no .debug_str_offsets section")
651 }
652 is64, known := b.format.dwarf64()
653 if !known {
654 b.error("unknown offset size for DW_FORM_strx")
655 }
656 if b.err != nil {
657 return nil
658 }
659 if is64 {
660 off *= 8
661 } else {
662 off *= 4
663 }
664 665 strBase := int64(u.strOffsetsBase())
666 val = resolveStrx(uint64(strBase), off)
667 668 case formStrpSup:
669 is64, known := b.format.dwarf64()
670 if !known {
671 b.error("unknown size for DW_FORM_strp_sup")
672 } else if is64 {
673 val = b.uint64()
674 } else {
675 val = b.uint32()
676 }
677 678 // lineptr, loclistptr, macptr, rangelistptr
679 // New in DWARF 4, but clang can generate them with -gdwarf-2.
680 // Section reference, replacing use of formData4 and formData8.
681 case formSecOffset, formGnuRefAlt, formGnuStrpAlt:
682 is64, known := b.format.dwarf64()
683 if !known {
684 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
685 } else if is64 {
686 val = int64(b.uint64())
687 } else {
688 val = int64(b.uint32())
689 }
690 691 // exprloc
692 // New in DWARF 4.
693 case formExprloc:
694 val = b.bytes(int(b.uint()))
695 696 // reference
697 // New in DWARF 4.
698 case formRefSig8:
699 // 64-bit type signature.
700 val = b.uint64()
701 case formRefSup4:
702 val = b.uint32()
703 case formRefSup8:
704 val = b.uint64()
705 706 // loclist
707 case formLoclistx:
708 val = b.uint()
709 710 // rnglist
711 case formRnglistx:
712 off := b.uint()
713 714 rnglistsBase := int64(u.rngListsBase())
715 val = resolveRnglistx(uint64(rnglistsBase), off)
716 }
717 718 e.Field[i].Val = val
719 }
720 if b.err != nil {
721 return nil
722 }
723 return e
724 }
725 726 // A Reader allows reading [Entry] structures from a DWARF “info” section.
727 // The [Entry] structures are arranged in a tree. The [Reader.Next] function
728 // return successive entries from a pre-order traversal of the tree.
729 // If an entry has children, its Children field will be true, and the children
730 // follow, terminated by an [Entry] with [Tag] 0.
731 type Reader struct {
732 b buf
733 d *Data
734 err error
735 unit int
736 lastUnit bool // set if last entry returned by Next is TagCompileUnit/TagPartialUnit
737 lastChildren bool // .Children of last entry returned by Next
738 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next
739 cu *Entry // current compilation unit
740 }
741 742 // Reader returns a new Reader for [Data].
743 // The reader is positioned at byte offset 0 in the DWARF “info” section.
744 func (d *Data) Reader() *Reader {
745 r := &Reader{d: d}
746 r.Seek(0)
747 return r
748 }
749 750 // AddressSize returns the size in bytes of addresses in the current compilation
751 // unit.
752 func (r *Reader) AddressSize() int {
753 return r.d.unit[r.unit].asize
754 }
755 756 // ByteOrder returns the byte order in the current compilation unit.
757 func (r *Reader) ByteOrder() binary.ByteOrder {
758 return r.b.order
759 }
760 761 // Seek positions the [Reader] at offset off in the encoded entry stream.
762 // Offset 0 can be used to denote the first entry.
763 func (r *Reader) Seek(off Offset) {
764 d := r.d
765 r.err = nil
766 r.lastChildren = false
767 if off == 0 {
768 if len(d.unit) == 0 {
769 return
770 }
771 u := &d.unit[0]
772 r.unit = 0
773 r.b = makeBuf(r.d, u, "info", u.off, u.data)
774 r.collectDwarf5BaseOffsets(u)
775 r.cu = nil
776 return
777 }
778 779 i := d.offsetToUnit(off)
780 if i == -1 {
781 r.err = errors.New("offset out of range")
782 return
783 }
784 if i != r.unit {
785 r.cu = nil
786 }
787 u := &d.unit[i]
788 r.unit = i
789 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
790 r.collectDwarf5BaseOffsets(u)
791 }
792 793 // maybeNextUnit advances to the next unit if this one is finished.
794 func (r *Reader) maybeNextUnit() {
795 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
796 r.nextUnit()
797 }
798 }
799 800 // nextUnit advances to the next unit.
801 func (r *Reader) nextUnit() {
802 r.unit++
803 u := &r.d.unit[r.unit]
804 r.b = makeBuf(r.d, u, "info", u.off, u.data)
805 r.cu = nil
806 r.collectDwarf5BaseOffsets(u)
807 }
808 809 func (r *Reader) collectDwarf5BaseOffsets(u *unit) {
810 if u.vers < 5 || u.unit5 != nil {
811 return
812 }
813 u.unit5 = &unit5{}
814 if err := r.d.collectDwarf5BaseOffsets(u); err != nil {
815 r.err = err
816 }
817 }
818 819 // Next reads the next entry from the encoded entry stream.
820 // It returns nil, nil when it reaches the end of the section.
821 // It returns an error if the current offset is invalid or the data at the
822 // offset cannot be decoded as a valid [Entry].
823 func (r *Reader) Next() (*Entry, error) {
824 if r.err != nil {
825 return nil, r.err
826 }
827 r.maybeNextUnit()
828 if len(r.b.data) == 0 {
829 return nil, nil
830 }
831 u := &r.d.unit[r.unit]
832 e := r.b.entry(r.cu, u)
833 if r.b.err != nil {
834 r.err = r.b.err
835 return nil, r.err
836 }
837 r.lastUnit = false
838 if e != nil {
839 r.lastChildren = e.Children
840 if r.lastChildren {
841 r.lastSibling, _ = e.Val(AttrSibling).(Offset)
842 }
843 if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit {
844 r.lastUnit = true
845 r.cu = e
846 }
847 } else {
848 r.lastChildren = false
849 }
850 return e, nil
851 }
852 853 // SkipChildren skips over the child entries associated with
854 // the last [Entry] returned by [Reader.Next]. If that [Entry] did not have
855 // children or [Reader.Next] has not been called, SkipChildren is a no-op.
856 func (r *Reader) SkipChildren() {
857 if r.err != nil || !r.lastChildren {
858 return
859 }
860 861 // If the last entry had a sibling attribute,
862 // that attribute gives the offset of the next
863 // sibling, so we can avoid decoding the
864 // child subtrees.
865 if r.lastSibling >= r.b.off {
866 r.Seek(r.lastSibling)
867 return
868 }
869 870 if r.lastUnit && r.unit+1 < len(r.d.unit) {
871 r.nextUnit()
872 return
873 }
874 875 for {
876 e, err := r.Next()
877 if err != nil || e == nil || e.Tag == 0 {
878 break
879 }
880 if e.Children {
881 r.SkipChildren()
882 }
883 }
884 }
885 886 // clone returns a copy of the reader. This is used by the typeReader
887 // interface.
888 func (r *Reader) clone() typeReader {
889 return r.d.Reader()
890 }
891 892 // offset returns the current buffer offset. This is used by the
893 // typeReader interface.
894 func (r *Reader) offset() Offset {
895 return r.b.off
896 }
897 898 // SeekPC returns the [Entry] for the compilation unit that includes pc,
899 // and positions the reader to read the children of that unit. If pc
900 // is not covered by any unit, SeekPC returns [ErrUnknownPC] and the
901 // position of the reader is undefined.
902 //
903 // Because compilation units can describe multiple regions of the
904 // executable, in the worst case SeekPC must search through all the
905 // ranges in all the compilation units. Each call to SeekPC starts the
906 // search at the compilation unit of the last call, so in general
907 // looking up a series of PCs will be faster if they are sorted. If
908 // the caller wishes to do repeated fast PC lookups, it should build
909 // an appropriate index using the Ranges method.
910 func (r *Reader) SeekPC(pc uint64) (*Entry, error) {
911 unit := r.unit
912 for i := 0; i < len(r.d.unit); i++ {
913 if unit >= len(r.d.unit) {
914 unit = 0
915 }
916 r.err = nil
917 r.lastChildren = false
918 r.unit = unit
919 r.cu = nil
920 u := &r.d.unit[unit]
921 r.b = makeBuf(r.d, u, "info", u.off, u.data)
922 r.collectDwarf5BaseOffsets(u)
923 e, err := r.Next()
924 if err != nil {
925 return nil, err
926 }
927 if e == nil || e.Tag == 0 {
928 return nil, ErrUnknownPC
929 }
930 ranges, err := r.d.Ranges(e)
931 if err != nil {
932 return nil, err
933 }
934 for _, pcs := range ranges {
935 if pcs[0] <= pc && pc < pcs[1] {
936 return e, nil
937 }
938 }
939 unit++
940 }
941 return nil, ErrUnknownPC
942 }
943 944 // Ranges returns the PC ranges covered by e, a slice of [low,high) pairs.
945 // Only some entry types, such as [TagCompileUnit] or [TagSubprogram], have PC
946 // ranges; for others, this will return nil with no error.
947 func (d *Data) Ranges(e *Entry) ([][2]uint64, error) {
948 var ret [][2]uint64
949 950 low, lowOK := e.Val(AttrLowpc).(uint64)
951 952 var high uint64
953 var highOK bool
954 highField := e.AttrField(AttrHighpc)
955 if highField != nil {
956 switch highField.Class {
957 case ClassAddress:
958 high, highOK = highField.Val.(uint64)
959 case ClassConstant:
960 off, ok := highField.Val.(int64)
961 if ok {
962 high = low + uint64(off)
963 highOK = true
964 }
965 }
966 }
967 968 if lowOK && highOK {
969 ret = append(ret, [2]uint64{low, high})
970 }
971 972 var u *unit
973 if uidx := d.offsetToUnit(e.Offset); uidx >= 0 && uidx < len(d.unit) {
974 u = &d.unit[uidx]
975 }
976 977 if u != nil && u.vers >= 5 && d.rngLists != nil {
978 // DWARF version 5 and later
979 field := e.AttrField(AttrRanges)
980 if field == nil {
981 return ret, nil
982 }
983 switch field.Class {
984 case ClassRangeListPtr:
985 ranges, rangesOK := field.Val.(int64)
986 if !rangesOK {
987 return ret, nil
988 }
989 cu, base, err := d.baseAddressForEntry(e)
990 if err != nil {
991 return nil, err
992 }
993 return d.dwarf5Ranges(u, cu, base, ranges, ret)
994 995 case ClassRngList:
996 rnglist, ok := field.Val.(uint64)
997 if !ok {
998 return ret, nil
999 }
1000 cu, base, err := d.baseAddressForEntry(e)
1001 if err != nil {
1002 return nil, err
1003 }
1004 return d.dwarf5Ranges(u, cu, base, int64(rnglist), ret)
1005 1006 default:
1007 return ret, nil
1008 }
1009 }
1010 1011 // DWARF version 2 through 4
1012 ranges, rangesOK := e.Val(AttrRanges).(int64)
1013 if rangesOK && d.ranges != nil {
1014 _, base, err := d.baseAddressForEntry(e)
1015 if err != nil {
1016 return nil, err
1017 }
1018 return d.dwarf2Ranges(u, base, ranges, ret)
1019 }
1020 1021 return ret, nil
1022 }
1023 1024 // baseAddressForEntry returns the initial base address to be used when
1025 // looking up the range list of entry e.
1026 // DWARF specifies that this should be the lowpc attribute of the enclosing
1027 // compilation unit, however comments in gdb/dwarf2read.c say that some
1028 // versions of GCC use the entrypc attribute, so we check that too.
1029 func (d *Data) baseAddressForEntry(e *Entry) (*Entry, uint64, error) {
1030 var cu *Entry
1031 if e.Tag == TagCompileUnit {
1032 cu = e
1033 } else {
1034 i := d.offsetToUnit(e.Offset)
1035 if i == -1 {
1036 return nil, 0, errors.New("no unit for entry")
1037 }
1038 u := &d.unit[i]
1039 b := makeBuf(d, u, "info", u.off, u.data)
1040 cu = b.entry(nil, u)
1041 if b.err != nil {
1042 return nil, 0, b.err
1043 }
1044 }
1045 1046 if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK {
1047 return cu, cuEntry, nil
1048 } else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK {
1049 return cu, cuLow, nil
1050 }
1051 1052 return cu, 0, nil
1053 }
1054 1055 func (d *Data) dwarf2Ranges(u *unit, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
1056 if ranges < 0 || ranges > int64(len(d.ranges)) {
1057 return nil, fmt.Errorf("invalid range offset %d (max %d)", ranges, len(d.ranges))
1058 }
1059 buf := makeBuf(d, u, "ranges", Offset(ranges), d.ranges[ranges:])
1060 for len(buf.data) > 0 {
1061 low := buf.addr()
1062 high := buf.addr()
1063 1064 if low == 0 && high == 0 {
1065 break
1066 }
1067 1068 if low == ^uint64(0)>>uint((8-u.addrsize())*8) {
1069 base = high
1070 } else {
1071 ret = append(ret, [2]uint64{base + low, base + high})
1072 }
1073 }
1074 1075 return ret, nil
1076 }
1077 1078 // dwarf5Ranges interprets a debug_rnglists sequence, see DWARFv5 section
1079 // 2.17.3 (page 53).
1080 func (d *Data) dwarf5Ranges(u *unit, cu *Entry, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
1081 if ranges < 0 || ranges > int64(len(d.rngLists)) {
1082 return nil, fmt.Errorf("invalid rnglist offset %d (max %d)", ranges, len(d.ranges))
1083 }
1084 var addrBase int64
1085 if cu != nil {
1086 addrBase, _ = cu.Val(AttrAddrBase).(int64)
1087 }
1088 1089 buf := makeBuf(d, u, "rnglists", 0, d.rngLists)
1090 buf.skip(int(ranges))
1091 for {
1092 opcode := buf.uint8()
1093 switch opcode {
1094 case rleEndOfList:
1095 if buf.err != nil {
1096 return nil, buf.err
1097 }
1098 return ret, nil
1099 1100 case rleBaseAddressx:
1101 baseIdx := buf.uint()
1102 var err error
1103 base, err = d.debugAddr(u, uint64(addrBase), baseIdx)
1104 if err != nil {
1105 return nil, err
1106 }
1107 1108 case rleStartxEndx:
1109 startIdx := buf.uint()
1110 endIdx := buf.uint()
1111 1112 start, err := d.debugAddr(u, uint64(addrBase), startIdx)
1113 if err != nil {
1114 return nil, err
1115 }
1116 end, err := d.debugAddr(u, uint64(addrBase), endIdx)
1117 if err != nil {
1118 return nil, err
1119 }
1120 ret = append(ret, [2]uint64{start, end})
1121 1122 case rleStartxLength:
1123 startIdx := buf.uint()
1124 len := buf.uint()
1125 start, err := d.debugAddr(u, uint64(addrBase), startIdx)
1126 if err != nil {
1127 return nil, err
1128 }
1129 ret = append(ret, [2]uint64{start, start + len})
1130 1131 case rleOffsetPair:
1132 off1 := buf.uint()
1133 off2 := buf.uint()
1134 ret = append(ret, [2]uint64{base + off1, base + off2})
1135 1136 case rleBaseAddress:
1137 base = buf.addr()
1138 1139 case rleStartEnd:
1140 start := buf.addr()
1141 end := buf.addr()
1142 ret = append(ret, [2]uint64{start, end})
1143 1144 case rleStartLength:
1145 start := buf.addr()
1146 len := buf.uint()
1147 ret = append(ret, [2]uint64{start, start + len})
1148 }
1149 }
1150 }
1151 1152 // debugAddr returns the address at idx in debug_addr
1153 func (d *Data) debugAddr(format dataFormat, addrBase, idx uint64) (uint64, error) {
1154 off := idx*uint64(format.addrsize()) + addrBase
1155 1156 if uint64(int(off)) != off {
1157 return 0, errors.New("offset out of range")
1158 }
1159 1160 b := makeBuf(d, format, "addr", 0, d.addr)
1161 b.skip(int(off))
1162 val := b.addr()
1163 if b.err != nil {
1164 return 0, b.err
1165 }
1166 return val, nil
1167 }
1168