Source file src/debug/dwarf/entry.go

     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 = make([]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:    make([]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 = new(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  

View as plain text