func (r *Reader) Next() (*Entry, error) {
	if r.err != nil {
		return nil, r.err
	}
	r.maybeNextUnit()
	if len(r.b.data) == 0 {
		return nil, nil
	}
	u := &r.d.unit[r.unit]
	e := r.b.entry(r.cu, u.atable, u.base, u.vers)
	if r.b.err != nil {
		r.err = r.b.err
		return nil, r.err
	}
	r.lastUnit = false
	if e != nil {
		r.lastChildren = e.Children
		if r.lastChildren {
			r.lastSibling, _ = e.Val(AttrSibling).(Offset)
		}
		if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit {
			r.lastUnit = true
			r.cu = e
		}
	} else {
		r.lastChildren = false
	}
	return e, nil
}
Next reads the next entry from the encoded entry stream.
It returns nil, nil when it reaches the end of the section.
It returns an error if the current offset is invalid or the data at the
offset cannot be decoded as a valid Entry.
package dwarf
import (
	"encoding/binary"
	"errors"
	"strconv"
)
type abbrev struct {
	tag      Tag
	children bool
	field    []afield
}
type afield struct {
	attr  Attr
	fmt   format
	class Class
	val   int64  
}
type abbrevTable map[uint32]abbrev
func (d *Data) parseAbbrev(off uint64, vers int) (abbrevTable, error) {
	if m, ok := d.abbrevCache[off]; ok {
		return m, nil
	}
	data := d.abbrev
	if off > uint64(len(data)) {
		data = nil
	} else {
		data = data[off:]
	}
	b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
	m := make(abbrevTable)
	for {
		id := uint32(b.uint())
		if id == 0 {
			break
		}
		n := 0
		b1 := b  
		b1.uint()
		b1.uint8()
		for {
			tag := b1.uint()
			fmt := b1.uint()
			if tag == 0 && fmt == 0 {
				break
			}
			if format(fmt) == formImplicitConst {
				b1.int()
			}
			n++
		}
		if b1.err != nil {
			return nil, b1.err
		}
		var a abbrev
		a.tag = Tag(b.uint())
		a.children = b.uint8() != 0
		a.field = make([]afield, n)
		for i := range a.field {
			a.field[i].attr = Attr(b.uint())
			a.field[i].fmt = format(b.uint())
			a.field[i].class = formToClass(a.field[i].fmt, a.field[i].attr, vers, &b)
			if a.field[i].fmt == formImplicitConst {
				a.field[i].val = b.int()
			}
		}
		b.uint()
		b.uint()
		m[id] = a
	}
	if b.err != nil {
		return nil, b.err
	}
	d.abbrevCache[off] = m
	return m, nil
}
var attrIsExprloc = map[Attr]bool{
	AttrLocation:      true,
	AttrByteSize:      true,
	AttrBitOffset:     true,
	AttrBitSize:       true,
	AttrStringLength:  true,
	AttrLowerBound:    true,
	AttrReturnAddr:    true,
	AttrStrideSize:    true,
	AttrUpperBound:    true,
	AttrCount:         true,
	AttrDataMemberLoc: true,
	AttrFrameBase:     true,
	AttrSegment:       true,
	AttrStaticLink:    true,
	AttrUseLocation:   true,
	AttrVtableElemLoc: true,
	AttrAllocated:     true,
	AttrAssociated:    true,
	AttrDataLocation:  true,
	AttrStride:        true,
}
var attrPtrClass = map[Attr]Class{
	AttrLocation:      ClassLocListPtr,
	AttrStmtList:      ClassLinePtr,
	AttrStringLength:  ClassLocListPtr,
	AttrReturnAddr:    ClassLocListPtr,
	AttrStartScope:    ClassRangeListPtr,
	AttrDataMemberLoc: ClassLocListPtr,
	AttrFrameBase:     ClassLocListPtr,
	AttrMacroInfo:     ClassMacPtr,
	AttrSegment:       ClassLocListPtr,
	AttrStaticLink:    ClassLocListPtr,
	AttrUseLocation:   ClassLocListPtr,
	AttrVtableElemLoc: ClassLocListPtr,
	AttrRanges:        ClassRangeListPtr,
	AttrStrOffsetsBase: ClassStrOffsetsPtr,
	AttrAddrBase:       ClassAddrPtr,
	AttrRnglistsBase:   ClassRngListsPtr,
	AttrLoclistsBase:   ClassLocListPtr,
}
func formToClass(form format, attr Attr, vers int, b *buf) Class {
	switch form {
	default:
		b.error("cannot determine class of unknown attribute form")
		return 0
	case formIndirect:
		return ClassUnknown
	case formAddr, formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
		return ClassAddress
	case formDwarfBlock1, formDwarfBlock2, formDwarfBlock4, formDwarfBlock:
		if attrIsExprloc[attr] {
			return ClassExprLoc
		}
		return ClassBlock
	case formData1, formData2, formData4, formData8, formSdata, formUdata, formData16, formImplicitConst:
		if class, ok := attrPtrClass[attr]; vers < 4 && ok {
			return class
		}
		return ClassConstant
	case formFlag, formFlagPresent:
		return ClassFlag
	case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata, formRefSup4, formRefSup8:
		return ClassReference
	case formRefSig8:
		return ClassReferenceSig
	case formString, formStrp, formStrx, formStrpSup, formLineStrp, formStrx1, formStrx2, formStrx3, formStrx4:
		return ClassString
	case formSecOffset:
		if class, ok := attrPtrClass[attr]; ok {
			return class
		}
		return ClassUnknown
	case formExprloc:
		return ClassExprLoc
	case formGnuRefAlt:
		return ClassReferenceAlt
	case formGnuStrpAlt:
		return ClassStringAlt
	case formLoclistx:
		return ClassLocList
	case formRnglistx:
		return ClassRngList
	}
}
type Entry struct {
	Offset   Offset  
	Tag      Tag     
	Children bool    
	Field    []Field
}
type Field struct {
	Attr  Attr
	Val   interface{}
	Class Class
}
type Class int
const (
	ClassUnknown Class = iota
	ClassAddress
	ClassBlock
	ClassConstant
	ClassExprLoc
	ClassFlag
	ClassLinePtr
	ClassLocListPtr
	ClassMacPtr
	ClassRangeListPtr
	ClassReference
	ClassReferenceSig
	ClassString
	ClassReferenceAlt
	ClassStringAlt
	ClassAddrPtr
	ClassLocList
	ClassRngList
	ClassRngListsPtr
	ClassStrOffsetsPtr
)
func (i Class) GoString() string {
	return "dwarf." + i.String()
}
func (e *Entry) Val(a Attr) interface{} {
	if f := e.AttrField(a); f != nil {
		return f.Val
	}
	return nil
}
func (e *Entry) AttrField(a Attr) *Field {
	for i, f := range e.Field {
		if f.Attr == a {
			return &e.Field[i]
		}
	}
	return nil
}
type Offset uint32
func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry {
	off := b.off
	id := uint32(b.uint())
	if id == 0 {
		return &Entry{}
	}
	a, ok := atab[id]
	if !ok {
		b.error("unknown abbreviation table index")
		return nil
	}
	e := &Entry{
		Offset:   off,
		Tag:      a.tag,
		Children: a.children,
		Field:    make([]Field, len(a.field)),
	}
	for i := range e.Field {
		e.Field[i].Attr = a.field[i].attr
		e.Field[i].Class = a.field[i].class
		fmt := a.field[i].fmt
		if fmt == formIndirect {
			fmt = format(b.uint())
			e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b)
		}
		var val interface{}
		switch fmt {
		default:
			b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
		case formAddr:
			val = b.addr()
		case formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
			var off uint64
			switch fmt {
			case formAddrx:
				off = b.uint()
			case formAddrx1:
				off = uint64(b.uint8())
			case formAddrx2:
				off = uint64(b.uint16())
			case formAddrx3:
				off = uint64(b.uint24())
			case formAddrx4:
				off = uint64(b.uint32())
			}
			if b.dwarf.addr == nil {
				b.error("DW_FORM_addrx with no .debug_addr section")
			}
			if b.err != nil {
				return nil
			}
			var addrBase int64
			if cu != nil {
				addrBase, _ = cu.Val(AttrAddrBase).(int64)
			}
			var err error
			val, err = b.dwarf.debugAddr(uint64(addrBase), off)
			if err != nil {
				if b.err == nil {
					b.err = err
				}
				return nil
			}
		case formDwarfBlock1:
			val = b.bytes(int(b.uint8()))
		case formDwarfBlock2:
			val = b.bytes(int(b.uint16()))
		case formDwarfBlock4:
			val = b.bytes(int(b.uint32()))
		case formDwarfBlock:
			val = b.bytes(int(b.uint()))
		case formData1:
			val = int64(b.uint8())
		case formData2:
			val = int64(b.uint16())
		case formData4:
			val = int64(b.uint32())
		case formData8:
			val = int64(b.uint64())
		case formData16:
			val = b.bytes(16)
		case formSdata:
			val = int64(b.int())
		case formUdata:
			val = int64(b.uint())
		case formImplicitConst:
			val = a.field[i].val
		case formFlag:
			val = b.uint8() == 1
		case formFlagPresent:
			val = true
		case formRefAddr:
			vers := b.format.version()
			if vers == 0 {
				b.error("unknown version for DW_FORM_ref_addr")
			} else if vers == 2 {
				val = Offset(b.addr())
			} else {
				is64, known := b.format.dwarf64()
				if !known {
					b.error("unknown size for DW_FORM_ref_addr")
				} else if is64 {
					val = Offset(b.uint64())
				} else {
					val = Offset(b.uint32())
				}
			}
		case formRef1:
			val = Offset(b.uint8()) + ubase
		case formRef2:
			val = Offset(b.uint16()) + ubase
		case formRef4:
			val = Offset(b.uint32()) + ubase
		case formRef8:
			val = Offset(b.uint64()) + ubase
		case formRefUdata:
			val = Offset(b.uint()) + ubase
		case formString:
			val = b.string()
		case formStrp, formLineStrp:
			var off uint64  
			is64, known := b.format.dwarf64()
			if !known {
				b.error("unknown size for DW_FORM_strp/line_strp")
			} else if is64 {
				off = b.uint64()
			} else {
				off = uint64(b.uint32())
			}
			if uint64(int(off)) != off {
				b.error("DW_FORM_strp/line_strp offset out of range")
			}
			if b.err != nil {
				return nil
			}
			var b1 buf
			if fmt == formStrp {
				b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
			} else {
				if len(b.dwarf.lineStr) == 0 {
					b.error("DW_FORM_line_strp with no .debug_line_str section")
				}
				b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr)
			}
			b1.skip(int(off))
			val = b1.string()
			if b1.err != nil {
				b.err = b1.err
				return nil
			}
		case formStrx, formStrx1, formStrx2, formStrx3, formStrx4:
			var off uint64
			switch fmt {
			case formStrx:
				off = b.uint()
			case formStrx1:
				off = uint64(b.uint8())
			case formStrx2:
				off = uint64(b.uint16())
			case formStrx3:
				off = uint64(b.uint24())
			case formStrx4:
				off = uint64(b.uint32())
			}
			if len(b.dwarf.strOffsets) == 0 {
				b.error("DW_FORM_strx with no .debug_str_offsets section")
			}
			is64, known := b.format.dwarf64()
			if !known {
				b.error("unknown offset size for DW_FORM_strx")
			}
			if b.err != nil {
				return nil
			}
			if is64 {
				off *= 8
			} else {
				off *= 4
			}
			if cu != nil {
				cuOff, ok := cu.Val(AttrStrOffsetsBase).(int64)
				if ok {
					off += uint64(cuOff)
				}
			}
			if uint64(int(off)) != off {
				b.error("DW_FORM_strx offset out of range")
			}
			b1 := makeBuf(b.dwarf, b.format, "str_offsets", 0, b.dwarf.strOffsets)
			b1.skip(int(off))
			if is64 {
				off = b1.uint64()
			} else {
				off = uint64(b1.uint32())
			}
			if b1.err != nil {
				b.err = b1.err
				return nil
			}
			if uint64(int(off)) != off {
				b.error("DW_FORM_strx indirect offset out of range")
			}
			b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
			b1.skip(int(off))
			val = b1.string()
			if b1.err != nil {
				b.err = b1.err
				return nil
			}
		case formStrpSup:
			is64, known := b.format.dwarf64()
			if !known {
				b.error("unknown size for DW_FORM_strp_sup")
			} else if is64 {
				val = b.uint64()
			} else {
				val = b.uint32()
			}
		case formSecOffset, formGnuRefAlt, formGnuStrpAlt:
			is64, known := b.format.dwarf64()
			if !known {
				b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
			} else if is64 {
				val = int64(b.uint64())
			} else {
				val = int64(b.uint32())
			}
		case formExprloc:
			val = b.bytes(int(b.uint()))
		case formRefSig8:
			val = b.uint64()
		case formRefSup4:
			val = b.uint32()
		case formRefSup8:
			val = b.uint64()
		case formLoclistx:
			val = b.uint()
		case formRnglistx:
			val = b.uint()
		}
		e.Field[i].Val = val
	}
	if b.err != nil {
		return nil
	}
	return e
}
type Reader struct {
	b            buf
	d            *Data
	err          error
	unit         int
	lastUnit     bool    
	lastChildren bool    
	lastSibling  Offset  
	cu           *Entry  
}
func (d *Data) Reader() *Reader {
	r := &Reader{d: d}
	r.Seek(0)
	return r
}
func (r *Reader) AddressSize() int {
	return r.d.unit[r.unit].asize
}
func (r *Reader) ByteOrder() binary.ByteOrder {
	return r.b.order
}
func (r *Reader) Seek(off Offset) {
	d := r.d
	r.err = nil
	r.lastChildren = false
	if off == 0 {
		if len(d.unit) == 0 {
			return
		}
		u := &d.unit[0]
		r.unit = 0
		r.b = makeBuf(r.d, u, "info", u.off, u.data)
		r.cu = nil
		return
	}
	i := d.offsetToUnit(off)
	if i == -1 {
		r.err = errors.New("offset out of range")
		return
	}
	if i != r.unit {
		r.cu = nil
	}
	u := &d.unit[i]
	r.unit = i
	r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
}
func (r *Reader) maybeNextUnit() {
	for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
		r.nextUnit()
	}
}
func (r *Reader) nextUnit() {
	r.unit++
	u := &r.d.unit[r.unit]
	r.b = makeBuf(r.d, u, "info", u.off, u.data)
	r.cu = nil
}