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 }