2018-01-29 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / debug / dwarf / typeunit.go
blob76b357ce28b3646ebd9bb5b7c7d8e6c70631f058
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.
5 package dwarf
7 import (
8 "fmt"
9 "strconv"
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.
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.
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
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
41 var ao uint64
42 if !dwarf64 {
43 ao = uint64(b.uint32())
44 } else {
45 ao = b.uint64()
47 atable, err := d.parseAbbrev(ao, vers)
48 if err != nil {
49 return err
51 asize := b.uint8()
52 sig := b.uint64()
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
63 toff = uint32(to64)
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,
77 toff: Offset(toff),
78 name: name,
80 if b.err != nil {
81 return b.err
84 return nil
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)
93 if tu.cache != nil {
94 return tu.cache, nil
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
104 tu.cache = t
105 return t, nil
108 // typeUnitReader is a typeReader for a tagTypeUnit.
109 type typeUnitReader struct {
110 d *Data
111 tu *typeUnit
112 b buf
113 err error
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
124 tur.b = makeBuf(tur.d, tur.tu, tur.tu.name, off, tur.tu.data[doff:])
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
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
137 if len(tur.tu.data) == 0 {
138 return nil, nil
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
145 return e, nil
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),
157 // offset returns the current offset.
158 func (tur *typeUnitReader) offset() Offset {
159 return tur.b.off