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