github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/src/debug/dwarf/entry.go (about)

     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  	"errors"
    15  	"strconv"
    16  )
    17  
    18  // a single entry's description: a sequence of attributes
    19  type abbrev struct {
    20  	tag      Tag
    21  	children bool
    22  	field    []afield
    23  }
    24  
    25  type afield struct {
    26  	attr  Attr
    27  	fmt   format
    28  	class Class
    29  }
    30  
    31  // a map from entry format ids to their descriptions
    32  type abbrevTable map[uint32]abbrev
    33  
    34  // ParseAbbrev returns the abbreviation table that starts at byte off
    35  // in the .debug_abbrev section.
    36  func (d *Data) parseAbbrev(off uint32, vers int) (abbrevTable, error) {
    37  	if m, ok := d.abbrevCache[off]; ok {
    38  		return m, nil
    39  	}
    40  
    41  	data := d.abbrev
    42  	if off > uint32(len(data)) {
    43  		data = nil
    44  	} else {
    45  		data = data[off:]
    46  	}
    47  	b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
    48  
    49  	// Error handling is simplified by the buf getters
    50  	// returning an endless stream of 0s after an error.
    51  	m := make(abbrevTable)
    52  	for {
    53  		// Table ends with id == 0.
    54  		id := uint32(b.uint())
    55  		if id == 0 {
    56  			break
    57  		}
    58  
    59  		// Walk over attributes, counting.
    60  		n := 0
    61  		b1 := b // Read from copy of b.
    62  		b1.uint()
    63  		b1.uint8()
    64  		for {
    65  			tag := b1.uint()
    66  			fmt := b1.uint()
    67  			if tag == 0 && fmt == 0 {
    68  				break
    69  			}
    70  			n++
    71  		}
    72  		if b1.err != nil {
    73  			return nil, b1.err
    74  		}
    75  
    76  		// Walk over attributes again, this time writing them down.
    77  		var a abbrev
    78  		a.tag = Tag(b.uint())
    79  		a.children = b.uint8() != 0
    80  		a.field = make([]afield, n)
    81  		for i := range a.field {
    82  			a.field[i].attr = Attr(b.uint())
    83  			a.field[i].fmt = format(b.uint())
    84  			a.field[i].class = formToClass(a.field[i].fmt, a.field[i].attr, vers, &b)
    85  		}
    86  		b.uint()
    87  		b.uint()
    88  
    89  		m[id] = a
    90  	}
    91  	if b.err != nil {
    92  		return nil, b.err
    93  	}
    94  	d.abbrevCache[off] = m
    95  	return m, nil
    96  }
    97  
    98  // attrIsExprloc indicates attributes that allow exprloc values that
    99  // are encoded as block values in DWARF 2 and 3. See DWARF 4, Figure
   100  // 20.
   101  var attrIsExprloc = map[Attr]bool{
   102  	AttrLocation:      true,
   103  	AttrByteSize:      true,
   104  	AttrBitOffset:     true,
   105  	AttrBitSize:       true,
   106  	AttrStringLength:  true,
   107  	AttrLowerBound:    true,
   108  	AttrReturnAddr:    true,
   109  	AttrStrideSize:    true,
   110  	AttrUpperBound:    true,
   111  	AttrCount:         true,
   112  	AttrDataMemberLoc: true,
   113  	AttrFrameBase:     true,
   114  	AttrSegment:       true,
   115  	AttrStaticLink:    true,
   116  	AttrUseLocation:   true,
   117  	AttrVtableElemLoc: true,
   118  	AttrAllocated:     true,
   119  	AttrAssociated:    true,
   120  	AttrDataLocation:  true,
   121  	AttrStride:        true,
   122  }
   123  
   124  // attrPtrClass indicates the *ptr class of attributes that have
   125  // encoding formSecOffset in DWARF 4 or formData* in DWARF 2 and 3.
   126  var attrPtrClass = map[Attr]Class{
   127  	AttrLocation:      ClassLocListPtr,
   128  	AttrStmtList:      ClassLinePtr,
   129  	AttrStringLength:  ClassLocListPtr,
   130  	AttrReturnAddr:    ClassLocListPtr,
   131  	AttrStartScope:    ClassRangeListPtr,
   132  	AttrDataMemberLoc: ClassLocListPtr,
   133  	AttrFrameBase:     ClassLocListPtr,
   134  	AttrMacroInfo:     ClassMacPtr,
   135  	AttrSegment:       ClassLocListPtr,
   136  	AttrStaticLink:    ClassLocListPtr,
   137  	AttrUseLocation:   ClassLocListPtr,
   138  	AttrVtableElemLoc: ClassLocListPtr,
   139  	AttrRanges:        ClassRangeListPtr,
   140  }
   141  
   142  // formToClass returns the DWARF 4 Class for the given form. If the
   143  // DWARF version is less then 4, it will disambiguate some forms
   144  // depending on the attribute.
   145  func formToClass(form format, attr Attr, vers int, b *buf) Class {
   146  	switch form {
   147  	default:
   148  		b.error("cannot determine class of unknown attribute form")
   149  		return 0
   150  
   151  	case formAddr:
   152  		return ClassAddress
   153  
   154  	case formDwarfBlock1, formDwarfBlock2, formDwarfBlock4, formDwarfBlock:
   155  		// In DWARF 2 and 3, ClassExprLoc was encoded as a
   156  		// block. DWARF 4 distinguishes ClassBlock and
   157  		// ClassExprLoc, but there are no attributes that can
   158  		// be both, so we also promote ClassBlock values in
   159  		// DWARF 4 that should be ClassExprLoc in case
   160  		// producers get this wrong.
   161  		if attrIsExprloc[attr] {
   162  			return ClassExprLoc
   163  		}
   164  		return ClassBlock
   165  
   166  	case formData1, formData2, formData4, formData8, formSdata, formUdata:
   167  		// In DWARF 2 and 3, ClassPtr was encoded as a
   168  		// constant. Unlike ClassExprLoc/ClassBlock, some
   169  		// DWARF 4 attributes need to distinguish Class*Ptr
   170  		// from ClassConstant, so we only do this promotion
   171  		// for versions 2 and 3.
   172  		if class, ok := attrPtrClass[attr]; vers < 4 && ok {
   173  			return class
   174  		}
   175  		return ClassConstant
   176  
   177  	case formFlag, formFlagPresent:
   178  		return ClassFlag
   179  
   180  	case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata:
   181  		return ClassReference
   182  
   183  	case formRefSig8:
   184  		return ClassReferenceSig
   185  
   186  	case formString, formStrp:
   187  		return ClassString
   188  
   189  	case formSecOffset:
   190  		// DWARF 4 defines four *ptr classes, but doesn't
   191  		// distinguish them in the encoding. Disambiguate
   192  		// these classes using the attribute.
   193  		if class, ok := attrPtrClass[attr]; ok {
   194  			return class
   195  		}
   196  		b.error("cannot determine class of unknown attribute with formSecOffset")
   197  		return 0
   198  
   199  	case formExprloc:
   200  		return ClassExprLoc
   201  
   202  	case formGnuRefAlt:
   203  		return ClassReferenceAlt
   204  
   205  	case formGnuStrpAlt:
   206  		return ClassStringAlt
   207  	}
   208  }
   209  
   210  // An entry is a sequence of attribute/value pairs.
   211  type Entry struct {
   212  	Offset   Offset // offset of Entry in DWARF info
   213  	Tag      Tag    // tag (kind of Entry)
   214  	Children bool   // whether Entry is followed by children
   215  	Field    []Field
   216  }
   217  
   218  // A Field is a single attribute/value pair in an Entry.
   219  //
   220  // A value can be one of several "attribute classes" defined by DWARF.
   221  // The Go types corresponding to each class are:
   222  //
   223  //    DWARF class       Go type        Class
   224  //    -----------       -------        -----
   225  //    address           uint64         ClassAddress
   226  //    block             []byte         ClassBlock
   227  //    constant          int64          ClassConstant
   228  //    flag              bool           ClassFlag
   229  //    reference
   230  //      to info         dwarf.Offset   ClassReference
   231  //      to type unit    uint64         ClassReferenceSig
   232  //    string            string         ClassString
   233  //    exprloc           []byte         ClassExprLoc
   234  //    lineptr           int64          ClassLinePtr
   235  //    loclistptr        int64          ClassLocListPtr
   236  //    macptr            int64          ClassMacPtr
   237  //    rangelistptr      int64          ClassRangeListPtr
   238  type Field struct {
   239  	Attr  Attr
   240  	Val   interface{}
   241  	Class Class
   242  }
   243  
   244  // A Class is the DWARF 4 class of an attibute value.
   245  //
   246  // In general, a given attribute's value may take on one of several
   247  // possible classes defined by DWARF, each of which leads to a
   248  // slightly different interpretation of the attribute.
   249  //
   250  // DWARF version 4 distinguishes attribute value classes more finely
   251  // than previous versions of DWARF. The reader will disambiguate
   252  // coarser classes from earlier versions of DWARF into the appropriate
   253  // DWARF 4 class. For example, DWARF 2 uses "constant" for constants
   254  // as well as all types of section offsets, but the reader will
   255  // canonicalize attributes in DWARF 2 files that refer to section
   256  // offsets to one of the Class*Ptr classes, even though these classes
   257  // were only defined in DWARF 3.
   258  type Class int
   259  
   260  const (
   261  	// ClassAddress represents values of type uint64 that are
   262  	// addresses on the target machine.
   263  	ClassAddress Class = 1 + iota
   264  
   265  	// ClassBlock represents values of type []byte whose
   266  	// interpretation depends on the attribute.
   267  	ClassBlock
   268  
   269  	// ClassConstant represents values of type int64 that are
   270  	// constants. The interpretation of this constant depends on
   271  	// the attribute.
   272  	ClassConstant
   273  
   274  	// ClassExprLoc represents values of type []byte that contain
   275  	// an encoded DWARF expression or location description.
   276  	ClassExprLoc
   277  
   278  	// ClassFlag represents values of type bool.
   279  	ClassFlag
   280  
   281  	// ClassLinePtr represents values that are an int64 offset
   282  	// into the "line" section.
   283  	ClassLinePtr
   284  
   285  	// ClassLocListPtr represents values that are an int64 offset
   286  	// into the "loclist" section.
   287  	ClassLocListPtr
   288  
   289  	// ClassMacPtr represents values that are an int64 offset into
   290  	// the "mac" section.
   291  	ClassMacPtr
   292  
   293  	// ClassMacPtr represents values that are an int64 offset into
   294  	// the "rangelist" section.
   295  	ClassRangeListPtr
   296  
   297  	// ClassReference represents values that are an Offset offset
   298  	// of an Entry in the info section (for use with Reader.Seek).
   299  	// The DWARF specification combines ClassReference and
   300  	// ClassReferenceSig into class "reference".
   301  	ClassReference
   302  
   303  	// ClassReferenceSig represents values that are a uint64 type
   304  	// signature referencing a type Entry.
   305  	ClassReferenceSig
   306  
   307  	// ClassString represents values that are strings. If the
   308  	// compilation unit specifies the AttrUseUTF8 flag (strongly
   309  	// recommended), the string value will be encoded in UTF-8.
   310  	// Otherwise, the encoding is unspecified.
   311  	ClassString
   312  
   313  	// ClassReferenceAlt represents values of type int64 that are
   314  	// an offset into the DWARF "info" section of an alternate
   315  	// object file.
   316  	ClassReferenceAlt
   317  
   318  	// ClassStringAlt represents values of type int64 that are an
   319  	// offset into the DWARF string section of an alternate object
   320  	// file.
   321  	ClassStringAlt
   322  )
   323  
   324  //go:generate stringer -type=Class
   325  
   326  func (i Class) GoString() string {
   327  	return "dwarf." + i.String()
   328  }
   329  
   330  // Val returns the value associated with attribute Attr in Entry,
   331  // or nil if there is no such attribute.
   332  //
   333  // A common idiom is to merge the check for nil return with
   334  // the check that the value has the expected dynamic type, as in:
   335  //	v, ok := e.Val(AttrSibling).(int64)
   336  //
   337  func (e *Entry) Val(a Attr) interface{} {
   338  	if f := e.AttrField(a); f != nil {
   339  		return f.Val
   340  	}
   341  	return nil
   342  }
   343  
   344  // AttrField returns the Field associated with attribute Attr in
   345  // Entry, or nil if there is no such attribute.
   346  func (e *Entry) AttrField(a Attr) *Field {
   347  	for i, f := range e.Field {
   348  		if f.Attr == a {
   349  			return &e.Field[i]
   350  		}
   351  	}
   352  	return nil
   353  }
   354  
   355  // An Offset represents the location of an Entry within the DWARF info.
   356  // (See Reader.Seek.)
   357  type Offset uint32
   358  
   359  // Entry reads a single entry from buf, decoding
   360  // according to the given abbreviation table.
   361  func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
   362  	off := b.off
   363  	id := uint32(b.uint())
   364  	if id == 0 {
   365  		return &Entry{}
   366  	}
   367  	a, ok := atab[id]
   368  	if !ok {
   369  		b.error("unknown abbreviation table index")
   370  		return nil
   371  	}
   372  	e := &Entry{
   373  		Offset:   off,
   374  		Tag:      a.tag,
   375  		Children: a.children,
   376  		Field:    make([]Field, len(a.field)),
   377  	}
   378  	for i := range e.Field {
   379  		e.Field[i].Attr = a.field[i].attr
   380  		e.Field[i].Class = a.field[i].class
   381  		fmt := a.field[i].fmt
   382  		if fmt == formIndirect {
   383  			fmt = format(b.uint())
   384  		}
   385  		var val interface{}
   386  		switch fmt {
   387  		default:
   388  			b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
   389  
   390  		// address
   391  		case formAddr:
   392  			val = b.addr()
   393  
   394  		// block
   395  		case formDwarfBlock1:
   396  			val = b.bytes(int(b.uint8()))
   397  		case formDwarfBlock2:
   398  			val = b.bytes(int(b.uint16()))
   399  		case formDwarfBlock4:
   400  			val = b.bytes(int(b.uint32()))
   401  		case formDwarfBlock:
   402  			val = b.bytes(int(b.uint()))
   403  
   404  		// constant
   405  		case formData1:
   406  			val = int64(b.uint8())
   407  		case formData2:
   408  			val = int64(b.uint16())
   409  		case formData4:
   410  			val = int64(b.uint32())
   411  		case formData8:
   412  			val = int64(b.uint64())
   413  		case formSdata:
   414  			val = int64(b.int())
   415  		case formUdata:
   416  			val = int64(b.uint())
   417  
   418  		// flag
   419  		case formFlag:
   420  			val = b.uint8() == 1
   421  		// New in DWARF 4.
   422  		case formFlagPresent:
   423  			// The attribute is implicitly indicated as present, and no value is
   424  			// encoded in the debugging information entry itself.
   425  			val = true
   426  
   427  		// reference to other entry
   428  		case formRefAddr:
   429  			vers := b.format.version()
   430  			if vers == 0 {
   431  				b.error("unknown version for DW_FORM_ref_addr")
   432  			} else if vers == 2 {
   433  				val = Offset(b.addr())
   434  			} else {
   435  				is64, known := b.format.dwarf64()
   436  				if !known {
   437  					b.error("unknown size for DW_FORM_ref_addr")
   438  				} else if is64 {
   439  					val = Offset(b.uint64())
   440  				} else {
   441  					val = Offset(b.uint32())
   442  				}
   443  			}
   444  		case formRef1:
   445  			val = Offset(b.uint8()) + ubase
   446  		case formRef2:
   447  			val = Offset(b.uint16()) + ubase
   448  		case formRef4:
   449  			val = Offset(b.uint32()) + ubase
   450  		case formRef8:
   451  			val = Offset(b.uint64()) + ubase
   452  		case formRefUdata:
   453  			val = Offset(b.uint()) + ubase
   454  
   455  		// string
   456  		case formString:
   457  			val = b.string()
   458  		case formStrp:
   459  			off := b.uint32() // offset into .debug_str
   460  			if b.err != nil {
   461  				return nil
   462  			}
   463  			b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str)
   464  			b1.skip(int(off))
   465  			val = b1.string()
   466  			if b1.err != nil {
   467  				b.err = b1.err
   468  				return nil
   469  			}
   470  
   471  		// lineptr, loclistptr, macptr, rangelistptr
   472  		// New in DWARF 4, but clang can generate them with -gdwarf-2.
   473  		// Section reference, replacing use of formData4 and formData8.
   474  		case formSecOffset, formGnuRefAlt, formGnuStrpAlt:
   475  			is64, known := b.format.dwarf64()
   476  			if !known {
   477  				b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
   478  			} else if is64 {
   479  				val = int64(b.uint64())
   480  			} else {
   481  				val = int64(b.uint32())
   482  			}
   483  
   484  		// exprloc
   485  		// New in DWARF 4.
   486  		case formExprloc:
   487  			val = b.bytes(int(b.uint()))
   488  
   489  		// reference
   490  		// New in DWARF 4.
   491  		case formRefSig8:
   492  			// 64-bit type signature.
   493  			val = b.uint64()
   494  		}
   495  		e.Field[i].Val = val
   496  	}
   497  	if b.err != nil {
   498  		return nil
   499  	}
   500  	return e
   501  }
   502  
   503  // A Reader allows reading Entry structures from a DWARF ``info'' section.
   504  // The Entry structures are arranged in a tree.  The Reader's Next function
   505  // return successive entries from a pre-order traversal of the tree.
   506  // If an entry has children, its Children field will be true, and the children
   507  // follow, terminated by an Entry with Tag 0.
   508  type Reader struct {
   509  	b            buf
   510  	d            *Data
   511  	err          error
   512  	unit         int
   513  	lastChildren bool   // .Children of last entry returned by Next
   514  	lastSibling  Offset // .Val(AttrSibling) of last entry returned by Next
   515  }
   516  
   517  // Reader returns a new Reader for Data.
   518  // The reader is positioned at byte offset 0 in the DWARF ``info'' section.
   519  func (d *Data) Reader() *Reader {
   520  	r := &Reader{d: d}
   521  	r.Seek(0)
   522  	return r
   523  }
   524  
   525  // AddressSize returns the size in bytes of addresses in the current compilation
   526  // unit.
   527  func (r *Reader) AddressSize() int {
   528  	return r.d.unit[r.unit].asize
   529  }
   530  
   531  // Seek positions the Reader at offset off in the encoded entry stream.
   532  // Offset 0 can be used to denote the first entry.
   533  func (r *Reader) Seek(off Offset) {
   534  	d := r.d
   535  	r.err = nil
   536  	r.lastChildren = false
   537  	if off == 0 {
   538  		if len(d.unit) == 0 {
   539  			return
   540  		}
   541  		u := &d.unit[0]
   542  		r.unit = 0
   543  		r.b = makeBuf(r.d, u, "info", u.off, u.data)
   544  		return
   545  	}
   546  
   547  	i := d.offsetToUnit(off)
   548  	if i == -1 {
   549  		r.err = errors.New("offset out of range")
   550  		return
   551  	}
   552  	u := &d.unit[i]
   553  	r.unit = i
   554  	r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
   555  }
   556  
   557  // maybeNextUnit advances to the next unit if this one is finished.
   558  func (r *Reader) maybeNextUnit() {
   559  	for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
   560  		r.unit++
   561  		u := &r.d.unit[r.unit]
   562  		r.b = makeBuf(r.d, u, "info", u.off, u.data)
   563  	}
   564  }
   565  
   566  // Next reads the next entry from the encoded entry stream.
   567  // It returns nil, nil when it reaches the end of the section.
   568  // It returns an error if the current offset is invalid or the data at the
   569  // offset cannot be decoded as a valid Entry.
   570  func (r *Reader) Next() (*Entry, error) {
   571  	if r.err != nil {
   572  		return nil, r.err
   573  	}
   574  	r.maybeNextUnit()
   575  	if len(r.b.data) == 0 {
   576  		return nil, nil
   577  	}
   578  	u := &r.d.unit[r.unit]
   579  	e := r.b.entry(u.atable, u.base)
   580  	if r.b.err != nil {
   581  		r.err = r.b.err
   582  		return nil, r.err
   583  	}
   584  	if e != nil {
   585  		r.lastChildren = e.Children
   586  		if r.lastChildren {
   587  			r.lastSibling, _ = e.Val(AttrSibling).(Offset)
   588  		}
   589  	} else {
   590  		r.lastChildren = false
   591  	}
   592  	return e, nil
   593  }
   594  
   595  // SkipChildren skips over the child entries associated with
   596  // the last Entry returned by Next.  If that Entry did not have
   597  // children or Next has not been called, SkipChildren is a no-op.
   598  func (r *Reader) SkipChildren() {
   599  	if r.err != nil || !r.lastChildren {
   600  		return
   601  	}
   602  
   603  	// If the last entry had a sibling attribute,
   604  	// that attribute gives the offset of the next
   605  	// sibling, so we can avoid decoding the
   606  	// child subtrees.
   607  	if r.lastSibling >= r.b.off {
   608  		r.Seek(r.lastSibling)
   609  		return
   610  	}
   611  
   612  	for {
   613  		e, err := r.Next()
   614  		if err != nil || e == nil || e.Tag == 0 {
   615  			break
   616  		}
   617  		if e.Children {
   618  			r.SkipChildren()
   619  		}
   620  	}
   621  }
   622  
   623  // clone returns a copy of the reader.  This is used by the typeReader
   624  // interface.
   625  func (r *Reader) clone() typeReader {
   626  	return r.d.Reader()
   627  }
   628  
   629  // offset returns the current buffer offset.  This is used by the
   630  // typeReader interface.
   631  func (r *Reader) offset() Offset {
   632  	return r.b.off
   633  }