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