OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [debug/] [dwarf/] [entry.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.