github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/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  }
    29  
    30  // a map from entry format ids to their descriptions
    31  type abbrevTable map[uint32]abbrev
    32  
    33  // ParseAbbrev returns the abbreviation table that starts at byte off
    34  // in the .debug_abbrev section.
    35  func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) {
    36  	if m, ok := d.abbrevCache[off]; ok {
    37  		return m, nil
    38  	}
    39  
    40  	data := d.abbrev
    41  	if off > uint32(len(data)) {
    42  		data = nil
    43  	} else {
    44  		data = data[off:]
    45  	}
    46  	b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
    47  
    48  	// Error handling is simplified by the buf getters
    49  	// returning an endless stream of 0s after an error.
    50  	m := make(abbrevTable)
    51  	for {
    52  		// Table ends with id == 0.
    53  		id := uint32(b.uint())
    54  		if id == 0 {
    55  			break
    56  		}
    57  
    58  		// Walk over attributes, counting.
    59  		n := 0
    60  		b1 := b // Read from copy of b.
    61  		b1.uint()
    62  		b1.uint8()
    63  		for {
    64  			tag := b1.uint()
    65  			fmt := b1.uint()
    66  			if tag == 0 && fmt == 0 {
    67  				break
    68  			}
    69  			n++
    70  		}
    71  		if b1.err != nil {
    72  			return nil, b1.err
    73  		}
    74  
    75  		// Walk over attributes again, this time writing them down.
    76  		var a abbrev
    77  		a.tag = Tag(b.uint())
    78  		a.children = b.uint8() != 0
    79  		a.field = make([]afield, n)
    80  		for i := range a.field {
    81  			a.field[i].attr = Attr(b.uint())
    82  			a.field[i].fmt = format(b.uint())
    83  		}
    84  		b.uint()
    85  		b.uint()
    86  
    87  		m[id] = a
    88  	}
    89  	if b.err != nil {
    90  		return nil, b.err
    91  	}
    92  	d.abbrevCache[off] = m
    93  	return m, nil
    94  }
    95  
    96  // An entry is a sequence of attribute/value pairs.
    97  type Entry struct {
    98  	Offset   Offset // offset of Entry in DWARF info
    99  	Tag      Tag    // tag (kind of Entry)
   100  	Children bool   // whether Entry is followed by children
   101  	Field    []Field
   102  }
   103  
   104  // A Field is a single attribute/value pair in an Entry.
   105  type Field struct {
   106  	Attr Attr
   107  	Val  interface{}
   108  }
   109  
   110  // Val returns the value associated with attribute Attr in Entry,
   111  // or nil if there is no such attribute.
   112  //
   113  // A common idiom is to merge the check for nil return with
   114  // the check that the value has the expected dynamic type, as in:
   115  //	v, ok := e.Val(AttrSibling).(int64);
   116  //
   117  func (e *Entry) Val(a Attr) interface{} {
   118  	for _, f := range e.Field {
   119  		if f.Attr == a {
   120  			return f.Val
   121  		}
   122  	}
   123  	return nil
   124  }
   125  
   126  // An Offset represents the location of an Entry within the DWARF info.
   127  // (See Reader.Seek.)
   128  type Offset uint32
   129  
   130  // Entry reads a single entry from buf, decoding
   131  // according to the given abbreviation table.
   132  func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
   133  	off := b.off
   134  	id := uint32(b.uint())
   135  	if id == 0 {
   136  		return &Entry{}
   137  	}
   138  	a, ok := atab[id]
   139  	if !ok {
   140  		b.error("unknown abbreviation table index")
   141  		return nil
   142  	}
   143  	e := &Entry{
   144  		Offset:   off,
   145  		Tag:      a.tag,
   146  		Children: a.children,
   147  		Field:    make([]Field, len(a.field)),
   148  	}
   149  	for i := range e.Field {
   150  		e.Field[i].Attr = a.field[i].attr
   151  		fmt := a.field[i].fmt
   152  		if fmt == formIndirect {
   153  			fmt = format(b.uint())
   154  		}
   155  		var val interface{}
   156  		switch fmt {
   157  		default:
   158  			b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
   159  
   160  		// address
   161  		case formAddr:
   162  			val = b.addr()
   163  
   164  		// block
   165  		case formDwarfBlock1:
   166  			val = b.bytes(int(b.uint8()))
   167  		case formDwarfBlock2:
   168  			val = b.bytes(int(b.uint16()))
   169  		case formDwarfBlock4:
   170  			val = b.bytes(int(b.uint32()))
   171  		case formDwarfBlock:
   172  			val = b.bytes(int(b.uint()))
   173  
   174  		// constant
   175  		case formData1:
   176  			val = int64(b.uint8())
   177  		case formData2:
   178  			val = int64(b.uint16())
   179  		case formData4:
   180  			val = int64(b.uint32())
   181  		case formData8:
   182  			val = int64(b.uint64())
   183  		case formSdata:
   184  			val = int64(b.int())
   185  		case formUdata:
   186  			val = int64(b.uint())
   187  
   188  		// flag
   189  		case formFlag:
   190  			val = b.uint8() == 1
   191  		// New in DWARF 4.
   192  		case formFlagPresent:
   193  			// The attribute is implicitly indicated as present, and no value is
   194  			// encoded in the debugging information entry itself.
   195  			val = true
   196  
   197  		// reference to other entry
   198  		case formRefAddr:
   199  			vers := b.format.version()
   200  			if vers == 0 {
   201  				b.error("unknown version for DW_FORM_ref_addr")
   202  			} else if vers == 2 {
   203  				val = Offset(b.addr())
   204  			} else {
   205  				is64, known := b.format.dwarf64()
   206  				if !known {
   207  					b.error("unknown size for DW_FORM_ref_addr")
   208  				} else if is64 {
   209  					val = Offset(b.uint64())
   210  				} else {
   211  					val = Offset(b.uint32())
   212  				}
   213  			}
   214  		case formRef1:
   215  			val = Offset(b.uint8()) + ubase
   216  		case formRef2:
   217  			val = Offset(b.uint16()) + ubase
   218  		case formRef4:
   219  			val = Offset(b.uint32()) + ubase
   220  		case formRef8:
   221  			val = Offset(b.uint64()) + ubase
   222  		case formRefUdata:
   223  			val = Offset(b.uint()) + ubase
   224  
   225  		// string
   226  		case formString:
   227  			val = b.string()
   228  		case formStrp:
   229  			off := b.uint32() // offset into .debug_str
   230  			if b.err != nil {
   231  				return nil
   232  			}
   233  			b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str)
   234  			b1.skip(int(off))
   235  			val = b1.string()
   236  			if b1.err != nil {
   237  				b.err = b1.err
   238  				return nil
   239  			}
   240  
   241  		// lineptr, loclistptr, macptr, rangelistptr
   242  		// New in DWARF 4, but clang can generate them with -gdwarf-2.
   243  		// Section reference, replacing use of formData4 and formData8.
   244  		case formSecOffset:
   245  			is64, known := b.format.dwarf64()
   246  			if !known {
   247  				b.error("unknown size for DW_FORM_sec_offset")
   248  			} else if is64 {
   249  				val = int64(b.uint64())
   250  			} else {
   251  				val = int64(b.uint32())
   252  			}
   253  
   254  		// exprloc
   255  		// New in DWARF 4.
   256  		case formExprloc:
   257  			val = b.bytes(int(b.uint()))
   258  
   259  		// reference
   260  		// New in DWARF 4.
   261  		case formRefSig8:
   262  			// 64-bit type signature.
   263  			val = b.uint64()
   264  		}
   265  		e.Field[i].Val = val
   266  	}
   267  	if b.err != nil {
   268  		return nil
   269  	}
   270  	return e
   271  }
   272  
   273  // A Reader allows reading Entry structures from a DWARF ``info'' section.
   274  // The Entry structures are arranged in a tree.  The Reader's Next function
   275  // return successive entries from a pre-order traversal of the tree.
   276  // If an entry has children, its Children field will be true, and the children
   277  // follow, terminated by an Entry with Tag 0.
   278  type Reader struct {
   279  	b            buf
   280  	d            *Data
   281  	err          error
   282  	unit         int
   283  	lastChildren bool   // .Children of last entry returned by Next
   284  	lastSibling  Offset // .Val(AttrSibling) of last entry returned by Next
   285  }
   286  
   287  // Reader returns a new Reader for Data.
   288  // The reader is positioned at byte offset 0 in the DWARF ``info'' section.
   289  func (d *Data) Reader() *Reader {
   290  	r := &Reader{d: d}
   291  	r.Seek(0)
   292  	return r
   293  }
   294  
   295  // Seek positions the Reader at offset off in the encoded entry stream.
   296  // Offset 0 can be used to denote the first entry.
   297  func (r *Reader) Seek(off Offset) {
   298  	d := r.d
   299  	r.err = nil
   300  	r.lastChildren = false
   301  	if off == 0 {
   302  		if len(d.unit) == 0 {
   303  			return
   304  		}
   305  		u := &d.unit[0]
   306  		r.unit = 0
   307  		r.b = makeBuf(r.d, u, "info", u.off, u.data)
   308  		return
   309  	}
   310  
   311  	// TODO(rsc): binary search (maybe a new package)
   312  	var i int
   313  	var u *unit
   314  	for i = range d.unit {
   315  		u = &d.unit[i]
   316  		if u.off <= off && off < u.off+Offset(len(u.data)) {
   317  			r.unit = i
   318  			r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
   319  			return
   320  		}
   321  	}
   322  	r.err = errors.New("offset out of range")
   323  }
   324  
   325  // maybeNextUnit advances to the next unit if this one is finished.
   326  func (r *Reader) maybeNextUnit() {
   327  	for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
   328  		r.unit++
   329  		u := &r.d.unit[r.unit]
   330  		r.b = makeBuf(r.d, u, "info", u.off, u.data)
   331  	}
   332  }
   333  
   334  // Next reads the next entry from the encoded entry stream.
   335  // It returns nil, nil when it reaches the end of the section.
   336  // It returns an error if the current offset is invalid or the data at the
   337  // offset cannot be decoded as a valid Entry.
   338  func (r *Reader) Next() (*Entry, error) {
   339  	if r.err != nil {
   340  		return nil, r.err
   341  	}
   342  	r.maybeNextUnit()
   343  	if len(r.b.data) == 0 {
   344  		return nil, nil
   345  	}
   346  	u := &r.d.unit[r.unit]
   347  	e := r.b.entry(u.atable, u.base)
   348  	if r.b.err != nil {
   349  		r.err = r.b.err
   350  		return nil, r.err
   351  	}
   352  	if e != nil {
   353  		r.lastChildren = e.Children
   354  		if r.lastChildren {
   355  			r.lastSibling, _ = e.Val(AttrSibling).(Offset)
   356  		}
   357  	} else {
   358  		r.lastChildren = false
   359  	}
   360  	return e, nil
   361  }
   362  
   363  // SkipChildren skips over the child entries associated with
   364  // the last Entry returned by Next.  If that Entry did not have
   365  // children or Next has not been called, SkipChildren is a no-op.
   366  func (r *Reader) SkipChildren() {
   367  	if r.err != nil || !r.lastChildren {
   368  		return
   369  	}
   370  
   371  	// If the last entry had a sibling attribute,
   372  	// that attribute gives the offset of the next
   373  	// sibling, so we can avoid decoding the
   374  	// child subtrees.
   375  	if r.lastSibling >= r.b.off {
   376  		r.Seek(r.lastSibling)
   377  		return
   378  	}
   379  
   380  	for {
   381  		e, err := r.Next()
   382  		if err != nil || e == nil || e.Tag == 0 {
   383  			break
   384  		}
   385  		if e.Children {
   386  			r.SkipChildren()
   387  		}
   388  	}
   389  }