...

Source file src/pkg/debug/dwarf/typeunit.go

     1	// Copyright 2012 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	package dwarf
     6	
     7	import (
     8		"fmt"
     9		"strconv"
    10	)
    11	
    12	// Parse the type units stored in a DWARF4 .debug_types section. Each
    13	// type unit defines a single primary type and an 8-byte signature.
    14	// Other sections may then use formRefSig8 to refer to the type.
    15	
    16	// The typeUnit format is a single type with a signature. It holds
    17	// the same data as a compilation unit.
    18	type typeUnit struct {
    19		unit
    20		toff  Offset // Offset to signature type within data.
    21		name  string // Name of .debug_type section.
    22		cache Type   // Cache the type, nil to start.
    23	}
    24	
    25	// Parse a .debug_types section.
    26	func (d *Data) parseTypes(name string, types []byte) error {
    27		b := makeBuf(d, unknownFormat{}, name, 0, types)
    28		for len(b.data) > 0 {
    29			base := b.off
    30			n, dwarf64 := b.unitLength()
    31			if n != Offset(uint32(n)) {
    32				b.error("type unit length overflow")
    33				return b.err
    34			}
    35			hdroff := b.off
    36			vers := int(b.uint16())
    37			if vers != 4 {
    38				b.error("unsupported DWARF version " + strconv.Itoa(vers))
    39				return b.err
    40			}
    41			var ao uint64
    42			if !dwarf64 {
    43				ao = uint64(b.uint32())
    44			} else {
    45				ao = b.uint64()
    46			}
    47			atable, err := d.parseAbbrev(ao, vers)
    48			if err != nil {
    49				return err
    50			}
    51			asize := b.uint8()
    52			sig := b.uint64()
    53	
    54			var toff uint32
    55			if !dwarf64 {
    56				toff = b.uint32()
    57			} else {
    58				to64 := b.uint64()
    59				if to64 != uint64(uint32(to64)) {
    60					b.error("type unit type offset overflow")
    61					return b.err
    62				}
    63				toff = uint32(to64)
    64			}
    65	
    66			boff := b.off
    67			d.typeSigs[sig] = &typeUnit{
    68				unit: unit{
    69					base:   base,
    70					off:    boff,
    71					data:   b.bytes(int(n - (b.off - hdroff))),
    72					atable: atable,
    73					asize:  int(asize),
    74					vers:   vers,
    75					is64:   dwarf64,
    76				},
    77				toff: Offset(toff),
    78				name: name,
    79			}
    80			if b.err != nil {
    81				return b.err
    82			}
    83		}
    84		return nil
    85	}
    86	
    87	// Return the type for a type signature.
    88	func (d *Data) sigToType(sig uint64) (Type, error) {
    89		tu := d.typeSigs[sig]
    90		if tu == nil {
    91			return nil, fmt.Errorf("no type unit with signature %v", sig)
    92		}
    93		if tu.cache != nil {
    94			return tu.cache, nil
    95		}
    96	
    97		b := makeBuf(d, tu, tu.name, tu.off, tu.data)
    98		r := &typeUnitReader{d: d, tu: tu, b: b}
    99		t, err := d.readType(tu.name, r, tu.toff, make(map[Offset]Type), nil)
   100		if err != nil {
   101			return nil, err
   102		}
   103	
   104		tu.cache = t
   105		return t, nil
   106	}
   107	
   108	// typeUnitReader is a typeReader for a tagTypeUnit.
   109	type typeUnitReader struct {
   110		d   *Data
   111		tu  *typeUnit
   112		b   buf
   113		err error
   114	}
   115	
   116	// Seek to a new position in the type unit.
   117	func (tur *typeUnitReader) Seek(off Offset) {
   118		tur.err = nil
   119		doff := off - tur.tu.off
   120		if doff < 0 || doff >= Offset(len(tur.tu.data)) {
   121			tur.err = fmt.Errorf("%s: offset %d out of range; max %d", tur.tu.name, doff, len(tur.tu.data))
   122			return
   123		}
   124		tur.b = makeBuf(tur.d, tur.tu, tur.tu.name, off, tur.tu.data[doff:])
   125	}
   126	
   127	// AddressSize returns the size in bytes of addresses in the current type unit.
   128	func (tur *typeUnitReader) AddressSize() int {
   129		return tur.tu.unit.asize
   130	}
   131	
   132	// Next reads the next Entry from the type unit.
   133	func (tur *typeUnitReader) Next() (*Entry, error) {
   134		if tur.err != nil {
   135			return nil, tur.err
   136		}
   137		if len(tur.tu.data) == 0 {
   138			return nil, nil
   139		}
   140		e := tur.b.entry(tur.tu.atable, tur.tu.base)
   141		if tur.b.err != nil {
   142			tur.err = tur.b.err
   143			return nil, tur.err
   144		}
   145		return e, nil
   146	}
   147	
   148	// clone returns a new reader for the type unit.
   149	func (tur *typeUnitReader) clone() typeReader {
   150		return &typeUnitReader{
   151			d:  tur.d,
   152			tu: tur.tu,
   153			b:  makeBuf(tur.d, tur.tu, tur.tu.name, tur.tu.off, tur.tu.data),
   154		}
   155	}
   156	
   157	// offset returns the current offset.
   158	func (tur *typeUnitReader) offset() Offset {
   159		return tur.b.off
   160	}
   161	

View as plain text