Run Format

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, 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	}

View as plain text