src/pkg/debug/dwarf/entry.go - The Go Programming Language

Golang

Source file src/pkg/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 "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, "abbrev", 0, data, 0)
    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	
   189			// reference to other entry
   190			case formRefAddr:
   191				val = Offset(b.addr())
   192			case formRef1:
   193				val = Offset(b.uint8()) + ubase
   194			case formRef2:
   195				val = Offset(b.uint16()) + ubase
   196			case formRef4:
   197				val = Offset(b.uint32()) + ubase
   198			case formRef8:
   199				val = Offset(b.uint64()) + ubase
   200			case formRefUdata:
   201				val = Offset(b.uint()) + ubase
   202	
   203			// string
   204			case formString:
   205				val = b.string()
   206			case formStrp:
   207				off := b.uint32() // offset into .debug_str
   208				if b.err != nil {
   209					return nil
   210				}
   211				b1 := makeBuf(b.dwarf, "str", 0, b.dwarf.str, 0)
   212				b1.skip(int(off))
   213				val = b1.string()
   214				if b1.err != nil {
   215					b.err = b1.err
   216					return nil
   217				}
   218			}
   219			e.Field[i].Val = val
   220		}
   221		if b.err != nil {
   222			return nil
   223		}
   224		return e
   225	}
   226	
   227	// A Reader allows reading Entry structures from a DWARF ``info'' section.
   228	// The Entry structures are arranged in a tree.  The Reader's Next function
   229	// return successive entries from a pre-order traversal of the tree.
   230	// If an entry has children, its Children field will be true, and the children
   231	// follow, terminated by an Entry with Tag 0.
   232	type Reader struct {
   233		b            buf
   234		d            *Data
   235		err          error
   236		unit         int
   237		lastChildren bool   // .Children of last entry returned by Next
   238		lastSibling  Offset // .Val(AttrSibling) of last entry returned by Next
   239	}
   240	
   241	// Reader returns a new Reader for Data.
   242	// The reader is positioned at byte offset 0 in the DWARF ``info'' section.
   243	func (d *Data) Reader() *Reader {
   244		r := &Reader{d: d}
   245		r.Seek(0)
   246		return r
   247	}
   248	
   249	// Seek positions the Reader at offset off in the encoded entry stream.
   250	// Offset 0 can be used to denote the first entry.
   251	func (r *Reader) Seek(off Offset) {
   252		d := r.d
   253		r.err = nil
   254		r.lastChildren = false
   255		if off == 0 {
   256			if len(d.unit) == 0 {
   257				return
   258			}
   259			u := &d.unit[0]
   260			r.unit = 0
   261			r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize)
   262			return
   263		}
   264	
   265		// TODO(rsc): binary search (maybe a new package)
   266		var i int
   267		var u *unit
   268		for i = range d.unit {
   269			u = &d.unit[i]
   270			if u.off <= off && off < u.off+Offset(len(u.data)) {
   271				r.unit = i
   272				r.b = makeBuf(r.d, "info", off, u.data[off-u.off:], u.addrsize)
   273				return
   274			}
   275		}
   276		r.err = errors.New("offset out of range")
   277	}
   278	
   279	// maybeNextUnit advances to the next unit if this one is finished.
   280	func (r *Reader) maybeNextUnit() {
   281		for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
   282			r.unit++
   283			u := &r.d.unit[r.unit]
   284			r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize)
   285		}
   286	}
   287	
   288	// Next reads the next entry from the encoded entry stream.
   289	// It returns nil, nil when it reaches the end of the section.
   290	// It returns an error if the current offset is invalid or the data at the
   291	// offset cannot be decoded as a valid Entry.
   292	func (r *Reader) Next() (*Entry, error) {
   293		if r.err != nil {
   294			return nil, r.err
   295		}
   296		r.maybeNextUnit()
   297		if len(r.b.data) == 0 {
   298			return nil, nil
   299		}
   300		u := &r.d.unit[r.unit]
   301		e := r.b.entry(u.atable, u.base)
   302		if r.b.err != nil {
   303			r.err = r.b.err
   304			return nil, r.err
   305		}
   306		if e != nil {
   307			r.lastChildren = e.Children
   308			if r.lastChildren {
   309				r.lastSibling, _ = e.Val(AttrSibling).(Offset)
   310			}
   311		} else {
   312			r.lastChildren = false
   313		}
   314		return e, nil
   315	}
   316	
   317	// SkipChildren skips over the child entries associated with
   318	// the last Entry returned by Next.  If that Entry did not have
   319	// children or Next has not been called, SkipChildren is a no-op.
   320	func (r *Reader) SkipChildren() {
   321		if r.err != nil || !r.lastChildren {
   322			return
   323		}
   324	
   325		// If the last entry had a sibling attribute,
   326		// that attribute gives the offset of the next
   327		// sibling, so we can avoid decoding the
   328		// child subtrees.
   329		if r.lastSibling >= r.b.off {
   330			r.Seek(r.lastSibling)
   331			return
   332		}
   333	
   334		for {
   335			e, err := r.Next()
   336			if err != nil || e == nil || e.Tag == 0 {
   337				break
   338			}
   339			if e.Children {
   340				r.SkipChildren()
   341			}
   342		}
   343	}