entry.mx raw

   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