...
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 (
    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, formGnuRefAlt, formGnuStrpAlt:
   245				is64, known := b.format.dwarf64()
   246				if !known {
   247					b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
   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	}
   390	
   391	// clone returns a copy of the reader.  This is used by the typeReader
   392	// interface.
   393	func (r *Reader) clone() typeReader {
   394		return r.d.Reader()
   395	}
   396	
   397	// offset returns the current buffer offset.  This is used by the
   398	// typeReader interface.
   399	func (r *Reader) offset() Offset {
   400		return r.b.off
   401	}
   402	

View as plain text