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  	"strconv"
    17  )
    18  
    19  // a single entry's description: a sequence of attributes
    20  type abbrev struct {
    21  	tag      Tag
    22  	children bool
    23  	field    []afield
    24  }
    25  
    26  type 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
    34  type abbrevTable map[uint32]abbrev
    35  
    36  // ParseAbbrev returns the abbreviation table that starts at byte off
    37  // in the .debug_abbrev section.
    38  func (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.
   109  var 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.
   134  var 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.
   158  func 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.
   232  type 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.
   262  type Field struct {
   263  	Attr  Attr
   264  	Val   any
   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.
   282  type Class int
   283  
   284  const (
   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  	// ClassRangeListPtr 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 a uint64 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  
   374  func (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  //
   384  //	v, ok := e.Val(AttrSibling).(int64)
   385  func (e *Entry) Val(a Attr) any {
   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.
   394  func (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.)
   405  type Offset uint32
   406  
   407  // Entry reads a single entry from buf, decoding
   408  // according to the given abbreviation table.
   409  func (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  
   427  	// If we are currently parsing the compilation unit,
   428  	// we can't evaluate Addrx or Strx until we've seen the
   429  	// relevant base entry.
   430  	type delayed struct {
   431  		idx int
   432  		off uint64
   433  		fmt format
   434  	}
   435  	var delay []delayed
   436  
   437  	resolveStrx := func(strBase, off uint64) string {
   438  		off += strBase
   439  		if uint64(int(off)) != off {
   440  			b.error("DW_FORM_strx offset out of range")
   441  		}
   442  
   443  		b1 := makeBuf(b.dwarf, b.format, "str_offsets", 0, b.dwarf.strOffsets)
   444  		b1.skip(int(off))
   445  		is64, _ := b.format.dwarf64()
   446  		if is64 {
   447  			off = b1.uint64()
   448  		} else {
   449  			off = uint64(b1.uint32())
   450  		}
   451  		if b1.err != nil {
   452  			b.err = b1.err
   453  			return ""
   454  		}
   455  		if uint64(int(off)) != off {
   456  			b.error("DW_FORM_strx indirect offset out of range")
   457  		}
   458  		b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
   459  		b1.skip(int(off))
   460  		val := b1.string()
   461  		if b1.err != nil {
   462  			b.err = b1.err
   463  		}
   464  		return val
   465  	}
   466  
   467  	resolveRnglistx := func(rnglistsBase, off uint64) uint64 {
   468  		is64, _ := b.format.dwarf64()
   469  		if is64 {
   470  			off *= 8
   471  		} else {
   472  			off *= 4
   473  		}
   474  		off += rnglistsBase
   475  		if uint64(int(off)) != off {
   476  			b.error("DW_FORM_rnglistx offset out of range")
   477  		}
   478  
   479  		b1 := makeBuf(b.dwarf, b.format, "rnglists", 0, b.dwarf.rngLists)
   480  		b1.skip(int(off))
   481  		if is64 {
   482  			off = b1.uint64()
   483  		} else {
   484  			off = uint64(b1.uint32())
   485  		}
   486  		if b1.err != nil {
   487  			b.err = b1.err
   488  			return 0
   489  		}
   490  		if uint64(int(off)) != off {
   491  			b.error("DW_FORM_rnglistx indirect offset out of range")
   492  		}
   493  		return rnglistsBase + off
   494  	}
   495  
   496  	for i := range e.Field {
   497  		e.Field[i].Attr = a.field[i].attr
   498  		e.Field[i].Class = a.field[i].class
   499  		fmt := a.field[i].fmt
   500  		if fmt == formIndirect {
   501  			fmt = format(b.uint())
   502  			e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b)
   503  		}
   504  		var val any
   505  		switch fmt {
   506  		default:
   507  			b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
   508  
   509  		// address
   510  		case formAddr:
   511  			val = b.addr()
   512  		case formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
   513  			var off uint64
   514  			switch fmt {
   515  			case formAddrx:
   516  				off = b.uint()
   517  			case formAddrx1:
   518  				off = uint64(b.uint8())
   519  			case formAddrx2:
   520  				off = uint64(b.uint16())
   521  			case formAddrx3:
   522  				off = uint64(b.uint24())
   523  			case formAddrx4:
   524  				off = uint64(b.uint32())
   525  			}
   526  			if b.dwarf.addr == nil {
   527  				b.error("DW_FORM_addrx with no .debug_addr section")
   528  			}
   529  			if b.err != nil {
   530  				return nil
   531  			}
   532  
   533  			// We have to adjust by the offset of the
   534  			// compilation unit. This won't work if the
   535  			// program uses Reader.Seek to skip over the
   536  			// unit. Not much we can do about that.
   537  			var addrBase int64
   538  			if cu != nil {
   539  				addrBase, _ = cu.Val(AttrAddrBase).(int64)
   540  			} else if a.tag == TagCompileUnit {
   541  				delay = append(delay, delayed{i, off, formAddrx})
   542  				break
   543  			}
   544  
   545  			var err error
   546  			val, err = b.dwarf.debugAddr(b.format, uint64(addrBase), off)
   547  			if err != nil {
   548  				if b.err == nil {
   549  					b.err = err
   550  				}
   551  				return nil
   552  			}
   553  
   554  		// block
   555  		case formDwarfBlock1:
   556  			val = b.bytes(int(b.uint8()))
   557  		case formDwarfBlock2:
   558  			val = b.bytes(int(b.uint16()))
   559  		case formDwarfBlock4:
   560  			val = b.bytes(int(b.uint32()))
   561  		case formDwarfBlock:
   562  			val = b.bytes(int(b.uint()))
   563  
   564  		// constant
   565  		case formData1:
   566  			val = int64(b.uint8())
   567  		case formData2:
   568  			val = int64(b.uint16())
   569  		case formData4:
   570  			val = int64(b.uint32())
   571  		case formData8:
   572  			val = int64(b.uint64())
   573  		case formData16:
   574  			val = b.bytes(16)
   575  		case formSdata:
   576  			val = int64(b.int())
   577  		case formUdata:
   578  			val = int64(b.uint())
   579  		case formImplicitConst:
   580  			val = a.field[i].val
   581  
   582  		// flag
   583  		case formFlag:
   584  			val = b.uint8() == 1
   585  		// New in DWARF 4.
   586  		case formFlagPresent:
   587  			// The attribute is implicitly indicated as present, and no value is
   588  			// encoded in the debugging information entry itself.
   589  			val = true
   590  
   591  		// reference to other entry
   592  		case formRefAddr:
   593  			vers := b.format.version()
   594  			if vers == 0 {
   595  				b.error("unknown version for DW_FORM_ref_addr")
   596  			} else if vers == 2 {
   597  				val = Offset(b.addr())
   598  			} else {
   599  				is64, known := b.format.dwarf64()
   600  				if !known {
   601  					b.error("unknown size for DW_FORM_ref_addr")
   602  				} else if is64 {
   603  					val = Offset(b.uint64())
   604  				} else {
   605  					val = Offset(b.uint32())
   606  				}
   607  			}
   608  		case formRef1:
   609  			val = Offset(b.uint8()) + ubase
   610  		case formRef2:
   611  			val = Offset(b.uint16()) + ubase
   612  		case formRef4:
   613  			val = Offset(b.uint32()) + ubase
   614  		case formRef8:
   615  			val = Offset(b.uint64()) + ubase
   616  		case formRefUdata:
   617  			val = Offset(b.uint()) + ubase
   618  
   619  		// string
   620  		case formString:
   621  			val = b.string()
   622  		case formStrp, formLineStrp:
   623  			var off uint64 // offset into .debug_str
   624  			is64, known := b.format.dwarf64()
   625  			if !known {
   626  				b.error("unknown size for DW_FORM_strp/line_strp")
   627  			} else if is64 {
   628  				off = b.uint64()
   629  			} else {
   630  				off = uint64(b.uint32())
   631  			}
   632  			if uint64(int(off)) != off {
   633  				b.error("DW_FORM_strp/line_strp offset out of range")
   634  			}
   635  			if b.err != nil {
   636  				return nil
   637  			}
   638  			var b1 buf
   639  			if fmt == formStrp {
   640  				b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
   641  			} else {
   642  				if len(b.dwarf.lineStr) == 0 {
   643  					b.error("DW_FORM_line_strp with no .debug_line_str section")
   644  					return nil
   645  				}
   646  				b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr)
   647  			}
   648  			b1.skip(int(off))
   649  			val = b1.string()
   650  			if b1.err != nil {
   651  				b.err = b1.err
   652  				return nil
   653  			}
   654  		case formStrx, formStrx1, formStrx2, formStrx3, formStrx4:
   655  			var off uint64
   656  			switch fmt {
   657  			case formStrx:
   658  				off = b.uint()
   659  			case formStrx1:
   660  				off = uint64(b.uint8())
   661  			case formStrx2:
   662  				off = uint64(b.uint16())
   663  			case formStrx3:
   664  				off = uint64(b.uint24())
   665  			case formStrx4:
   666  				off = uint64(b.uint32())
   667  			}
   668  			if len(b.dwarf.strOffsets) == 0 {
   669  				b.error("DW_FORM_strx with no .debug_str_offsets section")
   670  			}
   671  			is64, known := b.format.dwarf64()
   672  			if !known {
   673  				b.error("unknown offset size for DW_FORM_strx")
   674  			}
   675  			if b.err != nil {
   676  				return nil
   677  			}
   678  			if is64 {
   679  				off *= 8
   680  			} else {
   681  				off *= 4
   682  			}
   683  
   684  			// We have to adjust by the offset of the
   685  			// compilation unit. This won't work if the
   686  			// program uses Reader.Seek to skip over the
   687  			// unit. Not much we can do about that.
   688  			var strBase int64
   689  			if cu != nil {
   690  				strBase, _ = cu.Val(AttrStrOffsetsBase).(int64)
   691  			} else if a.tag == TagCompileUnit {
   692  				delay = append(delay, delayed{i, off, formStrx})
   693  				break
   694  			}
   695  
   696  			val = resolveStrx(uint64(strBase), off)
   697  
   698  		case formStrpSup:
   699  			is64, known := b.format.dwarf64()
   700  			if !known {
   701  				b.error("unknown size for DW_FORM_strp_sup")
   702  			} else if is64 {
   703  				val = b.uint64()
   704  			} else {
   705  				val = b.uint32()
   706  			}
   707  
   708  		// lineptr, loclistptr, macptr, rangelistptr
   709  		// New in DWARF 4, but clang can generate them with -gdwarf-2.
   710  		// Section reference, replacing use of formData4 and formData8.
   711  		case formSecOffset, formGnuRefAlt, formGnuStrpAlt:
   712  			is64, known := b.format.dwarf64()
   713  			if !known {
   714  				b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
   715  			} else if is64 {
   716  				val = int64(b.uint64())
   717  			} else {
   718  				val = int64(b.uint32())
   719  			}
   720  
   721  		// exprloc
   722  		// New in DWARF 4.
   723  		case formExprloc:
   724  			val = b.bytes(int(b.uint()))
   725  
   726  		// reference
   727  		// New in DWARF 4.
   728  		case formRefSig8:
   729  			// 64-bit type signature.
   730  			val = b.uint64()
   731  		case formRefSup4:
   732  			val = b.uint32()
   733  		case formRefSup8:
   734  			val = b.uint64()
   735  
   736  		// loclist
   737  		case formLoclistx:
   738  			val = b.uint()
   739  
   740  		// rnglist
   741  		case formRnglistx:
   742  			off := b.uint()
   743  
   744  			// We have to adjust by the rnglists_base of
   745  			// the compilation unit. This won't work if
   746  			// the program uses Reader.Seek to skip over
   747  			// the unit. Not much we can do about that.
   748  			var rnglistsBase int64
   749  			if cu != nil {
   750  				rnglistsBase, _ = cu.Val(AttrRnglistsBase).(int64)
   751  			} else if a.tag == TagCompileUnit {
   752  				delay = append(delay, delayed{i, off, formRnglistx})
   753  				break
   754  			}
   755  
   756  			val = resolveRnglistx(uint64(rnglistsBase), off)
   757  		}
   758  
   759  		e.Field[i].Val = val
   760  	}
   761  	if b.err != nil {
   762  		return nil
   763  	}
   764  
   765  	for _, del := range delay {
   766  		switch del.fmt {
   767  		case formAddrx:
   768  			addrBase, _ := e.Val(AttrAddrBase).(int64)
   769  			val, err := b.dwarf.debugAddr(b.format, uint64(addrBase), del.off)
   770  			if err != nil {
   771  				b.err = err
   772  				return nil
   773  			}
   774  			e.Field[del.idx].Val = val
   775  		case formStrx:
   776  			strBase, _ := e.Val(AttrStrOffsetsBase).(int64)
   777  			e.Field[del.idx].Val = resolveStrx(uint64(strBase), del.off)
   778  			if b.err != nil {
   779  				return nil
   780  			}
   781  		case formRnglistx:
   782  			rnglistsBase, _ := e.Val(AttrRnglistsBase).(int64)
   783  			e.Field[del.idx].Val = resolveRnglistx(uint64(rnglistsBase), del.off)
   784  			if b.err != nil {
   785  				return nil
   786  			}
   787  		}
   788  	}
   789  
   790  	return e
   791  }
   792  
   793  // A Reader allows reading Entry structures from a DWARF “info” section.
   794  // The Entry structures are arranged in a tree. The Reader's Next function
   795  // return successive entries from a pre-order traversal of the tree.
   796  // If an entry has children, its Children field will be true, and the children
   797  // follow, terminated by an Entry with Tag 0.
   798  type Reader struct {
   799  	b            buf
   800  	d            *Data
   801  	err          error
   802  	unit         int
   803  	lastUnit     bool   // set if last entry returned by Next is TagCompileUnit/TagPartialUnit
   804  	lastChildren bool   // .Children of last entry returned by Next
   805  	lastSibling  Offset // .Val(AttrSibling) of last entry returned by Next
   806  	cu           *Entry // current compilation unit
   807  }
   808  
   809  // Reader returns a new Reader for Data.
   810  // The reader is positioned at byte offset 0 in the DWARF “info” section.
   811  func (d *Data) Reader() *Reader {
   812  	r := &Reader{d: d}
   813  	r.Seek(0)
   814  	return r
   815  }
   816  
   817  // AddressSize returns the size in bytes of addresses in the current compilation
   818  // unit.
   819  func (r *Reader) AddressSize() int {
   820  	return r.d.unit[r.unit].asize
   821  }
   822  
   823  // ByteOrder returns the byte order in the current compilation unit.
   824  func (r *Reader) ByteOrder() binary.ByteOrder {
   825  	return r.b.order
   826  }
   827  
   828  // Seek positions the Reader at offset off in the encoded entry stream.
   829  // Offset 0 can be used to denote the first entry.
   830  func (r *Reader) Seek(off Offset) {
   831  	d := r.d
   832  	r.err = nil
   833  	r.lastChildren = false
   834  	if off == 0 {
   835  		if len(d.unit) == 0 {
   836  			return
   837  		}
   838  		u := &d.unit[0]
   839  		r.unit = 0
   840  		r.b = makeBuf(r.d, u, "info", u.off, u.data)
   841  		r.cu = nil
   842  		return
   843  	}
   844  
   845  	i := d.offsetToUnit(off)
   846  	if i == -1 {
   847  		r.err = errors.New("offset out of range")
   848  		return
   849  	}
   850  	if i != r.unit {
   851  		r.cu = nil
   852  	}
   853  	u := &d.unit[i]
   854  	r.unit = i
   855  	r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
   856  }
   857  
   858  // maybeNextUnit advances to the next unit if this one is finished.
   859  func (r *Reader) maybeNextUnit() {
   860  	for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
   861  		r.nextUnit()
   862  	}
   863  }
   864  
   865  // nextUnit advances to the next unit.
   866  func (r *Reader) nextUnit() {
   867  	r.unit++
   868  	u := &r.d.unit[r.unit]
   869  	r.b = makeBuf(r.d, u, "info", u.off, u.data)
   870  	r.cu = nil
   871  }
   872  
   873  // Next reads the next entry from the encoded entry stream.
   874  // It returns nil, nil when it reaches the end of the section.
   875  // It returns an error if the current offset is invalid or the data at the
   876  // offset cannot be decoded as a valid Entry.
   877  func (r *Reader) Next() (*Entry, error) {
   878  	if r.err != nil {
   879  		return nil, r.err
   880  	}
   881  	r.maybeNextUnit()
   882  	if len(r.b.data) == 0 {
   883  		return nil, nil
   884  	}
   885  	u := &r.d.unit[r.unit]
   886  	e := r.b.entry(r.cu, u.atable, u.base, u.vers)
   887  	if r.b.err != nil {
   888  		r.err = r.b.err
   889  		return nil, r.err
   890  	}
   891  	r.lastUnit = false
   892  	if e != nil {
   893  		r.lastChildren = e.Children
   894  		if r.lastChildren {
   895  			r.lastSibling, _ = e.Val(AttrSibling).(Offset)
   896  		}
   897  		if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit {
   898  			r.lastUnit = true
   899  			r.cu = e
   900  		}
   901  	} else {
   902  		r.lastChildren = false
   903  	}
   904  	return e, nil
   905  }
   906  
   907  // SkipChildren skips over the child entries associated with
   908  // the last Entry returned by Next. If that Entry did not have
   909  // children or Next has not been called, SkipChildren is a no-op.
   910  func (r *Reader) SkipChildren() {
   911  	if r.err != nil || !r.lastChildren {
   912  		return
   913  	}
   914  
   915  	// If the last entry had a sibling attribute,
   916  	// that attribute gives the offset of the next
   917  	// sibling, so we can avoid decoding the
   918  	// child subtrees.
   919  	if r.lastSibling >= r.b.off {
   920  		r.Seek(r.lastSibling)
   921  		return
   922  	}
   923  
   924  	if r.lastUnit && r.unit+1 < len(r.d.unit) {
   925  		r.nextUnit()
   926  		return
   927  	}
   928  
   929  	for {
   930  		e, err := r.Next()
   931  		if err != nil || e == nil || e.Tag == 0 {
   932  			break
   933  		}
   934  		if e.Children {
   935  			r.SkipChildren()
   936  		}
   937  	}
   938  }
   939  
   940  // clone returns a copy of the reader. This is used by the typeReader
   941  // interface.
   942  func (r *Reader) clone() typeReader {
   943  	return r.d.Reader()
   944  }
   945  
   946  // offset returns the current buffer offset. This is used by the
   947  // typeReader interface.
   948  func (r *Reader) offset() Offset {
   949  	return r.b.off
   950  }
   951  
   952  // SeekPC returns the Entry for the compilation unit that includes pc,
   953  // and positions the reader to read the children of that unit.  If pc
   954  // is not covered by any unit, SeekPC returns ErrUnknownPC and the
   955  // position of the reader is undefined.
   956  //
   957  // Because compilation units can describe multiple regions of the
   958  // executable, in the worst case SeekPC must search through all the
   959  // ranges in all the compilation units. Each call to SeekPC starts the
   960  // search at the compilation unit of the last call, so in general
   961  // looking up a series of PCs will be faster if they are sorted. If
   962  // the caller wishes to do repeated fast PC lookups, it should build
   963  // an appropriate index using the Ranges method.
   964  func (r *Reader) SeekPC(pc uint64) (*Entry, error) {
   965  	unit := r.unit
   966  	for i := 0; i < len(r.d.unit); i++ {
   967  		if unit >= len(r.d.unit) {
   968  			unit = 0
   969  		}
   970  		r.err = nil
   971  		r.lastChildren = false
   972  		r.unit = unit
   973  		r.cu = nil
   974  		u := &r.d.unit[unit]
   975  		r.b = makeBuf(r.d, u, "info", u.off, u.data)
   976  		e, err := r.Next()
   977  		if err != nil || e == nil || e.Tag == 0 {
   978  			return nil, err
   979  		}
   980  		ranges, err := r.d.Ranges(e)
   981  		if err != nil {
   982  			return nil, err
   983  		}
   984  		for _, pcs := range ranges {
   985  			if pcs[0] <= pc && pc < pcs[1] {
   986  				return e, nil
   987  			}
   988  		}
   989  		unit++
   990  	}
   991  	return nil, ErrUnknownPC
   992  }
   993  
   994  // Ranges returns the PC ranges covered by e, a slice of [low,high) pairs.
   995  // Only some entry types, such as TagCompileUnit or TagSubprogram, have PC
   996  // ranges; for others, this will return nil with no error.
   997  func (d *Data) Ranges(e *Entry) ([][2]uint64, error) {
   998  	var ret [][2]uint64
   999  
  1000  	low, lowOK := e.Val(AttrLowpc).(uint64)
  1001  
  1002  	var high uint64
  1003  	var highOK bool
  1004  	highField := e.AttrField(AttrHighpc)
  1005  	if highField != nil {
  1006  		switch highField.Class {
  1007  		case ClassAddress:
  1008  			high, highOK = highField.Val.(uint64)
  1009  		case ClassConstant:
  1010  			off, ok := highField.Val.(int64)
  1011  			if ok {
  1012  				high = low + uint64(off)
  1013  				highOK = true
  1014  			}
  1015  		}
  1016  	}
  1017  
  1018  	if lowOK && highOK {
  1019  		ret = append(ret, [2]uint64{low, high})
  1020  	}
  1021  
  1022  	var u *unit
  1023  	if uidx := d.offsetToUnit(e.Offset); uidx >= 0 && uidx < len(d.unit) {
  1024  		u = &d.unit[uidx]
  1025  	}
  1026  
  1027  	if u != nil && u.vers >= 5 && d.rngLists != nil {
  1028  		// DWARF version 5 and later
  1029  		field := e.AttrField(AttrRanges)
  1030  		if field == nil {
  1031  			return ret, nil
  1032  		}
  1033  		switch field.Class {
  1034  		case ClassRangeListPtr:
  1035  			ranges, rangesOK := field.Val.(int64)
  1036  			if !rangesOK {
  1037  				return ret, nil
  1038  			}
  1039  			cu, base, err := d.baseAddressForEntry(e)
  1040  			if err != nil {
  1041  				return nil, err
  1042  			}
  1043  			return d.dwarf5Ranges(u, cu, base, ranges, ret)
  1044  
  1045  		case ClassRngList:
  1046  			rnglist, ok := field.Val.(uint64)
  1047  			if !ok {
  1048  				return ret, nil
  1049  			}
  1050  			cu, base, err := d.baseAddressForEntry(e)
  1051  			if err != nil {
  1052  				return nil, err
  1053  			}
  1054  			return d.dwarf5Ranges(u, cu, base, int64(rnglist), ret)
  1055  
  1056  		default:
  1057  			return ret, nil
  1058  		}
  1059  	}
  1060  
  1061  	// DWARF version 2 through 4
  1062  	ranges, rangesOK := e.Val(AttrRanges).(int64)
  1063  	if rangesOK && d.ranges != nil {
  1064  		_, base, err := d.baseAddressForEntry(e)
  1065  		if err != nil {
  1066  			return nil, err
  1067  		}
  1068  		return d.dwarf2Ranges(u, base, ranges, ret)
  1069  	}
  1070  
  1071  	return ret, nil
  1072  }
  1073  
  1074  // baseAddressForEntry returns the initial base address to be used when
  1075  // looking up the range list of entry e.
  1076  // DWARF specifies that this should be the lowpc attribute of the enclosing
  1077  // compilation unit, however comments in gdb/dwarf2read.c say that some
  1078  // versions of GCC use the entrypc attribute, so we check that too.
  1079  func (d *Data) baseAddressForEntry(e *Entry) (*Entry, uint64, error) {
  1080  	var cu *Entry
  1081  	if e.Tag == TagCompileUnit {
  1082  		cu = e
  1083  	} else {
  1084  		i := d.offsetToUnit(e.Offset)
  1085  		if i == -1 {
  1086  			return nil, 0, errors.New("no unit for entry")
  1087  		}
  1088  		u := &d.unit[i]
  1089  		b := makeBuf(d, u, "info", u.off, u.data)
  1090  		cu = b.entry(nil, u.atable, u.base, u.vers)
  1091  		if b.err != nil {
  1092  			return nil, 0, b.err
  1093  		}
  1094  	}
  1095  
  1096  	if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK {
  1097  		return cu, cuEntry, nil
  1098  	} else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK {
  1099  		return cu, cuLow, nil
  1100  	}
  1101  
  1102  	return cu, 0, nil
  1103  }
  1104  
  1105  func (d *Data) dwarf2Ranges(u *unit, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
  1106  	buf := makeBuf(d, u, "ranges", Offset(ranges), d.ranges[ranges:])
  1107  	for len(buf.data) > 0 {
  1108  		low := buf.addr()
  1109  		high := buf.addr()
  1110  
  1111  		if low == 0 && high == 0 {
  1112  			break
  1113  		}
  1114  
  1115  		if low == ^uint64(0)>>uint((8-u.addrsize())*8) {
  1116  			base = high
  1117  		} else {
  1118  			ret = append(ret, [2]uint64{base + low, base + high})
  1119  		}
  1120  	}
  1121  
  1122  	return ret, nil
  1123  }
  1124  
  1125  // dwarf5Ranges interprets a debug_rnglists sequence, see DWARFv5 section
  1126  // 2.17.3 (page 53).
  1127  func (d *Data) dwarf5Ranges(u *unit, cu *Entry, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
  1128  	var addrBase int64
  1129  	if cu != nil {
  1130  		addrBase, _ = cu.Val(AttrAddrBase).(int64)
  1131  	}
  1132  
  1133  	buf := makeBuf(d, u, "rnglists", 0, d.rngLists)
  1134  	buf.skip(int(ranges))
  1135  	for {
  1136  		opcode := buf.uint8()
  1137  		switch opcode {
  1138  		case rleEndOfList:
  1139  			if buf.err != nil {
  1140  				return nil, buf.err
  1141  			}
  1142  			return ret, nil
  1143  
  1144  		case rleBaseAddressx:
  1145  			baseIdx := buf.uint()
  1146  			var err error
  1147  			base, err = d.debugAddr(u, uint64(addrBase), baseIdx)
  1148  			if err != nil {
  1149  				return nil, err
  1150  			}
  1151  
  1152  		case rleStartxEndx:
  1153  			startIdx := buf.uint()
  1154  			endIdx := buf.uint()
  1155  
  1156  			start, err := d.debugAddr(u, uint64(addrBase), startIdx)
  1157  			if err != nil {
  1158  				return nil, err
  1159  			}
  1160  			end, err := d.debugAddr(u, uint64(addrBase), endIdx)
  1161  			if err != nil {
  1162  				return nil, err
  1163  			}
  1164  			ret = append(ret, [2]uint64{start, end})
  1165  
  1166  		case rleStartxLength:
  1167  			startIdx := buf.uint()
  1168  			len := buf.uint()
  1169  			start, err := d.debugAddr(u, uint64(addrBase), startIdx)
  1170  			if err != nil {
  1171  				return nil, err
  1172  			}
  1173  			ret = append(ret, [2]uint64{start, start + len})
  1174  
  1175  		case rleOffsetPair:
  1176  			off1 := buf.uint()
  1177  			off2 := buf.uint()
  1178  			ret = append(ret, [2]uint64{base + off1, base + off2})
  1179  
  1180  		case rleBaseAddress:
  1181  			base = buf.addr()
  1182  
  1183  		case rleStartEnd:
  1184  			start := buf.addr()
  1185  			end := buf.addr()
  1186  			ret = append(ret, [2]uint64{start, end})
  1187  
  1188  		case rleStartLength:
  1189  			start := buf.addr()
  1190  			len := buf.uint()
  1191  			ret = append(ret, [2]uint64{start, start + len})
  1192  		}
  1193  	}
  1194  }
  1195  
  1196  // debugAddr returns the address at idx in debug_addr
  1197  func (d *Data) debugAddr(format dataFormat, addrBase, idx uint64) (uint64, error) {
  1198  	off := idx*uint64(format.addrsize()) + addrBase
  1199  
  1200  	if uint64(int(off)) != off {
  1201  		return 0, errors.New("offset out of range")
  1202  	}
  1203  
  1204  	b := makeBuf(d, format, "addr", 0, d.addr)
  1205  	b.skip(int(off))
  1206  	val := b.addr()
  1207  	if b.err != nil {
  1208  		return 0, b.err
  1209  	}
  1210  	return val, nil
  1211  }
  1212  

View as plain text